diff options
author | snej@chromium.org <snej@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-05 17:17:57 +0000 |
---|---|---|
committer | snej@chromium.org <snej@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-05 17:17:57 +0000 |
commit | 207c678c4692c9dfec3e34c0d206f2ee1b2fbb6a (patch) | |
tree | a2017eddab0bbb8713ddfd9c1473dd81e557ec4f /net | |
parent | 76964955a0fc995d7a0c95feaeaa17891eab2205 (diff) | |
download | chromium_src-207c678c4692c9dfec3e34c0d206f2ee1b2fbb6a.zip chromium_src-207c678c4692c9dfec3e34c0d206f2ee1b2fbb6a.tar.gz chromium_src-207c678c4692c9dfec3e34c0d206f2ee1b2fbb6a.tar.bz2 |
Revert my last commit 'cause it breaks net unit tests on OS X 10.6 :(
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@40743 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-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 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_mac.cc | 21 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 47 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_win.cc | 16 | ||||
-rw-r--r-- | net/socket/ssl_test_util.cc | 3 |
10 files changed, 88 insertions, 235 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); diff --git a/net/socket/ssl_client_socket_mac.cc b/net/socket/ssl_client_socket_mac.cc index 1a0ca6d..0720a40 100644 --- a/net/socket/ssl_client_socket_mac.cc +++ b/net/socket/ssl_client_socket_mac.cc @@ -411,22 +411,29 @@ X509Certificate* GetServerCert(SSLContextRef ssl_context) { DCHECK_GT(CFArrayGetCount(certs), 0); + SecCertificateRef server_cert = static_cast<SecCertificateRef>( + const_cast<void*>(CFArrayGetValueAtIndex(certs, 0))); + CFRetain(server_cert); + X509Certificate *x509_cert = X509Certificate::CreateFromHandle( + server_cert, X509Certificate::SOURCE_FROM_NETWORK); + if (!x509_cert) + return NULL; + // Add each of the intermediate certificates in the server's chain to the // server's X509Certificate object. This makes them available to // X509Certificate::Verify() for chain building. - std::vector<SecCertificateRef> intermediate_ca_certs; + // TODO(wtc): Since X509Certificate::CreateFromHandle may return a cached + // X509Certificate object, we may be adding intermediate CA certificates to + // it repeatedly! CFIndex certs_length = CFArrayGetCount(certs); for (CFIndex i = 1; i < certs_length; ++i) { SecCertificateRef cert_ref = reinterpret_cast<SecCertificateRef>( const_cast<void*>(CFArrayGetValueAtIndex(certs, i))); - intermediate_ca_certs.push_back(cert_ref); + CFRetain(cert_ref); + x509_cert->AddIntermediateCertificate(cert_ref); } - SecCertificateRef server_cert = static_cast<SecCertificateRef>( - const_cast<void*>(CFArrayGetValueAtIndex(certs, 0))); - CFRetain(server_cert); - return X509Certificate::CreateFromHandle( - server_cert, X509Certificate::SOURCE_FROM_NETWORK, intermediate_ca_certs); + return x509_cert; } // Dynamically look up a pointer to a function exported by a bundle. diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index 30566b3..52dc09e 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -595,11 +595,24 @@ X509Certificate *SSLClientSocketNSS::UpdateServerCert() { if (!cert_store_) cert_store_ = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL); - // Get each of the intermediate certificates in the server's chain. - // These will be added to the server's X509Certificate object, making - // them available to X509Certificate::Verify() for chain building. - X509Certificate::OSCertHandles intermediate_ca_certs; PCCERT_CONTEXT cert_context = NULL; + BOOL ok = CertAddEncodedCertificateToStore( + cert_store_, + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + server_cert_nss_->derCert.data, + server_cert_nss_->derCert.len, + CERT_STORE_ADD_USE_EXISTING, + &cert_context); + DCHECK(ok); + server_cert_ = X509Certificate::CreateFromHandle( + cert_context, X509Certificate::SOURCE_FROM_NETWORK); + + // Add each of the intermediate certificates in the server's chain to + // the server's X509Certificate object. This makes them available to + // X509Certificate::Verify() for chain building. + // TODO(wtc): Since X509Certificate::CreateFromHandle may return a + // cached X509Certificate object, we may be adding intermediate CA + // certificates to it repeatedly! CERTCertList* cert_list = CERT_GetCertChainFromCert( server_cert_nss_, PR_Now(), certUsageSSLCA); if (cert_list) { @@ -607,7 +620,7 @@ X509Certificate *SSLClientSocketNSS::UpdateServerCert() { !CERT_LIST_END(node, cert_list); node = CERT_LIST_NEXT(node)) { cert_context = NULL; - BOOL ok = CertAddEncodedCertificateToStore( + ok = CertAddEncodedCertificateToStore( cert_store_, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, node->cert->derCert.data, @@ -616,31 +629,14 @@ X509Certificate *SSLClientSocketNSS::UpdateServerCert() { &cert_context); DCHECK(ok); if (node->cert != server_cert_nss_) - intermediate_ca_certs.push_back(cert_context); + server_cert_->AddIntermediateCertificate(cert_context); } CERT_DestroyCertList(cert_list); } - - // Finally create the X509Certificate object. - BOOL ok = CertAddEncodedCertificateToStore( - cert_store_, - X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, - server_cert_nss_->derCert.data, - server_cert_nss_->derCert.len, - CERT_STORE_ADD_USE_EXISTING, - &cert_context); - DCHECK(ok); - server_cert_ = X509Certificate::CreateFromHandle( - cert_context, - X509Certificate::SOURCE_FROM_NETWORK, - intermediate_ca_certs); - for (size_t i = 0; i < intermediate_ca_certs.size(); ++i) - CertFreeCertificateContext(intermediate_ca_certs[i]); #else server_cert_ = X509Certificate::CreateFromHandle( CERT_DupCertificate(server_cert_nss_), - X509Certificate::SOURCE_FROM_NETWORK, - X509Certificate::OSCertHandles()); + X509Certificate::SOURCE_FROM_NETWORK); #endif } } @@ -1143,8 +1139,7 @@ SECStatus SSLClientSocketNSS::ClientAuthHandler( privkey = PK11_FindKeyByAnyCert(cert, wincx); if (privkey) { X509Certificate* x509_cert = X509Certificate::CreateFromHandle( - cert, X509Certificate::SOURCE_LONE_CERT_IMPORT, - net::X509Certificate::OSCertHandles()); + cert, X509Certificate::SOURCE_LONE_CERT_IMPORT); that->client_certs_.push_back(x509_cert); SECKEY_DestroyPrivateKey(privkey); continue; diff --git a/net/socket/ssl_client_socket_win.cc b/net/socket/ssl_client_socket_win.cc index bf4a547..7e76f9e 100644 --- a/net/socket/ssl_client_socket_win.cc +++ b/net/socket/ssl_client_socket_win.cc @@ -68,6 +68,13 @@ static int MapSecurityError(SECURITY_STATUS err) { } } +// Returns true if the two CERT_CONTEXTs contain the same certificate. +bool SameCert(PCCERT_CONTEXT a, PCCERT_CONTEXT b) { + return a == b || + (a->cbCertEncoded == b->cbCertEncoded && + memcmp(a->pbCertEncoded, b->pbCertEncoded, b->cbCertEncoded) == 0); +} + //----------------------------------------------------------------------------- // A bitmask consisting of these bit flags encodes which versions of the SSL @@ -411,8 +418,7 @@ void SSLClientSocketWin::GetSSLCertRequestInfo( continue; } scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( - cert_context2, X509Certificate::SOURCE_LONE_CERT_IMPORT, - net::X509Certificate::OSCertHandles()); + cert_context2, X509Certificate::SOURCE_LONE_CERT_IMPORT); cert_request_info->client_certs.push_back(cert); } @@ -1297,16 +1303,14 @@ int SSLClientSocketWin::DidCompleteHandshake() { return MapSecurityError(status); } if (renegotiating_ && - X509Certificate::IsSameOSCert(server_cert_->os_cert_handle(), - server_cert_handle)) { + SameCert(server_cert_->os_cert_handle(), server_cert_handle)) { // We already verified the server certificate. Either it is good or the // user has accepted the certificate error. CertFreeCertificateContext(server_cert_handle); DidCompleteRenegotiation(); } else { server_cert_ = X509Certificate::CreateFromHandle( - server_cert_handle, X509Certificate::SOURCE_FROM_NETWORK, - net::X509Certificate::OSCertHandles()); + server_cert_handle, X509Certificate::SOURCE_FROM_NETWORK); next_state_ = STATE_VERIFY_CERT; } diff --git a/net/socket/ssl_test_util.cc b/net/socket/ssl_test_util.cc index 56eba9c..55d104c 100644 --- a/net/socket/ssl_test_util.cc +++ b/net/socket/ssl_test_util.cc @@ -112,8 +112,7 @@ static net::X509Certificate* LoadTemporaryCert(const FilePath& filename) { const_cast<void*>(CFArrayGetValueAtIndex(cert_array, 0))); CFRetain(cert_ref); return net::X509Certificate::CreateFromHandle(cert_ref, - net::X509Certificate::SOURCE_LONE_CERT_IMPORT, - net::X509Certificate::OSCertHandles()); + net::X509Certificate::SOURCE_FROM_NETWORK); } #endif |