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 #if defined(OS_MACOSX) | 7 #if defined(OS_MACOSX) |
8 #include <Security/Security.h> | 8 #include <Security/Security.h> |
9 #elif defined(USE_NSS) | 9 #elif defined(USE_NSS) |
10 #include <cert.h> | 10 #include <cert.h> |
11 #endif | 11 #endif |
12 | 12 |
| 13 #include <map> |
| 14 |
13 #include "base/histogram.h" | 15 #include "base/histogram.h" |
14 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/singleton.h" |
15 #include "base/time.h" | 18 #include "base/time.h" |
16 | 19 |
17 namespace net { | 20 namespace net { |
18 | 21 |
19 namespace { | 22 namespace { |
20 | 23 |
21 // Returns true if this cert fingerprint is the null (all zero) fingerprint. | 24 // Returns true if this cert fingerprint is the null (all zero) fingerprint. |
22 // We use this as a bogus fingerprint value. | 25 // We use this as a bogus fingerprint value. |
23 bool IsNullFingerprint(const X509Certificate::Fingerprint& fingerprint) { | 26 bool IsNullFingerprint(const SHA1Fingerprint& fingerprint) { |
24 for (size_t i = 0; i < arraysize(fingerprint.data); ++i) { | 27 for (size_t i = 0; i < arraysize(fingerprint.data); ++i) { |
25 if (fingerprint.data[i] != 0) | 28 if (fingerprint.data[i] != 0) |
26 return false; | 29 return false; |
27 } | 30 } |
28 return true; | 31 return true; |
29 } | 32 } |
30 | 33 |
31 } // namespace | 34 } // namespace |
32 | 35 |
33 // static | 36 // static |
(...skipping 16 matching lines...) Expand all Loading... |
50 #elif defined(USE_NSS) | 53 #elif defined(USE_NSS) |
51 return a->derCert.len == b->derCert.len && | 54 return a->derCert.len == b->derCert.len && |
52 memcmp(a->derCert.data, b->derCert.data, a->derCert.len) == 0; | 55 memcmp(a->derCert.data, b->derCert.data, a->derCert.len) == 0; |
53 #else | 56 #else |
54 // TODO(snej): not implemented | 57 // TODO(snej): not implemented |
55 UNREACHED(); | 58 UNREACHED(); |
56 return false; | 59 return false; |
57 #endif | 60 #endif |
58 } | 61 } |
59 | 62 |
60 bool X509Certificate::FingerprintLessThan::operator()( | |
61 const SHA1Fingerprint& lhs, | |
62 const SHA1Fingerprint& rhs) const { | |
63 for (size_t i = 0; i < sizeof(lhs.data); ++i) { | |
64 if (lhs.data[i] < rhs.data[i]) | |
65 return true; | |
66 if (lhs.data[i] > rhs.data[i]) | |
67 return false; | |
68 } | |
69 return false; | |
70 } | |
71 | |
72 bool X509Certificate::LessThan::operator()(X509Certificate* lhs, | 63 bool X509Certificate::LessThan::operator()(X509Certificate* lhs, |
73 X509Certificate* rhs) const { | 64 X509Certificate* rhs) const { |
74 if (lhs == rhs) | 65 if (lhs == rhs) |
75 return false; | 66 return false; |
76 | 67 |
77 X509Certificate::FingerprintLessThan fingerprint_functor; | 68 SHA1FingerprintLessThan fingerprint_functor; |
78 return fingerprint_functor(lhs->fingerprint_, rhs->fingerprint_); | 69 return fingerprint_functor(lhs->fingerprint_, rhs->fingerprint_); |
79 } | 70 } |
80 | 71 |
81 // A thread-safe cache for X509Certificate objects. | 72 // A thread-safe cache for X509Certificate objects. |
82 // | 73 // |
83 // The cache does not hold a reference to the certificate objects. The objects | 74 // The cache does not hold a reference to the certificate objects. The objects |
84 // must |Remove| themselves from the cache upon destruction (or else the cache | 75 // must |Remove| themselves from the cache upon destruction (or else the cache |
85 // will be holding dead pointers to the objects). | 76 // will be holding dead pointers to the objects). |
| 77 // TODO(rsleevi): Fix the cache to hold references, as there is a race where: |
| 78 // Thread A: Release the last reference to an X509Certificate. |
| 79 // Thread B: Calls Find(), which acquires |lock_| |
| 80 // Thread A: X509Certificate DTOR invokes, and calls Remove(), which blocks |
| 81 // on |lock_| |
| 82 // Thread B: Finds the X509Certificate (that is DTORing in Thread A) and |
| 83 // returns it, releasing |lock_| |
| 84 // Thread A: Acquires |lock_|, removes the X509Certificate, and then |
| 85 // proceeds with DTOR |
| 86 // Thread B: Now holds a dead pointer |
| 87 class X509Certificate::Cache { |
| 88 public: |
| 89 static Cache* GetInstance(); |
| 90 void Insert(X509Certificate* cert); |
| 91 void Remove(X509Certificate* cert); |
| 92 X509Certificate* Find(const SHA1Fingerprint& fingerprint); |
| 93 |
| 94 private: |
| 95 typedef std::map<SHA1Fingerprint, X509Certificate*, SHA1FingerprintLessThan> |
| 96 CertMap; |
| 97 |
| 98 // Obtain an instance of X509Certificate::Cache via GetInstance(). |
| 99 Cache() {} |
| 100 friend struct DefaultSingletonTraits<Cache>; |
| 101 |
| 102 // You must acquire this lock before using any private data of this object. |
| 103 // You must not block while holding this lock. |
| 104 Lock lock_; |
| 105 |
| 106 // The certificate cache. You must acquire |lock_| before using |cache_|. |
| 107 CertMap cache_; |
| 108 |
| 109 DISALLOW_COPY_AND_ASSIGN(Cache); |
| 110 }; |
86 | 111 |
87 // Get the singleton object for the cache. | 112 // Get the singleton object for the cache. |
88 // static | 113 // static |
89 X509Certificate::Cache* X509Certificate::Cache::GetInstance() { | 114 X509Certificate::Cache* X509Certificate::Cache::GetInstance() { |
90 return Singleton<X509Certificate::Cache>::get(); | 115 return Singleton<X509Certificate::Cache>::get(); |
91 } | 116 } |
92 | 117 |
93 // Insert |cert| into the cache. The cache does NOT AddRef |cert|. | 118 // Insert |cert| into the cache. The cache does NOT AddRef |cert|. |
94 // Any existing certificate with the same fingerprint will be replaced. | 119 // Any existing certificate with the same fingerprint will be replaced. |
95 void X509Certificate::Cache::Insert(X509Certificate* cert) { | 120 void X509Certificate::Cache::Insert(X509Certificate* cert) { |
(...skipping 10 matching lines...) Expand all Loading... |
106 AutoLock lock(lock_); | 131 AutoLock lock(lock_); |
107 | 132 |
108 CertMap::iterator pos(cache_.find(cert->fingerprint())); | 133 CertMap::iterator pos(cache_.find(cert->fingerprint())); |
109 if (pos == cache_.end()) | 134 if (pos == cache_.end()) |
110 return; // It is not an error to remove a cert that is not in the cache. | 135 return; // It is not an error to remove a cert that is not in the cache. |
111 cache_.erase(pos); | 136 cache_.erase(pos); |
112 }; | 137 }; |
113 | 138 |
114 // Find a certificate in the cache with the given fingerprint. If one does | 139 // Find a certificate in the cache with the given fingerprint. If one does |
115 // not exist, this method returns NULL. | 140 // not exist, this method returns NULL. |
116 X509Certificate* X509Certificate::Cache::Find(const Fingerprint& fingerprint) { | 141 X509Certificate* X509Certificate::Cache::Find( |
| 142 const SHA1Fingerprint& fingerprint) { |
117 AutoLock lock(lock_); | 143 AutoLock lock(lock_); |
118 | 144 |
119 CertMap::iterator pos(cache_.find(fingerprint)); | 145 CertMap::iterator pos(cache_.find(fingerprint)); |
120 if (pos == cache_.end()) | 146 if (pos == cache_.end()) |
121 return NULL; | 147 return NULL; |
122 | 148 |
123 return pos->second; | 149 return pos->second; |
124 }; | 150 }; |
125 | 151 |
126 // static | 152 // static |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 | 250 |
225 bool X509Certificate::HasIntermediateCertificates(const OSCertHandles& certs) { | 251 bool X509Certificate::HasIntermediateCertificates(const OSCertHandles& certs) { |
226 for (size_t i = 0; i < certs.size(); ++i) { | 252 for (size_t i = 0; i < certs.size(); ++i) { |
227 if (!HasIntermediateCertificate(certs[i])) | 253 if (!HasIntermediateCertificate(certs[i])) |
228 return false; | 254 return false; |
229 } | 255 } |
230 return true; | 256 return true; |
231 } | 257 } |
232 | 258 |
233 } // namespace net | 259 } // namespace net |
OLD | NEW |