diff options
Diffstat (limited to 'net/base')
-rw-r--r-- | net/base/x509_certificate.cc | 92 | ||||
-rw-r--r-- | net/base/x509_certificate.h | 38 | ||||
-rw-r--r-- | net/base/x509_certificate_mac.cc | 14 | ||||
-rw-r--r-- | net/base/x509_certificate_nss.cc | 9 | ||||
-rw-r--r-- | net/base/x509_certificate_unittest.cc | 70 | ||||
-rw-r--r-- | net/base/x509_certificate_win.cc | 13 |
6 files changed, 42 insertions, 194 deletions
diff --git a/net/base/x509_certificate.cc b/net/base/x509_certificate.cc index 700b254..24388d8 100644 --- a/net/base/x509_certificate.cc +++ b/net/base/x509_certificate.cc @@ -4,10 +4,6 @@ #include "net/base/x509_certificate.h" -#if defined(USE_NSS) -#include <cert.h> -#endif - #include "base/histogram.h" #include "base/logging.h" #include "base/time.h" @@ -28,33 +24,6 @@ bool IsNullFingerprint(const X509Certificate::Fingerprint& fingerprint) { } // namespace -// static -bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, - X509Certificate::OSCertHandle b) { - DCHECK(a && b); - if (a == b) - return true; -#if defined(OS_WIN) - return a->cbCertEncoded == b->cbCertEncoded && - memcmp(a->pbCertEncoded, b->pbCertEncoded, a->cbCertEncoded) == 0; -#elif defined(OS_MACOSX) - if (CFEqual(a, b)) - return true; - CSSM_DATA a_data, b_data; - return SecCertificateGetData(a, &a_data) == noErr && - SecCertificateGetData(b, &b_data) == noErr && - a_data.Length == b_data.Length && - memcmp(a_data.Data, b_data.Data, a_data.Length) == 0; -#elif defined(USE_NSS) - return a->derCert.len == b->derCert.len && - memcmp(a->derCert.data, b->derCert.data, a->derCert.len) == 0; -#else - // TODO(snej): not implemented - UNREACHED(); - return false; -#endif -} - bool X509Certificate::FingerprintLessThan::operator()( const Fingerprint& lhs, const Fingerprint& rhs) const { @@ -88,13 +57,14 @@ X509Certificate::Cache* X509Certificate::Cache::GetInstance() { return Singleton<X509Certificate::Cache>::get(); } -// Insert |cert| into the cache. The cache does NOT AddRef |cert|. -// Any existing certificate with the same fingerprint will be replaced. +// Insert |cert| into the cache. The cache does NOT AddRef |cert|. The cache +// must not already contain a certificate with the same fingerprint. void X509Certificate::Cache::Insert(X509Certificate* cert) { AutoLock lock(lock_); DCHECK(!IsNullFingerprint(cert->fingerprint())) << "Only insert certs with real fingerprints."; + DCHECK(cache_.find(cert->fingerprint()) == cache_.end()); cache_[cert->fingerprint()] = cert; }; @@ -163,10 +133,8 @@ bool X509Certificate::Policy::HasDeniedCert() const { } // static -X509Certificate* X509Certificate::CreateFromHandle( - OSCertHandle cert_handle, - Source source, - const OSCertHandles& intermediates) { +X509Certificate* X509Certificate::CreateFromHandle(OSCertHandle cert_handle, + Source source) { DCHECK(cert_handle); DCHECK(source != SOURCE_UNUSED); @@ -176,20 +144,18 @@ X509Certificate* X509Certificate::CreateFromHandle( cache->Find(CalculateFingerprint(cert_handle)); if (cached_cert) { DCHECK(cached_cert->source_ != SOURCE_UNUSED); - if (cached_cert->source_ > source || - (cached_cert->source_ == source && - cached_cert->HasIntermediateCertificates(intermediates))) { - // Return the certificate with the same fingerprint from our cache. - // But we own the input OSCertHandle, which makes it our job to free it. + if (cached_cert->source_ >= source) { + // We've found a certificate with the same fingerprint in our cache. We + // own the |cert_handle|, which makes it our job to free it. FreeOSCertHandle(cert_handle); DHISTOGRAM_COUNTS("X509CertificateReuseCount", 1); return cached_cert; } - // Else the new cert is better and will replace the old one in the cache. + // Kick out the old certificate from our cache. The new one is better. + cache->Remove(cached_cert); } - // Otherwise, allocate a new object. - return new X509Certificate(cert_handle, source, intermediates); + return new X509Certificate(cert_handle, source); } // static @@ -199,25 +165,13 @@ X509Certificate* X509Certificate::CreateFromBytes(const char* data, if (!cert_handle) return NULL; - return CreateFromHandle(cert_handle, - SOURCE_LONE_CERT_IMPORT, - OSCertHandles()); + return CreateFromHandle(cert_handle, SOURCE_LONE_CERT_IMPORT); } -X509Certificate::X509Certificate(OSCertHandle cert_handle, - Source source, - const OSCertHandles& intermediates) +X509Certificate::X509Certificate(OSCertHandle cert_handle, Source source) : cert_handle_(cert_handle), source_(source) { -#if defined(OS_MACOSX) || defined(OS_WIN) - // Copy/retain the intermediate cert handles. - for (size_t i = 0; i < intermediates.size(); ++i) - intermediate_ca_certs_.push_back(DupOSCertHandle(intermediates[i])); -#endif - // Platform-specific initialization. Initialize(); - // Store the certificate in the cache in case we need it later. - X509Certificate::Cache::GetInstance()->Insert(this); } X509Certificate::X509Certificate(const std::string& subject, @@ -248,24 +202,4 @@ bool X509Certificate::HasExpired() const { return base::Time::Now() > valid_expiry(); } -bool X509Certificate::HasIntermediateCertificate(OSCertHandle cert) { -#if defined(OS_MACOSX) || defined(OS_WIN) - for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) { - if (IsSameOSCert(cert, intermediate_ca_certs_[i])) - return true; - } - return false; -#else - return true; -#endif -} - -bool X509Certificate::HasIntermediateCertificates(const OSCertHandles& certs) { - for (size_t i = 0; i < certs.size(); ++i) { - if (!HasIntermediateCertificate(certs[i])) - return false; - } - return true; -} - } // namespace net diff --git a/net/base/x509_certificate.h b/net/base/x509_certificate.h index ec287ce..f3f3fea 100644 --- a/net/base/x509_certificate.h +++ b/net/base/x509_certificate.h @@ -72,8 +72,6 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> { typedef void* OSCertHandle; #endif - typedef std::vector<OSCertHandle> OSCertHandles; - // Principal represent an X.509 principal. struct Principal { Principal() { } @@ -154,11 +152,10 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> { // prefers the handle from the network because our HTTP cache isn't // caching the corresponding intermediate CA certificates yet // (http://crbug.com/7065). - // The list of intermediate certificates is ignored under NSS (i.e. Linux.) + // // The returned pointer must be stored in a scoped_refptr<X509Certificate>. static X509Certificate* CreateFromHandle(OSCertHandle cert_handle, - Source source, - const OSCertHandles& intermediates); + Source source); // Create an X509Certificate from the BER-encoded representation. // Returns NULL on failure. @@ -213,20 +210,20 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> { bool HasExpired() const; #if defined(OS_MACOSX) || defined(OS_WIN) + // Adds an untrusted intermediate certificate that may be needed for + // chain building. + void AddIntermediateCertificate(OSCertHandle cert) { + intermediate_ca_certs_.push_back(cert); + } + // Returns intermediate certificates added via AddIntermediateCertificate(). // Ownership follows the "get" rule: it is the caller's responsibility to // retain the elements of the result. - const OSCertHandles& GetIntermediateCertificates() const { + const std::vector<OSCertHandle>& GetIntermediateCertificates() const { return intermediate_ca_certs_; } #endif - // Returns true if I already contain the given intermediate cert. - bool HasIntermediateCertificate(OSCertHandle cert); - - // Returns true if I already contain all the given intermediate certs. - bool HasIntermediateCertificates(const OSCertHandles& certs); - #if defined(OS_MACOSX) // Does this certificate's usage allow SSL client authentication? bool SupportsSSLClientAuth() const; @@ -265,14 +262,9 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> { OSCertHandle os_cert_handle() const { return cert_handle_; } - // Returns true if two OSCertHandles refer to identical certificates. - static bool IsSameOSCert(OSCertHandle a, OSCertHandle b); - - private: friend class base::RefCountedThreadSafe<X509Certificate>; FRIEND_TEST(X509CertificateTest, Cache); - FRIEND_TEST(X509CertificateTest, IntermediateCertificates); // A cache of X509Certificate objects. class Cache { @@ -302,8 +294,7 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> { // Construct an X509Certificate from a handle to the certificate object // in the underlying crypto library. - X509Certificate(OSCertHandle cert_handle, Source source, - const OSCertHandles& intermediates); + X509Certificate(OSCertHandle cert_handle, Source source); ~X509Certificate(); @@ -317,10 +308,7 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> { static OSCertHandle CreateOSCertHandleFromBytes(const char* data, int length); - // Duplicates (or adds a reference to) an OS certificate handle. - static OSCertHandle DupOSCertHandle(OSCertHandle cert_handle); - - // Frees (or releases a reference to) an OS certificate handle. + // Frees an OS certificate handle. static void FreeOSCertHandle(OSCertHandle cert_handle); // Calculates the SHA-1 fingerprint of the certificate. Returns an empty @@ -347,8 +335,8 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> { #if defined(OS_MACOSX) || defined(OS_WIN) // Untrusted intermediate certificates associated with this certificate - // that may be needed for chain building. (NSS impl does not need these.) - OSCertHandles intermediate_ca_certs_; + // that may be needed for chain building. + std::vector<OSCertHandle> intermediate_ca_certs_; #endif // Where the certificate comes from. diff --git a/net/base/x509_certificate_mac.cc b/net/base/x509_certificate_mac.cc index fa1c17e0..36fc65a 100644 --- a/net/base/x509_certificate_mac.cc +++ b/net/base/x509_certificate_mac.cc @@ -405,6 +405,9 @@ void X509Certificate::Initialize() { &valid_expiry_); fingerprint_ = CalculateFingerprint(cert_handle_); + + // Store the certificate in the cache in case we need it later. + X509Certificate::Cache::GetInstance()->Insert(this); } // static @@ -686,14 +689,6 @@ X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( } // static -X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( - OSCertHandle handle) { - if (!handle) - return NULL; - return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); -} - -// static void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { CFRelease(cert_handle); } @@ -790,8 +785,7 @@ bool X509Certificate::GetSSLClientCertificates ( continue; scoped_refptr<X509Certificate> cert( - CreateFromHandle(cert_handle, SOURCE_LONE_CERT_IMPORT, - OSCertHandles())); + CreateFromHandle(cert_handle, SOURCE_LONE_CERT_IMPORT)); // cert_handle is adoped by cert, so I don't need to release it myself. if (cert->HasExpired() || !cert->SupportsSSLClientAuth()) continue; diff --git a/net/base/x509_certificate_nss.cc b/net/base/x509_certificate_nss.cc index 705690a..b25688e 100644 --- a/net/base/x509_certificate_nss.cc +++ b/net/base/x509_certificate_nss.cc @@ -472,6 +472,9 @@ void X509Certificate::Initialize() { ParseDate(&cert_handle_->validity.notAfter, &valid_expiry_); fingerprint_ = CalculateFingerprint(cert_handle_); + + // Store the certificate in the cache in case we need it later. + X509Certificate::Cache::GetInstance()->Insert(this); } // static @@ -627,12 +630,6 @@ X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( } // static -X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( - OSCertHandle cert_handle) { - return CERT_DupCertificate(cert_handle); -} - -// static void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { CERT_DestroyCertificate(cert_handle); } diff --git a/net/base/x509_certificate_unittest.cc b/net/base/x509_certificate_unittest.cc index 7081f1ad..7904cf0 100644 --- a/net/base/x509_certificate_unittest.cc +++ b/net/base/x509_certificate_unittest.cc @@ -309,16 +309,14 @@ TEST(X509CertificateTest, Cache) { google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes( reinterpret_cast<const char*>(google_der), sizeof(google_der)); scoped_refptr<X509Certificate> cert1 = X509Certificate::CreateFromHandle( - google_cert_handle, X509Certificate::SOURCE_LONE_CERT_IMPORT, - X509Certificate::OSCertHandles()); + google_cert_handle, X509Certificate::SOURCE_LONE_CERT_IMPORT); // Add a certificate from the same source (SOURCE_LONE_CERT_IMPORT). This // should return the cached certificate (cert1). google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes( reinterpret_cast<const char*>(google_der), sizeof(google_der)); scoped_refptr<X509Certificate> cert2 = X509Certificate::CreateFromHandle( - google_cert_handle, X509Certificate::SOURCE_LONE_CERT_IMPORT, - X509Certificate::OSCertHandles()); + google_cert_handle, X509Certificate::SOURCE_LONE_CERT_IMPORT); EXPECT_EQ(cert1, cert2); @@ -327,8 +325,7 @@ TEST(X509CertificateTest, Cache) { google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes( reinterpret_cast<const char*>(google_der), sizeof(google_der)); scoped_refptr<X509Certificate> cert3 = X509Certificate::CreateFromHandle( - google_cert_handle, X509Certificate::SOURCE_FROM_NETWORK, - X509Certificate::OSCertHandles()); + google_cert_handle, X509Certificate::SOURCE_FROM_NETWORK); EXPECT_NE(cert1, cert3); @@ -337,16 +334,14 @@ TEST(X509CertificateTest, Cache) { google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes( reinterpret_cast<const char*>(google_der), sizeof(google_der)); scoped_refptr<X509Certificate> cert4 = X509Certificate::CreateFromHandle( - google_cert_handle, X509Certificate::SOURCE_FROM_NETWORK, - X509Certificate::OSCertHandles()); + google_cert_handle, X509Certificate::SOURCE_FROM_NETWORK); EXPECT_EQ(cert3, cert4); google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes( reinterpret_cast<const char*>(google_der), sizeof(google_der)); scoped_refptr<X509Certificate> cert5 = X509Certificate::CreateFromHandle( - google_cert_handle, X509Certificate::SOURCE_FROM_NETWORK, - X509Certificate::OSCertHandles()); + google_cert_handle, X509Certificate::SOURCE_FROM_NETWORK); EXPECT_EQ(cert3, cert5); } @@ -401,59 +396,4 @@ TEST(X509CertificateTest, Policy) { EXPECT_TRUE(policy.HasDeniedCert()); } -#if defined(OS_MACOSX) || defined(OS_WIN) -TEST(X509CertificateTest, IntermediateCertificates) { - X509Certificate::OSCertHandle handle1, handle2, handle3, handle4; - - // Create object with no intermediates: - handle1 = X509Certificate::CreateOSCertHandleFromBytes( - reinterpret_cast<const char*>(google_der), sizeof(google_der)); - X509Certificate::OSCertHandles intermediates1; - scoped_refptr<X509Certificate> cert1; - cert1 = X509Certificate::CreateFromHandle(handle1, - X509Certificate::SOURCE_FROM_NETWORK, - intermediates1); - EXPECT_TRUE(cert1->HasIntermediateCertificates(intermediates1)); - handle2 = X509Certificate::CreateOSCertHandleFromBytes( - reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der)); - EXPECT_FALSE(cert1->HasIntermediateCertificate(handle2)); - - // Create object with 2 intermediates: - handle1 = X509Certificate::CreateOSCertHandleFromBytes( - reinterpret_cast<const char*>(google_der), sizeof(google_der)); - X509Certificate::OSCertHandles intermediates2; - handle3 = X509Certificate::CreateOSCertHandleFromBytes( - reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der)); - intermediates2.push_back(handle2); - intermediates2.push_back(handle3); - scoped_refptr<X509Certificate> cert2; - cert2 = X509Certificate::CreateFromHandle(handle1, - X509Certificate::SOURCE_FROM_NETWORK, - intermediates2); - - // The cache should have stored cert2 'cause it has more intermediates: - EXPECT_NE(cert1, cert2); - - // Verify it has all the intermediates: - EXPECT_TRUE(cert2->HasIntermediateCertificate(handle2)); - EXPECT_TRUE(cert2->HasIntermediateCertificate(handle3)); - handle4 = X509Certificate::CreateOSCertHandleFromBytes( - reinterpret_cast<const char*>(paypal_null_der), sizeof(paypal_null_der)); - EXPECT_FALSE(cert2->HasIntermediateCertificate(handle4)); - - // Create object with 1 intermediate: - handle3 = X509Certificate::CreateOSCertHandleFromBytes( - reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der)); - X509Certificate::OSCertHandles intermediates3; - intermediates2.push_back(handle3); - scoped_refptr<X509Certificate> cert3; - cert3 = X509Certificate::CreateFromHandle(handle1, - X509Certificate::SOURCE_FROM_NETWORK, - intermediates3); - - // The cache should have returned cert2 'cause it has more intermediates: - EXPECT_EQ(cert3, cert2); -} -#endif - } // namespace net diff --git a/net/base/x509_certificate_win.cc b/net/base/x509_certificate_win.cc index 7f3f09e..df43814 100644 --- a/net/base/x509_certificate_win.cc +++ b/net/base/x509_certificate_win.cc @@ -463,6 +463,9 @@ void X509Certificate::Initialize() { valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter); fingerprint_ = CalculateFingerprint(cert_handle_); + + // Store the certificate in the cache in case we need it later. + X509Certificate::Cache::GetInstance()->Insert(this); } // static @@ -481,8 +484,7 @@ X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, NULL, reinterpret_cast<const void **>(&cert_handle))) return NULL; - return CreateFromHandle(cert_handle, SOURCE_LONE_CERT_IMPORT, - OSCertHandles()); + return CreateFromHandle(cert_handle, SOURCE_LONE_CERT_IMPORT); } void X509Certificate::Persist(Pickle* pickle) { @@ -744,13 +746,6 @@ X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( return cert_handle; } - -// static -X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( - OSCertHandle cert_handle) { - return CertDuplicateCertificateContext(cert_handle); -} - // static void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { CertFreeCertificateContext(cert_handle); |