diff options
Diffstat (limited to 'net/socket/ssl_client_socket_nss.cc')
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 139 |
1 files changed, 81 insertions, 58 deletions
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index a6aa458..3234320 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -94,6 +94,7 @@ #include "net/ocsp/nss_ocsp.h" #include "net/socket/client_socket_handle.h" #include "net/socket/dns_cert_provenance_check.h" +#include "net/socket/ssl_error_params.h" #include "net/socket/ssl_host_info.h" static const int kRecvBufferSize = 4096; @@ -272,28 +273,6 @@ int MapHandshakeError(PRErrorCode err) { } } -// Extra parameters to attach to the NetLog when we receive an SSL error. -class SSLErrorParams : public NetLog::EventParameters { - public: - // If |ssl_lib_error| is 0, it will be ignored. - SSLErrorParams(int net_error, PRErrorCode ssl_lib_error) - : net_error_(net_error), - ssl_lib_error_(ssl_lib_error) { - } - - virtual Value* ToValue() const { - DictionaryValue* dict = new DictionaryValue(); - dict->SetInteger("net_error", net_error_); - if (ssl_lib_error_) - dict->SetInteger("ssl_lib_error", ssl_lib_error_); - return dict; - } - - private: - const int net_error_; - const PRErrorCode ssl_lib_error_; -}; - // Extra parameters to attach to the NetLog when we receive an error in response // to a call to an NSS function. Used instead of SSLErrorParams with // events of type TYPE_SSL_NSS_ERROR. Automatically looks up last PR error. @@ -417,7 +396,7 @@ class PeerCertificateChain { } // namespace SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket, - const std::string& hostname, + const HostPortPair& host_and_port, const SSLConfig& ssl_config, SSLHostInfo* ssl_host_info, DnsRRResolver* dnsrr_resolver) @@ -431,7 +410,7 @@ SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket, ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_( this, &SSLClientSocketNSS::OnHandshakeIOComplete)), transport_(transport_socket), - hostname_(hostname), + host_and_port_(host_and_port), ssl_config_(ssl_config), user_connect_callback_(NULL), user_read_callback_(NULL), @@ -500,7 +479,8 @@ void SSLClientSocketNSS::SaveSnapStartInfo() { } net_log_.AddEvent(NetLog::TYPE_SSL_SNAP_START, new NetLogIntegerParameter("type", snap_start_type)); - LOG(ERROR) << "Snap Start: " << snap_start_type << " " << hostname_; + LOG(ERROR) << "Snap Start: " << snap_start_type << " " + << host_and_port_.ToString(); if (snap_start_type == SSL_SNAP_START_FULL || snap_start_type == SSL_SNAP_START_RESUME) { // If we did a successful Snap Start then our information was correct and @@ -539,7 +519,7 @@ void SSLClientSocketNSS::SaveSnapStartInfo() { certs[i]->derCert.len)); } - LOG(ERROR) << "Setting Snap Start info " << hostname_; + LOG(ERROR) << "Setting Snap Start info " << host_and_port_.ToString(); ssl_host_info_->Persist(); } @@ -729,6 +709,14 @@ int SSLClientSocketNSS::InitializeSSLOptions() { return ERR_UNEXPECTED; } + for (std::vector<uint16>::const_iterator it = + ssl_config_.disabled_cipher_suites.begin(); + it != ssl_config_.disabled_cipher_suites.end(); ++it) { + // This will fail if the specified cipher is not implemented by NSS, but + // the failure is harmless. + SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE); + } + #ifdef SSL_ENABLE_SESSION_TICKETS // Support RFC 5077 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE); @@ -754,7 +742,8 @@ int SSLClientSocketNSS::InitializeSSLOptions() { rv = SSL_OptionSet( nss_fd_, SSL_ENABLE_FALSE_START, ssl_config_.false_start_enabled && - !SSLConfigService::IsKnownFalseStartIncompatibleServer(hostname_)); + !SSLConfigService::IsKnownFalseStartIncompatibleServer( + host_and_port_.host())); if (rv != SECSuccess) LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_FALSE_START"); #endif @@ -771,7 +760,7 @@ int SSLClientSocketNSS::InitializeSSLOptions() { #ifdef SSL_ENABLE_RENEGOTIATION // Deliberately disable this check for now: http://crbug.com/55410 if (false && - SSLConfigService::IsKnownStrictTLSServer(hostname_) && + SSLConfigService::IsKnownStrictTLSServer(host_and_port_.host()) && !ssl_config_.mitm_proxies_allowed) { rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_SAFE_NEGOTIATION, PR_TRUE); if (rv != SECSuccess) { @@ -836,7 +825,7 @@ int SSLClientSocketNSS::InitializeSSLOptions() { } // Tell SSL the hostname we're trying to connect to. - SSL_SetURL(nss_fd_, hostname_.c_str()); + SSL_SetURL(nss_fd_, host_and_port_.host().c_str()); // Tell SSL we're a client; needed if not letting NSPR do socket I/O SSL_ResetHandshake(nss_fd_, 0); @@ -871,10 +860,7 @@ int SSLClientSocketNSS::InitializeSSLPeerName() { // Set the peer ID for session reuse. This is necessary when we create an // SSL tunnel through a proxy -- GetPeerName returns the proxy's address // rather than the destination server's address in that case. - // TODO(wtc): port in |peer_address| is not the server's port when a proxy is - // used. - std::string peer_id = base::StringPrintf("%s:%d", hostname_.c_str(), - peer_address.GetPort()); + std::string peer_id = host_and_port_.ToString(); SECStatus rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str())); if (rv != SECSuccess) LogFailedNSSFunction(net_log_, "SSL_SetSockPeerID", peer_id.c_str()); @@ -883,19 +869,11 @@ int SSLClientSocketNSS::InitializeSSLPeerName() { return OK; } -void SSLClientSocketNSS::InvalidateSessionIfBadCertificate() { - if (UpdateServerCert() != NULL && - ssl_config_.IsAllowedBadCert(server_cert_)) { - SSL_InvalidateSession(nss_fd_); - } -} - void SSLClientSocketNSS::Disconnect() { EnterFunction(""); // TODO(wtc): Send SSL close_notify alert. if (nss_fd_ != NULL) { - InvalidateSessionIfBadCertificate(); PR_Close(nss_fd_); nss_fd_ = NULL; } @@ -1090,6 +1068,11 @@ bool SSLClientSocketNSS::SetSendBufferSize(int32 size) { return transport_->socket()->SetSendBufferSize(size); } +// static +void SSLClientSocketNSS::ClearSessionCache() { + SSL_ClearSessionCache(); +} + // Sets server_cert_ and server_cert_nss_ if not yet set. // Returns server_cert_. X509Certificate *SSLClientSocketNSS::UpdateServerCert() { @@ -1156,7 +1139,7 @@ void SSLClientSocketNSS::UpdateConnectionStatus() { ssl_connection_status_ |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION; // Log an informational message if the server does not support secure // renegotiation (RFC 5746). - VLOG(1) << "The server " << hostname_ + VLOG(1) << "The server " << host_and_port_.ToString() << " does not support the TLS renegotiation_info extension."; } UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported", @@ -1200,7 +1183,8 @@ void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) { void SSLClientSocketNSS::GetSSLCertRequestInfo( SSLCertRequestInfo* cert_request_info) { EnterFunction(""); - cert_request_info->host_and_port = hostname_; // TODO(wtc): no port! + // TODO(rch): switch SSLCertRequestInfo.host_and_port to a HostPortPair + cert_request_info->host_and_port = host_and_port_.ToString(); cert_request_info->client_certs = client_certs_; LeaveFunction(cert_request_info->client_certs.size()); } @@ -1691,6 +1675,54 @@ SECStatus SSLClientSocketNSS::PlatformClientAuthHandler( if (that->ssl_config_.client_cert) { PCCERT_CONTEXT cert_context = that->ssl_config_.client_cert->os_cert_handle(); + if (VLOG_IS_ON(1)) { + do { + DWORD size_needed = 0; + BOOL got_info = CertGetCertificateContextProperty( + cert_context, CERT_KEY_PROV_INFO_PROP_ID, NULL, &size_needed); + if (!got_info) { + VLOG(1) << "Failed to get key prov info size " << GetLastError(); + break; + } + std::vector<BYTE> raw_info(size_needed); + got_info = CertGetCertificateContextProperty( + cert_context, CERT_KEY_PROV_INFO_PROP_ID, &raw_info[0], + &size_needed); + if (!got_info) { + VLOG(1) << "Failed to get key prov info " << GetLastError(); + break; + } + PCRYPT_KEY_PROV_INFO info = + reinterpret_cast<PCRYPT_KEY_PROV_INFO>(&raw_info[0]); + VLOG(1) << "Container Name: " << info->pwszContainerName + << "\nProvider Name: " << info->pwszProvName + << "\nProvider Type: " << info->dwProvType + << "\nFlags: " << info->dwFlags + << "\nProvider Param Count: " << info->cProvParam + << "\nKey Specifier: " << info->dwKeySpec; + } while (false); + + do { + DWORD size_needed = 0; + BOOL got_identifier = CertGetCertificateContextProperty( + cert_context, CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size_needed); + if (!got_identifier) { + VLOG(1) << "Failed to get key identifier size " + << GetLastError(); + break; + } + std::vector<BYTE> raw_id(size_needed); + got_identifier = CertGetCertificateContextProperty( + cert_context, CERT_KEY_IDENTIFIER_PROP_ID, &raw_id[0], + &size_needed); + if (!got_identifier) { + VLOG(1) << "Failed to get key identifier " << GetLastError(); + break; + } + VLOG(1) << "Key Identifier: " << base::HexEncode(&raw_id[0], + size_needed); + } while (false); + } HCRYPTPROV provider = NULL; DWORD key_spec = AT_KEYEXCHANGE; BOOL must_free = FALSE; @@ -1911,7 +1943,7 @@ SECStatus SSLClientSocketNSS::PlatformClientAuthHandler( } // Now get the available client certs whose issuers are allowed by the server. - X509Certificate::GetSSLClientCertificates(that->hostname_, + X509Certificate::GetSSLClientCertificates(that->host_and_port_.host(), valid_issuers, &that->client_certs_); @@ -2126,7 +2158,8 @@ int SSLClientSocketNSS::DoHandshake() { // prepared for switching the protocol like that so we make up an error // and rely on the fact that the request will be retried. if (IsNPNProtocolMispredicted()) { - LOG(WARNING) << "Mispredicted NPN protocol for " << hostname_; + LOG(WARNING) << "Mispredicted NPN protocol for " + << host_and_port_.ToString(); net_error = ERR_SSL_SNAP_START_NPN_MISPREDICTION; } else { // Let's verify the certificate. @@ -2315,16 +2348,9 @@ static DNSValidationResult CheckDNSSECChain( } int SSLClientSocketNSS::DoVerifyDNSSEC(int result) { -#if !defined(USE_OPENSSL) - if (ssl_config_.dns_cert_provenance_checking_enabled && dnsrr_resolver_) { - PeerCertificateChain certs(nss_fd_); - DoAsyncDNSCertProvenanceVerification( - hostname_, dnsrr_resolver_, certs.AsStringPieceVector()); - } -#endif - if (ssl_config_.dnssec_enabled) { - DNSValidationResult r = CheckDNSSECChain(hostname_, server_cert_nss_); + DNSValidationResult r = CheckDNSSECChain(host_and_port_.host(), + server_cert_nss_); if (r == DNSVR_SUCCESS) { local_server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC; server_cert_verify_result_ = &local_server_cert_verify_result_; @@ -2420,7 +2446,7 @@ int SSLClientSocketNSS::DoVerifyCert(int result) { flags |= X509Certificate::VERIFY_EV_CERT; verifier_.reset(new CertVerifier); server_cert_verify_result_ = &local_server_cert_verify_result_; - return verifier_->Verify(server_cert_, hostname_, flags, + return verifier_->Verify(server_cert_, host_and_port_.host(), flags, &local_server_cert_verify_result_, &handshake_io_callback_); } @@ -2456,9 +2482,6 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) { LogConnectionTypeMetrics(); completed_handshake_ = true; - // TODO(ukai): we may not need this call because it is now harmless to have a - // session with a bad cert. - InvalidateSessionIfBadCertificate(); // If we merged a Write call into the handshake we need to make the // callback now. |