| 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 |