OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |