Chromium Code Reviews| Index: net/socket/ssl_client_socket_openssl.cc |
| diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc |
| index 8bdc3148d11e83b8b2a28ee5ceebca57d6bce9f5..1d7501cbac8a89f48be8fa6ae616745ee4b6cc2b 100644 |
| --- a/net/socket/ssl_client_socket_openssl.cc |
| +++ b/net/socket/ssl_client_socket_openssl.cc |
| @@ -97,10 +97,23 @@ std::string GetSocketSessionCacheKey(const SSLClientSocketOpenSSL& socket) { |
| return result; |
| } |
| -static void FreeX509Stack(STACK_OF(X509) * ptr) { |
| +void FreeX509Stack(STACK_OF(X509) * ptr) { |
| sk_X509_pop_free(ptr, X509_free); |
| } |
| +crypto::ScopedX509 OSCertHandleToOpenSSL( |
| + X509Certificate::OSCertHandle os_handle) { |
| +#if defined(USE_OPENSSL_CERTS) |
| + return crypto::ScopedX509(X509Certificate::DupOSCertHandle(os_handle)); |
| +#else // !defined(USE_OPENSSL_CERTS) |
| + std::string der_encoded; |
| + if (!X509Certificate::GetDEREncoded(os_handle, &der_encoded)) |
| + return crypto::ScopedX509(); |
| + const uint8_t* bytes = reinterpret_cast<const uint8_t*>(der_encoded.data()); |
| + return crypto::ScopedX509(d2i_X509(NULL, &bytes, der_encoded.size())); |
| +#endif // defined(USE_OPENSSL_CERTS) |
| +} |
| + |
| } // namespace |
| class SSLClientSocketOpenSSL::SSLContext { |
| @@ -1349,31 +1362,39 @@ int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl, |
| // Second pass: a client certificate should have been selected. |
| if (ssl_config_.client_cert.get()) { |
| + // TODO(davidben): Configure OpenSSL to also send the intermediates. |
| + crypto::ScopedX509 leaf_x509 = |
| + OSCertHandleToOpenSSL(ssl_config_.client_cert->os_cert_handle()); |
| + if (!leaf_x509 || true) { |
| + LOG(WARNING) << "Failed to import certificate"; |
| + return -1; |
| + } |
| + |
| + OpenSSLClientKeyStore::ScopedEVP_PKEY privkey; |
|
davidben
2014/07/11 00:10:25
This silly thing will be crypto::ScopedEVP_PKEY wi
|
| #if defined(USE_OPENSSL_CERTS) |
| // A note about ownership: FetchClientCertPrivateKey() increments |
| // the reference count of the EVP_PKEY. Ownership of this reference |
| // is passed directly to OpenSSL, which will release the reference |
| // using EVP_PKEY_free() when the SSL object is destroyed. |
| - OpenSSLClientKeyStore::ScopedEVP_PKEY privkey; |
| - if (OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey( |
| + if (!OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey( |
| ssl_config_.client_cert.get(), &privkey)) { |
| - // TODO(joth): (copied from NSS) We should wait for server certificate |
| - // verification before sending our credentials. See http://crbug.com/13934 |
| - *x509 = X509Certificate::DupOSCertHandle( |
| - ssl_config_.client_cert->os_cert_handle()); |
| - *pkey = privkey.release(); |
| - return 1; |
| + // Could not find the private key. Fail the handshake and surface an |
| + // appropriate error to the caller. |
| + LOG(WARNING) << "Client cert found without private key"; |
| + OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY); |
| + return -1; |
| } |
| - |
| - // Could not find the private key. Fail the handshake and surface an |
| - // appropriate error to the caller. |
| - LOG(WARNING) << "Client cert found without private key"; |
| - OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY); |
| - return -1; |
| #else // !defined(USE_OPENSSL_CERTS) |
| - // OS handling of client certificates is not yet implemented. |
| + // OS handling of private keys is not yet implemented. |
| NOTIMPLEMENTED(); |
| + return 0; |
| #endif // defined(USE_OPENSSL_CERTS) |
| + |
| + // TODO(joth): (copied from NSS) We should wait for server certificate |
| + // verification before sending our credentials. See http://crbug.com/13934 |
| + *x509 = leaf_x509.release(); |
| + *pkey = privkey.release(); |
| + return 1; |
| } |
| // Send no client certificate. |