diff options
author | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-27 23:28:35 +0000 |
---|---|---|
committer | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-27 23:28:35 +0000 |
commit | 757f2e2ba0c1fa7100461745bfac865e3da1d976 (patch) | |
tree | 5ada8a2ea4122f949104663b3a02c54c3ba31720 /net/socket | |
parent | 017f19b5f1af1702252655b4b52bdcd9ab7a0de2 (diff) | |
download | chromium_src-757f2e2ba0c1fa7100461745bfac865e3da1d976.zip chromium_src-757f2e2ba0c1fa7100461745bfac865e3da1d976.tar.gz chromium_src-757f2e2ba0c1fa7100461745bfac865e3da1d976.tar.bz2 |
Report the SSL protocol version in ssl_info.connection_status.
Refactor SSLClientSocketNSS::GetSSLInfo -- the code that sets
ssl_info->connection_status is moved to a new
UpdateConnectionStatus method, and CheckSecureRenegotiation
is subsumed by UpdateConnectionStatus.
R=agl,finnur
BUG=53659
TEST=none
Review URL: http://codereview.chromium.org/4198003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64178 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket')
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 156 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.h | 6 |
2 files changed, 107 insertions, 55 deletions
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index 6d3f54f..f62c7b1 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -60,6 +60,7 @@ #include <sechash.h> #include <ssl.h> #include <sslerr.h> +#include <sslproto.h> #include <limits> @@ -76,6 +77,7 @@ #include "net/base/address_list.h" #include "net/base/cert_status_flags.h" #include "net/base/cert_verifier.h" +#include "net/base/connection_type_histograms.h" #include "net/base/dns_util.h" #include "net/base/dnsrr_resolver.h" #include "net/base/dnssec_chain_verifier.h" @@ -381,6 +383,7 @@ SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket, user_read_buf_len_(0), user_write_buf_len_(0), server_cert_nss_(NULL), + ssl_connection_status_(0), client_auth_cert_needed_(false), handshake_callback_called_(false), completed_handshake_(false), @@ -867,6 +870,7 @@ void SSLClientSocketNSS::Disconnect() { server_cert_nss_ = NULL; } server_cert_verify_result_.Reset(); + ssl_connection_status_ = 0; completed_handshake_ = false; pseudo_connected_ = false; eset_mitm_detected_ = false; @@ -1034,11 +1038,10 @@ bool SSLClientSocketNSS::SetSendBufferSize(int32 size) { return transport_->socket()->SetSendBufferSize(size); } - +// Sets server_cert_ and server_cert_nss_ if not yet set. +// Returns server_cert_. X509Certificate *SSLClientSocketNSS::UpdateServerCert() { - // We set the server_cert_ from HandshakeCallback(), but this handler - // does not necessarily get called if we are continuing a cached SSL - // session. + // We set the server_cert_ from HandshakeCallback(). if (server_cert_ == NULL) { server_cert_nss_ = SSL_PeerCertificate(nss_fd_); if (server_cert_nss_) { @@ -1069,21 +1072,61 @@ X509Certificate *SSLClientSocketNSS::UpdateServerCert() { return server_cert_; } -// Log an informational message if the server does not support secure -// renegotiation (RFC 5746). -void SSLClientSocketNSS::CheckSecureRenegotiation() const { +// Sets ssl_connection_status_. +void SSLClientSocketNSS::UpdateConnectionStatus() { + SSLChannelInfo channel_info; + SECStatus ok = SSL_GetChannelInfo(nss_fd_, + &channel_info, sizeof(channel_info)); + if (ok == SECSuccess && + channel_info.length == sizeof(channel_info) && + channel_info.cipherSuite) { + ssl_connection_status_ |= + (static_cast<int>(channel_info.cipherSuite) & + SSL_CONNECTION_CIPHERSUITE_MASK) << + SSL_CONNECTION_CIPHERSUITE_SHIFT; + + ssl_connection_status_ |= + (static_cast<int>(channel_info.compressionMethod) & + SSL_CONNECTION_COMPRESSION_MASK) << + SSL_CONNECTION_COMPRESSION_SHIFT; + + int version = SSL_CONNECTION_VERSION_UNKNOWN; + if (channel_info.protocolVersion < SSL_LIBRARY_VERSION_3_0) { + // All versions less than SSL_LIBRARY_VERSION_3_0 are treated as SSL + // version 2. + version = SSL_CONNECTION_VERSION_SSL2; + } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_0) { + version = SSL_CONNECTION_VERSION_SSL3; + } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_1_TLS) { + version = SSL_CONNECTION_VERSION_TLS1; + } + ssl_connection_status_ |= + (version & SSL_CONNECTION_VERSION_MASK) << + SSL_CONNECTION_VERSION_SHIFT; + } + // SSL_HandshakeNegotiatedExtension was added in NSS 3.12.6. // Since SSL_MAX_EXTENSIONS was added at the same time, we can test // SSL_MAX_EXTENSIONS for the presence of SSL_HandshakeNegotiatedExtension. #if defined(SSL_MAX_EXTENSIONS) - PRBool received_renego_info; - if (SSL_HandshakeNegotiatedExtension(nss_fd_, ssl_renegotiation_info_xtn, - &received_renego_info) == SECSuccess && - !received_renego_info) { - VLOG(1) << "The server " << hostname_ - << " does not support the TLS renegotiation_info extension."; + PRBool peer_supports_renego_ext; + ok = SSL_HandshakeNegotiatedExtension(nss_fd_, ssl_renegotiation_info_xtn, + &peer_supports_renego_ext); + if (ok == SECSuccess) { + if (!peer_supports_renego_ext) { + 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_ + << " does not support the TLS renegotiation_info extension."; + } + UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported", + peer_supports_renego_ext, 2); } #endif + + if (ssl_config_.ssl3_fallback) + ssl_connection_status_ |= SSL_CONNECTION_SSL3_FALLBACK; } void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) { @@ -1095,50 +1138,23 @@ void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) { return; } - SSLChannelInfo channel_info; - SECStatus ok = SSL_GetChannelInfo(nss_fd_, - &channel_info, sizeof(channel_info)); - if (ok == SECSuccess && - channel_info.length == sizeof(channel_info) && - channel_info.cipherSuite) { - SSLCipherSuiteInfo cipher_info; - ok = SSL_GetCipherSuiteInfo(channel_info.cipherSuite, - &cipher_info, sizeof(cipher_info)); - if (ok == SECSuccess) { - ssl_info->security_bits = cipher_info.effectiveKeyBits; - } else { - ssl_info->security_bits = -1; - LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError() - << " for cipherSuite " << channel_info.cipherSuite; - } - ssl_info->connection_status |= - (((int)channel_info.cipherSuite) & SSL_CONNECTION_CIPHERSUITE_MASK) << - SSL_CONNECTION_CIPHERSUITE_SHIFT; - - ssl_info->connection_status |= - (((int)channel_info.compressionMethod) & - SSL_CONNECTION_COMPRESSION_MASK) << - SSL_CONNECTION_COMPRESSION_SHIFT; - - UpdateServerCert(); - } ssl_info->cert_status = server_cert_verify_result_.cert_status; DCHECK(server_cert_ != NULL); ssl_info->cert = server_cert_; + ssl_info->connection_status = ssl_connection_status_; - PRBool peer_supports_renego_ext; - ok = SSL_HandshakeNegotiatedExtension(nss_fd_, ssl_renegotiation_info_xtn, - &peer_supports_renego_ext); + PRUint16 cipher_suite = + SSLConnectionStatusToCipherSuite(ssl_connection_status_); + SSLCipherSuiteInfo cipher_info; + SECStatus ok = SSL_GetCipherSuiteInfo(cipher_suite, + &cipher_info, sizeof(cipher_info)); if (ok == SECSuccess) { - if (!peer_supports_renego_ext) - ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION; - UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported", - (int)peer_supports_renego_ext, 2); + ssl_info->security_bits = cipher_info.effectiveKeyBits; + } else { + ssl_info->security_bits = -1; + LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError() + << " for cipherSuite " << cipher_suite; } - - if (ssl_config_.ssl3_fallback) - ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK; - LeaveFunction(""); } @@ -1798,8 +1814,7 @@ void SSLClientSocketNSS::HandshakeCallback(PRFileDesc* socket, that->handshake_callback_called_ = true; that->UpdateServerCert(); - - that->CheckSecureRenegotiation(); + that->UpdateConnectionStatus(); } int SSLClientSocketNSS::DoSnapStartLoadInfo() { @@ -2218,6 +2233,9 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) { result = OK; } + if (result == OK) + 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. @@ -2286,4 +2304,36 @@ int SSLClientSocketNSS::DoPayloadWrite() { return rv; } +void SSLClientSocketNSS::LogConnectionTypeMetrics() const { + UpdateConnectionTypeHistograms(CONNECTION_SSL); + if (server_cert_verify_result_.has_md5) + UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5); + if (server_cert_verify_result_.has_md2) + UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2); + if (server_cert_verify_result_.has_md4) + UpdateConnectionTypeHistograms(CONNECTION_SSL_MD4); + if (server_cert_verify_result_.has_md5_ca) + UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5_CA); + if (server_cert_verify_result_.has_md2_ca) + UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA); + int ssl_version = SSLConnectionStatusToVersion(ssl_connection_status_); + switch (ssl_version) { + case SSL_CONNECTION_VERSION_SSL2: + UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL2); + break; + case SSL_CONNECTION_VERSION_SSL3: + UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL3); + break; + case SSL_CONNECTION_VERSION_TLS1: + UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1); + break; + case SSL_CONNECTION_VERSION_TLS1_1: + UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_1); + break; + case SSL_CONNECTION_VERSION_TLS1_2: + UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_2); + break; + }; +} + } // namespace net diff --git a/net/socket/ssl_client_socket_nss.h b/net/socket/ssl_client_socket_nss.h index ce5fef8..a0c79fb 100644 --- a/net/socket/ssl_client_socket_nss.h +++ b/net/socket/ssl_client_socket_nss.h @@ -50,7 +50,7 @@ class SSLClientSocketNSS : public SSLClientSocket { virtual void GetSSLInfo(SSLInfo* ssl_info); virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info); virtual NextProtoStatus GetNextProto(std::string* proto); - virtual void UseDNSSEC(DNSSECProvider*); + virtual void UseDNSSEC(DNSSECProvider* provider); // ClientSocket methods: virtual int Connect(CompletionCallback* callback); @@ -83,7 +83,7 @@ class SSLClientSocketNSS : public SSLClientSocket { static X509Certificate::OSCertHandle CreateOSCert(const SECItem& der_cert); #endif X509Certificate* UpdateServerCert(); - void CheckSecureRenegotiation() const; + void UpdateConnectionStatus(); void DoReadCallback(int result); void DoWriteCallback(int result); void DoConnectCallback(int result); @@ -105,6 +105,7 @@ class SSLClientSocketNSS : public SSLClientSocket { int DoVerifyCertComplete(int result); int DoPayloadRead(); int DoPayloadWrite(); + void LogConnectionTypeMetrics() const; int Init(); void SaveSnapStartInfo(); bool LoadSnapStartInfo(); @@ -166,6 +167,7 @@ class SSLClientSocketNSS : public SSLClientSocket { scoped_refptr<X509Certificate> server_cert_; CERTCertificate* server_cert_nss_; CertVerifyResult server_cert_verify_result_; + int ssl_connection_status_; // Stores client authentication information between ClientAuthHandler and // GetSSLCertRequestInfo calls. |