summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-21 04:48:17 +0000
committerwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-21 04:48:17 +0000
commit40a089c802ae7e4e514d2228c84c115842c4d371 (patch)
treee14688f6f48968f4c8ae432315323d78fe18342d /net
parent1ab4ddf6636cdb88ea138aa5820ddeed29f72b98 (diff)
downloadchromium_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.cc21
-rw-r--r--net/base/x509_certificate.h11
-rw-r--r--net/base/x509_certificate_win.cc32
-rw-r--r--net/socket/ssl_client_socket_nss.cc11
-rw-r--r--net/socket/ssl_client_socket_win.cc46
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,
+ &copy);
+ 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;
}