summaryrefslogtreecommitdiffstats
path: root/net/socket
diff options
context:
space:
mode:
authorwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-27 23:28:35 +0000
committerwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-27 23:28:35 +0000
commit757f2e2ba0c1fa7100461745bfac865e3da1d976 (patch)
tree5ada8a2ea4122f949104663b3a02c54c3ba31720 /net/socket
parent017f19b5f1af1702252655b4b52bdcd9ab7a0de2 (diff)
downloadchromium_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.cc156
-rw-r--r--net/socket/ssl_client_socket_nss.h6
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.