Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(526)

Unified Diff: net/socket/ssl_client_socket_nss.cc

Issue 7995009: net: fix crash when failing to import a client-side cert into NSS. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: ... Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | net/socket/ssl_server_socket_nss.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/ssl_client_socket_nss.cc
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index 879689ad6dd149d58a656858cf558d424074efd1..56597b135ed248bcd3e6e10e36b5c600f422dc32 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -2137,24 +2137,19 @@ SECStatus SSLClientSocketNSS::PlatformClientAuthHandler(
if (that->ssl_config_.client_cert) {
PCCERT_CONTEXT cert_context =
that->ssl_config_.client_cert->os_cert_handle();
- PCERT_KEY_CONTEXT key_context = reinterpret_cast<PCERT_KEY_CONTEXT>(
- PORT_ZAlloc(sizeof(CERT_KEY_CONTEXT)));
- if (!key_context)
- return SECFailure;
- key_context->cbSize = sizeof(*key_context);
+ HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv = INVALID_HANDLE;
+ DWORD dwKeySpec = 0;
wtc 2011/09/23 19:53:34 I haven't seen the INVALID_HANDLE macro before. S
BOOL must_free = FALSE;
BOOL acquired_key = CryptAcquireCertificatePrivateKey(
cert_context, CRYPT_ACQUIRE_CACHE_FLAG, NULL,
- &key_context->hCryptProv, &key_context->dwKeySpec, &must_free);
- if (acquired_key && key_context->hCryptProv) {
- DCHECK_NE(key_context->dwKeySpec, CERT_NCRYPT_KEY_SPEC);
+ &hCryptProv, &dwKeySpec, &must_free);
+ // Since we passed CRYPT_ACQUIRE_CACHE_FLAG, |must_free| must be false
+ // according to the MSDN documentation.
+ DCHECK(must_free == FALSE);
wtc 2011/09/23 19:53:34 You can use DCHECK_EQ here. cpplint probably will
Ryan Sleevi 2011/09/23 22:33:50 Double checked my notes from disassembling this fu
- // The certificate cache may have been updated/used, in which case,
- // duplicate the existing handle, since NSS will free it when no
- // longer in use.
- if (!must_free)
- CryptContextAddRef(key_context->hCryptProv, NULL, 0);
+ if (acquired_key && hCryptProv != INVALID_HANDLE) {
+ DCHECK_NE(dwKeySpec, CERT_NCRYPT_KEY_SPEC);
SECItem der_cert;
der_cert.type = siDERCertBuffer;
@@ -2162,11 +2157,16 @@ SECStatus SSLClientSocketNSS::PlatformClientAuthHandler(
der_cert.len = cert_context->cbCertEncoded;
// TODO(rsleevi): Error checking for NSS allocation errors.
- *result_certs = CERT_NewCertList();
CERTCertDBHandle* db_handle = CERT_GetDefaultCertDB();
CERTCertificate* user_cert = CERT_NewTempCertificate(
db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE);
- CERT_AddCertToListTail(*result_certs, user_cert);
+ if (!user_cert) {
+ // Importing the certificate can fail for reasons including a serial
+ // number collision. See crbug.com/97355.
+ return SECFailure;
+ }
+ CERTCertList* cert_chain = CERT_NewCertList();
+ CERT_AddCertToListTail(cert_chain, user_cert);
// Add the intermediates.
X509Certificate::OSCertHandles intermediates =
@@ -2178,12 +2178,26 @@ SECStatus SSLClientSocketNSS::PlatformClientAuthHandler(
CERTCertificate* intermediate = CERT_NewTempCertificate(
db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE);
- CERT_AddCertToListTail(*result_certs, intermediate);
+ if (!intermediate) {
+ CERT_DestroyCertList(cert_chain);
+ return SECFailure;
+ }
+ CERT_AddCertToListTail(cert_chain, intermediate);
}
+ PCERT_KEY_CONTEXT key_context = reinterpret_cast<PCERT_KEY_CONTEXT>(
+ PORT_ZAlloc(sizeof(CERT_KEY_CONTEXT));
+ key_context->cbSize = sizeof(*key_context);
+ // NSS will free this context when no longer in use, but the
+ // |must_free| result from CryptAcquireCertificatePrivateKey was false
+ // so we increment the refcount to negate NSS's future decrement.
+ CryptContextAddRef(hCryptProv, NULL, 0);
+ key_context->hCryptProv = hCryptProv;
+ key_context->dwKeySpec = dwKeySpec;
*result_private_key = key_context;
+ *result_certs = cert_chain;
+
return SECSuccess;
}
- PORT_Free(key_context);
LOG(WARNING) << "Client cert found without private key";
}
// Send no client certificate.
@@ -2320,6 +2334,12 @@ SECStatus SSLClientSocketNSS::PlatformClientAuthHandler(
der_cert.len = cert_data.Length;
CERTCertificate* nss_cert = CERT_NewTempCertificate(
CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
+ if (!nss_cert) {
+ // In the event of an NSS error we make up an OS error and reuse
+ // the error handling, below.
+ os_error = errKCCreateChainFailed;
+ break;
+ }
CERT_AddCertToListTail(*result_certs, nss_cert);
}
}
« no previous file with comments | « no previous file | net/socket/ssl_server_socket_nss.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698