Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: net/base/x509_certificate.cc

Issue 5242002: Reland 66791 (change was innocent)... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/x509_certificate.h ('k') | net/base/x509_certificate_mac.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/x509_certificate.h" 5 #include "net/base/x509_certificate.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/lazy_instance.h"
9 #include "base/logging.h" 10 #include "base/logging.h"
10 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
11 #include "base/singleton.h"
12 #include "base/string_piece.h" 12 #include "base/string_piece.h"
13 #include "base/time.h" 13 #include "base/time.h"
14 #include "net/base/pem_tokenizer.h" 14 #include "net/base/pem_tokenizer.h"
15 15
16 namespace net { 16 namespace net {
17 17
18 namespace { 18 namespace {
19 19
20 // Returns true if this cert fingerprint is the null (all zero) fingerprint. 20 // Returns true if this cert fingerprint is the null (all zero) fingerprint.
21 // We use this as a bogus fingerprint value. 21 // We use this as a bogus fingerprint value.
(...skipping 10 matching lines...) Expand all
32 const X509Certificate::Format kFormatDecodePriority[] = { 32 const X509Certificate::Format kFormatDecodePriority[] = {
33 X509Certificate::FORMAT_SINGLE_CERTIFICATE, 33 X509Certificate::FORMAT_SINGLE_CERTIFICATE,
34 X509Certificate::FORMAT_PKCS7 34 X509Certificate::FORMAT_PKCS7
35 }; 35 };
36 36
37 // The PEM block header used for DER certificates 37 // The PEM block header used for DER certificates
38 const char kCertificateHeader[] = "CERTIFICATE"; 38 const char kCertificateHeader[] = "CERTIFICATE";
39 // The PEM block header used for PKCS#7 data 39 // The PEM block header used for PKCS#7 data
40 const char kPKCS7Header[] = "PKCS7"; 40 const char kPKCS7Header[] = "PKCS7";
41 41
42 } // namespace
43
44 bool X509Certificate::LessThan::operator()(X509Certificate* lhs,
45 X509Certificate* rhs) const {
46 if (lhs == rhs)
47 return false;
48
49 SHA1FingerprintLessThan fingerprint_functor;
50 return fingerprint_functor(lhs->fingerprint_, rhs->fingerprint_);
51 }
52
53 // A thread-safe cache for X509Certificate objects. 42 // A thread-safe cache for X509Certificate objects.
54 // 43 //
55 // The cache does not hold a reference to the certificate objects. The objects 44 // The cache does not hold a reference to the certificate objects. The objects
56 // must |Remove| themselves from the cache upon destruction (or else the cache 45 // must |Remove| themselves from the cache upon destruction (or else the cache
57 // will be holding dead pointers to the objects). 46 // will be holding dead pointers to the objects).
58 // TODO(rsleevi): There exists a chance of a use-after-free, due to a race 47 // TODO(rsleevi): There exists a chance of a use-after-free, due to a race
59 // between Find() and Remove(). See http://crbug.com/49377 48 // between Find() and Remove(). See http://crbug.com/49377
60 class X509Certificate::Cache { 49 class X509CertificateCache {
61 public: 50 public:
62 static Cache* GetInstance();
63 void Insert(X509Certificate* cert); 51 void Insert(X509Certificate* cert);
64 void Remove(X509Certificate* cert); 52 void Remove(X509Certificate* cert);
65 X509Certificate* Find(const SHA1Fingerprint& fingerprint); 53 X509Certificate* Find(const SHA1Fingerprint& fingerprint);
66 54
67 private: 55 private:
68 typedef std::map<SHA1Fingerprint, X509Certificate*, SHA1FingerprintLessThan> 56 typedef std::map<SHA1Fingerprint, X509Certificate*, SHA1FingerprintLessThan>
69 CertMap; 57 CertMap;
70 58
71 // Obtain an instance of X509Certificate::Cache via GetInstance(). 59 // Obtain an instance of X509CertificateCache via a LazyInstance.
72 Cache() {} 60 X509CertificateCache() {}
73 friend struct DefaultSingletonTraits<Cache>; 61 ~X509CertificateCache() {}
62 friend struct base::DefaultLazyInstanceTraits<X509CertificateCache>;
74 63
75 // You must acquire this lock before using any private data of this object. 64 // You must acquire this lock before using any private data of this object.
76 // You must not block while holding this lock. 65 // You must not block while holding this lock.
77 Lock lock_; 66 Lock lock_;
78 67
79 // The certificate cache. You must acquire |lock_| before using |cache_|. 68 // The certificate cache. You must acquire |lock_| before using |cache_|.
80 CertMap cache_; 69 CertMap cache_;
81 70
82 DISALLOW_COPY_AND_ASSIGN(Cache); 71 DISALLOW_COPY_AND_ASSIGN(X509CertificateCache);
83 }; 72 };
84 73
85 // Get the singleton object for the cache. 74 base::LazyInstance<X509CertificateCache,
86 // static 75 base::LeakyLazyInstanceTraits<X509CertificateCache> >
87 X509Certificate::Cache* X509Certificate::Cache::GetInstance() { 76 g_x509_certificate_cache(base::LINKER_INITIALIZED);
88 return Singleton<X509Certificate::Cache>::get();
89 }
90 77
91 // Insert |cert| into the cache. The cache does NOT AddRef |cert|. 78 // Insert |cert| into the cache. The cache does NOT AddRef |cert|.
92 // Any existing certificate with the same fingerprint will be replaced. 79 // Any existing certificate with the same fingerprint will be replaced.
93 void X509Certificate::Cache::Insert(X509Certificate* cert) { 80 void X509CertificateCache::Insert(X509Certificate* cert) {
94 AutoLock lock(lock_); 81 AutoLock lock(lock_);
95 82
96 DCHECK(!IsNullFingerprint(cert->fingerprint())) << 83 DCHECK(!IsNullFingerprint(cert->fingerprint())) <<
97 "Only insert certs with real fingerprints."; 84 "Only insert certs with real fingerprints.";
98 cache_[cert->fingerprint()] = cert; 85 cache_[cert->fingerprint()] = cert;
99 }; 86 };
100 87
101 // Remove |cert| from the cache. The cache does not assume that |cert| is 88 // Remove |cert| from the cache. The cache does not assume that |cert| is
102 // already in the cache. 89 // already in the cache.
103 void X509Certificate::Cache::Remove(X509Certificate* cert) { 90 void X509CertificateCache::Remove(X509Certificate* cert) {
104 AutoLock lock(lock_); 91 AutoLock lock(lock_);
105 92
106 CertMap::iterator pos(cache_.find(cert->fingerprint())); 93 CertMap::iterator pos(cache_.find(cert->fingerprint()));
107 if (pos == cache_.end()) 94 if (pos == cache_.end())
108 return; // It is not an error to remove a cert that is not in the cache. 95 return; // It is not an error to remove a cert that is not in the cache.
109 cache_.erase(pos); 96 cache_.erase(pos);
110 }; 97 };
111 98
112 // Find a certificate in the cache with the given fingerprint. If one does 99 // Find a certificate in the cache with the given fingerprint. If one does
113 // not exist, this method returns NULL. 100 // not exist, this method returns NULL.
114 X509Certificate* X509Certificate::Cache::Find( 101 X509Certificate* X509CertificateCache::Find(
115 const SHA1Fingerprint& fingerprint) { 102 const SHA1Fingerprint& fingerprint) {
116 AutoLock lock(lock_); 103 AutoLock lock(lock_);
117 104
118 CertMap::iterator pos(cache_.find(fingerprint)); 105 CertMap::iterator pos(cache_.find(fingerprint));
119 if (pos == cache_.end()) 106 if (pos == cache_.end())
120 return NULL; 107 return NULL;
121 108
122 return pos->second; 109 return pos->second;
123 }; 110 };
124 111
112 } // namespace
113
114 bool X509Certificate::LessThan::operator()(X509Certificate* lhs,
115 X509Certificate* rhs) const {
116 if (lhs == rhs)
117 return false;
118
119 SHA1FingerprintLessThan fingerprint_functor;
120 return fingerprint_functor(lhs->fingerprint_, rhs->fingerprint_);
121 }
122
125 // static 123 // static
126 X509Certificate* X509Certificate::CreateFromHandle( 124 X509Certificate* X509Certificate::CreateFromHandle(
127 OSCertHandle cert_handle, 125 OSCertHandle cert_handle,
128 Source source, 126 Source source,
129 const OSCertHandles& intermediates) { 127 const OSCertHandles& intermediates) {
130 DCHECK(cert_handle); 128 DCHECK(cert_handle);
131 DCHECK(source != SOURCE_UNUSED); 129 DCHECK(source != SOURCE_UNUSED);
132 130
133 // Check if we already have this certificate in memory. 131 // Check if we already have this certificate in memory.
134 X509Certificate::Cache* cache = X509Certificate::Cache::GetInstance(); 132 X509CertificateCache* cache = g_x509_certificate_cache.Pointer();
135 X509Certificate* cached_cert = 133 X509Certificate* cached_cert =
136 cache->Find(CalculateFingerprint(cert_handle)); 134 cache->Find(CalculateFingerprint(cert_handle));
137 if (cached_cert) { 135 if (cached_cert) {
138 DCHECK(cached_cert->source_ != SOURCE_UNUSED); 136 DCHECK(cached_cert->source_ != SOURCE_UNUSED);
139 if (cached_cert->source_ > source || 137 if (cached_cert->source_ > source ||
140 (cached_cert->source_ == source && 138 (cached_cert->source_ == source &&
141 cached_cert->HasIntermediateCertificates(intermediates))) { 139 cached_cert->HasIntermediateCertificates(intermediates))) {
142 // Return the certificate with the same fingerprint from our cache. 140 // Return the certificate with the same fingerprint from our cache.
143 DHISTOGRAM_COUNTS("X509CertificateReuseCount", 1); 141 DHISTOGRAM_COUNTS("X509CertificateReuseCount", 1);
144 return cached_cert; 142 return cached_cert;
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 issuer_(issuer), 302 issuer_(issuer),
305 valid_start_(start_date), 303 valid_start_(start_date),
306 valid_expiry_(expiration_date), 304 valid_expiry_(expiration_date),
307 cert_handle_(NULL), 305 cert_handle_(NULL),
308 source_(SOURCE_UNUSED) { 306 source_(SOURCE_UNUSED) {
309 memset(fingerprint_.data, 0, sizeof(fingerprint_.data)); 307 memset(fingerprint_.data, 0, sizeof(fingerprint_.data));
310 } 308 }
311 309
312 X509Certificate::~X509Certificate() { 310 X509Certificate::~X509Certificate() {
313 // We might not be in the cache, but it is safe to remove ourselves anyway. 311 // We might not be in the cache, but it is safe to remove ourselves anyway.
314 X509Certificate::Cache::GetInstance()->Remove(this); 312 g_x509_certificate_cache.Get().Remove(this);
315 if (cert_handle_) 313 if (cert_handle_)
316 FreeOSCertHandle(cert_handle_); 314 FreeOSCertHandle(cert_handle_);
317 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) 315 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i)
318 FreeOSCertHandle(intermediate_ca_certs_[i]); 316 FreeOSCertHandle(intermediate_ca_certs_[i]);
319 } 317 }
320 318
321 bool X509Certificate::HasExpired() const { 319 bool X509Certificate::HasExpired() const {
322 return base::Time::Now() > valid_expiry(); 320 return base::Time::Now() > valid_expiry();
323 } 321 }
324 322
(...skipping 15 matching lines...) Expand all
340 338
341 bool X509Certificate::HasIntermediateCertificates(const OSCertHandles& certs) { 339 bool X509Certificate::HasIntermediateCertificates(const OSCertHandles& certs) {
342 for (size_t i = 0; i < certs.size(); ++i) { 340 for (size_t i = 0; i < certs.size(); ++i) {
343 if (!HasIntermediateCertificate(certs[i])) 341 if (!HasIntermediateCertificate(certs[i]))
344 return false; 342 return false;
345 } 343 }
346 return true; 344 return true;
347 } 345 }
348 346
349 } // namespace net 347 } // namespace net
OLDNEW
« no previous file with comments | « net/base/x509_certificate.h ('k') | net/base/x509_certificate_mac.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698