diff options
author | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-28 19:44:02 +0000 |
---|---|---|
committer | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-28 19:44:02 +0000 |
commit | f505a9b267f83d8375eee2037e5e08dc6197143d (patch) | |
tree | f14dda4257275e562cdaa81c27cffe59f6ce53ea /net/socket/ssl_client_socket_nss.cc | |
parent | 2618629d2408b7d152b5b0e189586740dd5332a6 (diff) | |
download | chromium_src-f505a9b267f83d8375eee2037e5e08dc6197143d.zip chromium_src-f505a9b267f83d8375eee2037e5e08dc6197143d.tar.gz chromium_src-f505a9b267f83d8375eee2037e5e08dc6197143d.tar.bz2 |
Port SSLClientSocketNSS to Windows. The next step is to
actually use it (controlled by a boolean flag in SSLConfig,
which is controlled by a command-line switch).
On Windows we still use CryptoAPI to verify and display
certificates. SSL client authentication isn't supported yet.
R=agl,mark
BUG=28744
TEST=No build errors.
Review URL: http://codereview.chromium.org/557027
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37427 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket/ssl_client_socket_nss.cc')
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 84 |
1 files changed, 74 insertions, 10 deletions
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index 29af7f0..10690ee 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -213,17 +213,22 @@ int MapHandshakeError(PRErrorCode err) { } // namespace -bool SSLClientSocketNSS::nss_options_initialized_ = false; +#if defined(OS_WIN) +// static +HCERTSTORE SSLClientSocketNSS::cert_store_ = NULL; +#endif SSLClientSocketNSS::SSLClientSocketNSS(ClientSocket* transport_socket, const std::string& hostname, const SSLConfig& ssl_config) - : - buffer_send_callback_(this, &SSLClientSocketNSS::BufferSendComplete), - buffer_recv_callback_(this, &SSLClientSocketNSS::BufferRecvComplete), + : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_( + this, &SSLClientSocketNSS::BufferSendComplete)), + ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_( + this, &SSLClientSocketNSS::BufferRecvComplete)), transport_send_busy_(false), transport_recv_busy_(false), - handshake_io_callback_(this, &SSLClientSocketNSS::OnHandshakeIOComplete), + ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_( + this, &SSLClientSocketNSS::OnHandshakeIOComplete)), transport_(transport_socket), hostname_(hostname), ssl_config_(ssl_config), @@ -232,6 +237,7 @@ SSLClientSocketNSS::SSLClientSocketNSS(ClientSocket* transport_socket, user_write_callback_(NULL), user_read_buf_len_(0), user_write_buf_len_(0), + server_cert_nss_(NULL), client_auth_cert_needed_(false), completed_handshake_(false), next_handshake_state_(STATE_NONE), @@ -251,10 +257,12 @@ int SSLClientSocketNSS::Init() { // Initialize the NSS SSL library in a threadsafe way. This also // initializes the NSS base library. EnsureNSSSSLInit(); +#if !defined(OS_WIN) // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop // by MessageLoopForIO::current(). // X509Certificate::Verify() runs on a worker thread of CertVerifier. EnsureOCSPInit(); +#endif LeaveFunction(""); return OK; @@ -467,6 +475,10 @@ void SSLClientSocketNSS::Disconnect() { user_write_buf_ = NULL; user_write_buf_len_ = 0; server_cert_ = NULL; + if (server_cert_nss_) { + CERT_DestroyCertificate(server_cert_nss_); + server_cert_nss_ = NULL; + } server_cert_verify_result_.Reset(); completed_handshake_ = false; nss_bufs_ = NULL; @@ -570,10 +582,56 @@ X509Certificate *SSLClientSocketNSS::UpdateServerCert() { // does not necessarily get called if we are continuing a cached SSL // session. if (server_cert_ == NULL) { - X509Certificate::OSCertHandle nss_cert = SSL_PeerCertificate(nss_fd_); - if (nss_cert) { + server_cert_nss_ = SSL_PeerCertificate(nss_fd_); + if (server_cert_nss_) { +#if defined(OS_WIN) + // TODO(wtc): close cert_store_ at shutdown. + if (!cert_store_) + cert_store_ = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL); + + PCCERT_CONTEXT cert_context = NULL; + BOOL ok = CertAddEncodedCertificateToStore( + cert_store_, + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + server_cert_nss_->derCert.data, + server_cert_nss_->derCert.len, + CERT_STORE_ADD_USE_EXISTING, + &cert_context); + DCHECK(ok); + server_cert_ = X509Certificate::CreateFromHandle( + cert_context, X509Certificate::SOURCE_FROM_NETWORK); + + // Add each of the intermediate certificates in the server's chain to + // the server's X509Certificate object. This makes them available to + // X509Certificate::Verify() for chain building. + // TODO(wtc): Since X509Certificate::CreateFromHandle may return a + // cached X509Certificate object, we may be adding intermediate CA + // certificates to it repeatedly! + CERTCertList* cert_list = CERT_GetCertChainFromCert( + server_cert_nss_, PR_Now(), certUsageSSLCA); + if (cert_list) { + for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); + !CERT_LIST_END(node, cert_list); + node = CERT_LIST_NEXT(node)) { + cert_context = NULL; + ok = CertAddEncodedCertificateToStore( + cert_store_, + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + node->cert->derCert.data, + node->cert->derCert.len, + CERT_STORE_ADD_USE_EXISTING, + &cert_context); + DCHECK(ok); + if (node->cert != server_cert_nss_) + server_cert_->AddIntermediateCertificate(cert_context); + } + CERT_DestroyCertList(cert_list); + } +#else server_cert_ = X509Certificate::CreateFromHandle( - nss_cert, X509Certificate::SOURCE_FROM_NETWORK); + CERT_DupCertificate(server_cert_nss_), + X509Certificate::SOURCE_FROM_NETWORK); +#endif } } return server_cert_; @@ -1009,6 +1067,11 @@ SECStatus SSLClientSocketNSS::ClientAuthHandler( CERTDistNames* ca_names, CERTCertificate** result_certificate, SECKEYPrivateKey** result_private_key) { +#if defined(OS_WIN) + // Not implemented. Send no client certificate. + PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); + return SECFailure; +#else SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); that->client_auth_cert_needed_ = !that->ssl_config_.send_client_cert; @@ -1065,6 +1128,7 @@ SECStatus SSLClientSocketNSS::ClientAuthHandler( } return SECFailure; +#endif } // static @@ -1147,13 +1211,13 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) { // purposes. See https://bugzilla.mozilla.org/show_bug.cgi?id=508081 and // http://crbug.com/15630 for more info. CERTCertList* cert_list = CERT_GetCertChainFromCert( - server_cert_->os_cert_handle(), PR_Now(), certUsageSSLCA); + server_cert_nss_, PR_Now(), certUsageSSLCA); if (cert_list) { for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); !CERT_LIST_END(node, cert_list); node = CERT_LIST_NEXT(node)) { if (node->cert->slot || node->cert->isRoot || node->cert->isperm || - node->cert == server_cert_->os_cert_handle()) { + node->cert == server_cert_nss_) { // Some certs we don't want to remember are: // - found on a token. // - the root cert. |