diff options
author | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-21 04:48:17 +0000 |
---|---|---|
committer | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-21 04:48:17 +0000 |
commit | 40a089c802ae7e4e514d2228c84c115842c4d371 (patch) | |
tree | e14688f6f48968f4c8ae432315323d78fe18342d /net | |
parent | 1ab4ddf6636cdb88ea138aa5820ddeed29f72b98 (diff) | |
download | chromium_src-40a089c802ae7e4e514d2228c84c115842c4d371.zip chromium_src-40a089c802ae7e4e514d2228c84c115842c4d371.tar.gz chromium_src-40a089c802ae7e4e514d2228c84c115842c4d371.tar.bz2 |
Revert r92977 partially to fix a certificate verification regression
on Windows.
We still need X509Certificate::cert_store(). Make it a leaky lazy
instance.
R=rsleevi@chromium.org,rvargas@chromium.org
BUG=89899,49377
TEST=Visit https://bugs.webkit.org/show_bug.cgi?id=64580 on Windows.
Should not get the untrusted certificate error.
Review URL: http://codereview.chromium.org/7473009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93338 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/x509_certificate.cc | 21 | ||||
-rw-r--r-- | net/base/x509_certificate.h | 11 | ||||
-rw-r--r-- | net/base/x509_certificate_win.cc | 32 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 11 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_win.cc | 46 |
5 files changed, 104 insertions, 17 deletions
diff --git a/net/base/x509_certificate.cc b/net/base/x509_certificate.cc index 9d36b50..9fbf702 100644 --- a/net/base/x509_certificate.cc +++ b/net/base/x509_certificate.cc @@ -217,6 +217,22 @@ void SplitOnChar(const base::StringPiece& src, } } +#if defined(OS_WIN) +X509Certificate::OSCertHandle CreateOSCert(base::StringPiece der_cert) { + X509Certificate::OSCertHandle cert_handle = NULL; + BOOL ok = CertAddEncodedCertificateToStore( + X509Certificate::cert_store(), X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + reinterpret_cast<const BYTE*>(der_cert.data()), der_cert.size(), + CERT_STORE_ADD_USE_EXISTING, &cert_handle); + return ok ? cert_handle : NULL; +} +#else +X509Certificate::OSCertHandle CreateOSCert(base::StringPiece der_cert) { + return X509Certificate::CreateOSCertHandleFromBytes( + const_cast<char*>(der_cert.data()), der_cert.size()); +} +#endif + } // namespace bool X509Certificate::LessThan::operator()(X509Certificate* lhs, @@ -248,11 +264,6 @@ X509Certificate* X509Certificate::CreateFromHandle( return new X509Certificate(cert_handle, intermediates); } -static X509Certificate::OSCertHandle CreateOSCert(base::StringPiece der_cert) { - return X509Certificate::CreateOSCertHandleFromBytes( - const_cast<char*>(der_cert.data()), der_cert.size()); -} - // static X509Certificate* X509Certificate::CreateFromDERCertChain( const std::vector<base::StringPiece>& der_certs) { diff --git a/net/base/x509_certificate.h b/net/base/x509_certificate.h index b02ede6..ad0849b 100644 --- a/net/base/x509_certificate.h +++ b/net/base/x509_certificate.h @@ -293,6 +293,17 @@ class NET_API X509Certificate CFArrayRef CreateClientCertificateChain() const; #endif +#if defined(OS_WIN) + // Returns a handle to a global, in-memory certificate store. We use it for + // two purposes: + // 1. Import server certificates into this store so that we can verify and + // display the certificates using CryptoAPI. + // 2. Copy client certificates from the "MY" system certificate store into + // this store so that we can close the system store when we finish + // searching for client certificates. + static HCERTSTORE cert_store(); +#endif + #if defined(USE_OPENSSL) // Returns a handle to a global, in-memory certificate store. We // use it for test code, e.g. importing the test server's certificate. diff --git a/net/base/x509_certificate_win.cc b/net/base/x509_certificate_win.cc index 57044d8..59b61a3 100644 --- a/net/base/x509_certificate_win.cc +++ b/net/base/x509_certificate_win.cc @@ -4,6 +4,7 @@ #include "net/base/x509_certificate.h" +#include "base/lazy_instance.h" #include "base/logging.h" #include "base/pickle.h" #include "base/sha1.h" @@ -642,6 +643,37 @@ void X509Certificate::GetSubjectAltName( } } +class GlobalCertStore { + public: + HCERTSTORE cert_store() { + return cert_store_; + } + + private: + friend struct base::DefaultLazyInstanceTraits<GlobalCertStore>; + + GlobalCertStore() + : cert_store_(CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL)) { + } + + ~GlobalCertStore() { + CertCloseStore(cert_store_, 0 /* flags */); + } + + const HCERTSTORE cert_store_; + + DISALLOW_COPY_AND_ASSIGN(GlobalCertStore); +}; + +static base::LazyInstance<GlobalCertStore, + base::LeakyLazyInstanceTraits<GlobalCertStore> > + g_cert_store(base::LINKER_INITIALIZED); + +// static +HCERTSTORE X509Certificate::cert_store() { + return g_cert_store.Get().cert_store(); +} + int X509Certificate::VerifyInternal(const std::string& hostname, int flags, CertVerifyResult* verify_result) const { diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index 83e866c..536b206 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -2056,10 +2056,11 @@ SECStatus SSLClientSocketNSS::PlatformClientAuthHandler( // Get the leaf certificate. PCCERT_CONTEXT cert_context = chain_context->rgpChain[0]->rgpElement[0]->pCertContext; - // Copy the certificate into a NULL store, so that we can close the "MY" - // store before returning from this function. + // Copy it to our own certificate store, so that we can close the "MY" + // certificate store before returning from this function. PCCERT_CONTEXT cert_context2; - BOOL ok = CertAddCertificateContextToStore(NULL, cert_context, + BOOL ok = CertAddCertificateContextToStore(X509Certificate::cert_store(), + cert_context, CERT_STORE_ADD_USE_EXISTING, &cert_context2); if (!ok) { @@ -2074,8 +2075,8 @@ SECStatus SSLClientSocketNSS::PlatformClientAuthHandler( net::X509Certificate::OSCertHandles intermediates; for (DWORD i = 1; i < chain_context->rgpChain[0]->cElement; i++) { PCCERT_CONTEXT intermediate_copy; - ok = CertAddCertificateContextToStore( - NULL, chain_context->rgpChain[0]->rgpElement[i]->pCertContext, + ok = CertAddCertificateContextToStore(X509Certificate::cert_store(), + chain_context->rgpChain[0]->rgpElement[i]->pCertContext, CERT_STORE_ADD_USE_EXISTING, &intermediate_copy); if (!ok) { NOTREACHED(); diff --git a/net/socket/ssl_client_socket_win.cc b/net/socket/ssl_client_socket_win.cc index a1a2396..6784b64 100644 --- a/net/socket/ssl_client_socket_win.cc +++ b/net/socket/ssl_client_socket_win.cc @@ -337,6 +337,40 @@ static BOOL WINAPI ClientCertFindCallback(PCCERT_CONTEXT cert_context, //----------------------------------------------------------------------------- +// A memory certificate store for client certificates. This allows us to +// close the "MY" system certificate store when we finish searching for +// client certificates. +class ClientCertStore { + public: + ClientCertStore() { + store_ = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL); + } + + ~ClientCertStore() { + if (store_) { + BOOL ok = CertCloseStore(store_, CERT_CLOSE_STORE_CHECK_FLAG); + DCHECK(ok); + } + } + + PCCERT_CONTEXT CopyCertContext(PCCERT_CONTEXT client_cert) { + PCCERT_CONTEXT copy; + BOOL ok = CertAddCertificateContextToStore(store_, client_cert, + CERT_STORE_ADD_USE_EXISTING, + ©); + DCHECK(ok); + return ok ? copy : NULL; + } + + private: + HCERTSTORE store_; +}; + +static base::LazyInstance<ClientCertStore> g_client_cert_store( + base::LINKER_INITIALIZED); + +//----------------------------------------------------------------------------- + // Size of recv_buffer_ // // Ciphertext is decrypted one SSL record at a time, so recv_buffer_ needs to @@ -488,13 +522,11 @@ void SSLClientSocketWin::GetSSLCertRequestInfo( // Get the leaf certificate. PCCERT_CONTEXT cert_context = chain_context->rgpChain[0]->rgpElement[0]->pCertContext; - // Copy the certificate into a NULL store, so that we can close the "MY" - // store before returning from this function. - PCCERT_CONTEXT cert_context2 = NULL; - BOOL ok = CertAddCertificateContextToStore(NULL, cert_context, - CERT_STORE_ADD_USE_EXISTING, - &cert_context2); - if (!ok) { + // Copy it to our own certificate store, so that we can close the "MY" + // certificate store before returning from this function. + PCCERT_CONTEXT cert_context2 = + g_client_cert_store.Get().CopyCertContext(cert_context); + if (!cert_context2) { NOTREACHED(); continue; } |