| Index: net/socket/ssl_client_socket_win.cc
|
| diff --git a/net/socket/ssl_client_socket_win.cc b/net/socket/ssl_client_socket_win.cc
|
| index ae4d4b5905ed090246c7beec9b338c50cf704151..16d12dd0535d032ce0cca820b8d0674691b06f49 100644
|
| --- a/net/socket/ssl_client_socket_win.cc
|
| +++ b/net/socket/ssl_client_socket_win.cc
|
| @@ -330,40 +330,6 @@ 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
|
| @@ -512,19 +478,35 @@ void SSLClientSocketWin::GetSSLCertRequestInfo(
|
| // Get the leaf certificate.
|
| PCCERT_CONTEXT cert_context =
|
| chain_context->rgpChain[0]->rgpElement[0]->pCertContext;
|
| - // 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) {
|
| + // 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) {
|
| NOTREACHED();
|
| continue;
|
| }
|
| +
|
| + // Grab the intermediates, if any.
|
| + X509Certificate::OSCertHandles intermediates;
|
| + for (DWORD i = 1; i < chain_context->rgpChain[0]->cElement; ++i) {
|
| + PCCERT_CONTEXT chain_intermediate =
|
| + chain_context->rgpChain[0]->rgpElement[i]->pCertContext;
|
| + PCCERT_CONTEXT chain_intermediate2;
|
| + ok = CertAddCertificateContextToStore(NULL, chain_intermediate,
|
| + CERT_STORE_ADD_USE_EXISTING,
|
| + &chain_intermediate2);
|
| + if (ok)
|
| + intermediates.push_back(chain_intermediate2);
|
| + }
|
| scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle(
|
| - cert_context2, X509Certificate::SOURCE_LONE_CERT_IMPORT,
|
| - X509Certificate::OSCertHandles());
|
| + cert_context2, intermediates);
|
| cert_request_info->client_certs.push_back(cert);
|
| CertFreeCertificateContext(cert_context2);
|
| + for (size_t i = 0; i < intermediates.size(); ++i)
|
| + CertFreeCertificateContext(intermediates[i]);
|
| }
|
|
|
| FreeContextBuffer(issuer_list.aIssuers);
|
| @@ -1473,20 +1455,34 @@ int SSLClientSocketWin::DidCompleteHandshake() {
|
| LOG(ERROR) << "QueryContextAttributes (remote cert) failed: " << status;
|
| return MapSecurityError(status);
|
| }
|
| +
|
| + X509Certificate::OSCertHandles intermediates;
|
| + PCCERT_CONTEXT intermediate =
|
| + CertEnumCertificatesInStore(server_cert_handle->hCertStore, NULL);
|
| + while (intermediate != NULL) {
|
| + intermediates.push_back(CertDuplicateCertificateContext(intermediate));
|
| + intermediate = CertEnumCertificatesInStore(server_cert_handle->hCertStore,
|
| + intermediate);
|
| + }
|
| +
|
| if (renegotiating_ &&
|
| X509Certificate::IsSameOSCert(server_cert_->os_cert_handle(),
|
| - server_cert_handle)) {
|
| + server_cert_handle) &&
|
| + server_cert_->HasIntermediateCertificates(intermediates) &&
|
| + server_cert_->GetIntermediateCertificates().size() ==
|
| + intermediates.size()) {
|
| // We already verified the server certificate. Either it is good or the
|
| // user has accepted the certificate error.
|
| DidCompleteRenegotiation();
|
| } else {
|
| server_cert_ = X509Certificate::CreateFromHandle(
|
| - server_cert_handle, X509Certificate::SOURCE_FROM_NETWORK,
|
| - X509Certificate::OSCertHandles());
|
| + server_cert_handle, intermediates);
|
|
|
| next_state_ = STATE_VERIFY_CERT;
|
| }
|
| CertFreeCertificateContext(server_cert_handle);
|
| + for (size_t i = 0; i < intermediates.size(); ++i)
|
| + CertFreeCertificateContext(intermediates[i]);
|
| return OK;
|
| }
|
|
|
|
|