diff options
-rw-r--r-- | chrome/browser/renderer_host/resource_dispatcher_host.cc | 16 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_manager.cc | 17 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_manager.h | 6 | ||||
-rw-r--r-- | chrome/browser/tab_contents/navigation_entry.cc | 1 | ||||
-rw-r--r-- | chrome/browser/tab_contents/navigation_entry.h | 8 | ||||
-rw-r--r-- | chrome/browser/tab_contents/provisional_load_details.cc | 4 | ||||
-rw-r--r-- | chrome/browser/tab_contents/provisional_load_details.h | 3 | ||||
-rw-r--r-- | chrome/browser/tab_contents/render_view_context_menu.cc | 6 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents.cc | 5 | ||||
-rw-r--r-- | net/base/ssl_config_service.h | 5 | ||||
-rw-r--r-- | net/base/ssl_connection_status_flags.h | 31 | ||||
-rw-r--r-- | net/base/ssl_info.h | 9 | ||||
-rw-r--r-- | net/http/http_network_transaction.cc | 5 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_mac.cc | 4 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 15 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_win.cc | 6 |
16 files changed, 119 insertions, 22 deletions
diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.cc b/chrome/browser/renderer_host/resource_dispatcher_host.cc index 2d1e7fc..253c5ba 100644 --- a/chrome/browser/renderer_host/resource_dispatcher_host.cc +++ b/chrome/browser/renderer_host/resource_dispatcher_host.cc @@ -1038,14 +1038,16 @@ bool ResourceDispatcherHost::CompleteResponseStarted(URLRequest* request) { CertStore::GetSharedInstance()->StoreCert(request->ssl_info().cert, info->child_id()); response->response_head.security_info = - SSLManager::SerializeSecurityInfo(cert_id, - request->ssl_info().cert_status, - request->ssl_info().security_bits); + SSLManager::SerializeSecurityInfo( + cert_id, request->ssl_info().cert_status, + request->ssl_info().security_bits, + request->ssl_info().connection_status); } else { // We should not have any SSL state. DCHECK(!request->ssl_info().cert_status && (request->ssl_info().security_bits == -1 || - request->ssl_info().security_bits == 0)); + request->ssl_info().security_bits == 0) && + !request->ssl_info().connection_status); } NotifyResponseStarted(request, info->child_id()); @@ -1375,9 +1377,9 @@ void ResourceDispatcherHost::OnResponseCompleted(URLRequest* request) { if (ssl_info.cert != NULL) { int cert_id = CertStore::GetSharedInstance()->StoreCert(ssl_info.cert, info->child_id()); - security_info = SSLManager::SerializeSecurityInfo(cert_id, - ssl_info.cert_status, - ssl_info.security_bits); + security_info = SSLManager::SerializeSecurityInfo( + cert_id, ssl_info.cert_status, ssl_info.security_bits, + ssl_info.connection_status); } if (info->resource_handler()->OnResponseCompleted(info->request_id(), diff --git a/chrome/browser/ssl/ssl_manager.cc b/chrome/browser/ssl/ssl_manager.cc index dbff09e..d328d6e 100644 --- a/chrome/browser/ssl/ssl_manager.cc +++ b/chrome/browser/ssl/ssl_manager.cc @@ -59,11 +59,13 @@ void SSLManager::NotifySSLInternalStateChanged() { // static std::string SSLManager::SerializeSecurityInfo(int cert_id, int cert_status, - int security_bits) { + int security_bits, + int ssl_connection_status) { Pickle pickle; pickle.WriteInt(cert_id); pickle.WriteInt(cert_status); pickle.WriteInt(security_bits); + pickle.WriteInt(ssl_connection_status); return std::string(static_cast<const char*>(pickle.data()), pickle.size()); } @@ -71,13 +73,15 @@ std::string SSLManager::SerializeSecurityInfo(int cert_id, bool SSLManager::DeserializeSecurityInfo(const std::string& state, int* cert_id, int* cert_status, - int* security_bits) { + int* security_bits, + int* ssl_connection_status) { DCHECK(cert_id && cert_status && security_bits); if (state.empty()) { // No SSL used. *cert_id = 0; *cert_status = 0; *security_bits = -1; + *ssl_connection_status = 0; return false; } @@ -85,7 +89,8 @@ bool SSLManager::DeserializeSecurityInfo(const std::string& state, void * iter = NULL; return pickle.ReadInt(&iter, cert_id) && pickle.ReadInt(&iter, cert_status) && - pickle.ReadInt(&iter, security_bits); + pickle.ReadInt(&iter, security_bits) && + pickle.ReadInt(&iter, ssl_connection_status); } // static @@ -134,11 +139,12 @@ void SSLManager::DidCommitProvisionalLoad( if (details->is_main_frame) { if (entry) { // Decode the security details. - int ssl_cert_id, ssl_cert_status, ssl_security_bits; + int ssl_cert_id, ssl_cert_status, ssl_security_bits, ssl_connection_status; DeserializeSecurityInfo(details->serialized_security_info, &ssl_cert_id, &ssl_cert_status, - &ssl_security_bits); + &ssl_security_bits, + &ssl_connection_status); // We may not have an entry if this is a navigation to an initial blank // page. Reset the SSL information and add the new data we have. @@ -146,6 +152,7 @@ void SSLManager::DidCommitProvisionalLoad( entry->ssl().set_cert_id(ssl_cert_id); entry->ssl().set_cert_status(ssl_cert_status); entry->ssl().set_security_bits(ssl_security_bits); + entry->ssl().set_connection_status(ssl_connection_status); } backend_.ShowPendingMessages(); } diff --git a/chrome/browser/ssl/ssl_manager.h b/chrome/browser/ssl/ssl_manager.h index 7ee110e..e9916b3 100644 --- a/chrome/browser/ssl/ssl_manager.h +++ b/chrome/browser/ssl/ssl_manager.h @@ -56,11 +56,13 @@ class SSLManager : public NotificationObserver { // Convenience methods for serializing/deserializing the security info. static std::string SerializeSecurityInfo(int cert_id, int cert_status, - int security_bits); + int security_bits, + int connection_status); static bool DeserializeSecurityInfo(const std::string& state, int* cert_id, int* cert_status, - int* security_bits); + int* security_bits, + int* connection_status); // Returns "<organization_name> [<country>]". static std::wstring GetEVCertName(const net::X509Certificate& cert); diff --git a/chrome/browser/tab_contents/navigation_entry.cc b/chrome/browser/tab_contents/navigation_entry.cc index 4ce5bda..0fb4777 100644 --- a/chrome/browser/tab_contents/navigation_entry.cc +++ b/chrome/browser/tab_contents/navigation_entry.cc @@ -29,6 +29,7 @@ NavigationEntry::SSLStatus::SSLStatus() cert_id_(0), cert_status_(0), security_bits_(-1), + connection_status_(0), content_status_(NORMAL_CONTENT) { } diff --git a/chrome/browser/tab_contents/navigation_entry.h b/chrome/browser/tab_contents/navigation_entry.h index 1faee15..341ebeb 100644 --- a/chrome/browser/tab_contents/navigation_entry.h +++ b/chrome/browser/tab_contents/navigation_entry.h @@ -102,6 +102,13 @@ class NavigationEntry { return (content_status_ & RAN_INSECURE_CONTENT) != 0; } + void set_connection_status(int connection_status) { + connection_status_ = connection_status; + } + int connection_status() const { + return connection_status_; + } + // Raw accessors for all the content status flags. This contains a // combination of any of the ContentStatusFlags defined above. It is used // by some tests for checking and for certain copying. Use the per-status @@ -119,6 +126,7 @@ class NavigationEntry { int cert_id_; int cert_status_; int security_bits_; + int connection_status_; int content_status_; // Copy and assignment is explicitly allowed for this class. diff --git a/chrome/browser/tab_contents/provisional_load_details.cc b/chrome/browser/tab_contents/provisional_load_details.cc index f144d0a..3bea977 100644 --- a/chrome/browser/tab_contents/provisional_load_details.cc +++ b/chrome/browser/tab_contents/provisional_load_details.cc @@ -19,9 +19,11 @@ ProvisionalLoadDetails::ProvisionalLoadDetails(bool is_main_frame, ssl_cert_id_(0), ssl_cert_status_(0), ssl_security_bits_(-1), + ssl_connection_status_(0), is_content_filtered_(is_content_filtered) { SSLManager::DeserializeSecurityInfo(security_info, &ssl_cert_id_, &ssl_cert_status_, - &ssl_security_bits_); + &ssl_security_bits_, + &ssl_connection_status_); } diff --git a/chrome/browser/tab_contents/provisional_load_details.h b/chrome/browser/tab_contents/provisional_load_details.h index ce4f5da..4f6abad 100644 --- a/chrome/browser/tab_contents/provisional_load_details.h +++ b/chrome/browser/tab_contents/provisional_load_details.h @@ -43,6 +43,8 @@ class ProvisionalLoadDetails { int ssl_security_bits() const { return ssl_security_bits_; } + int ssl_connection_status() const { return ssl_connection_status_; } + bool is_content_filtered() const { return is_content_filtered_; } private: @@ -53,6 +55,7 @@ class ProvisionalLoadDetails { int ssl_cert_id_; int ssl_cert_status_; int ssl_security_bits_; + int ssl_connection_status_; bool is_content_filtered_; DISALLOW_COPY_AND_ASSIGN(ProvisionalLoadDetails); diff --git a/chrome/browser/tab_contents/render_view_context_menu.cc b/chrome/browser/tab_contents/render_view_context_menu.cc index 101d43f..c912965 100644 --- a/chrome/browser/tab_contents/render_view_context_menu.cc +++ b/chrome/browser/tab_contents/render_view_context_menu.cc @@ -1169,14 +1169,16 @@ void RenderViewContextMenu::ExecuteCommand(int id) { // Deserialize the SSL info. NavigationEntry::SSLStatus ssl; if (!params_.security_info.empty()) { - int cert_id, cert_status, security_bits; + int cert_id, cert_status, security_bits, connection_status; SSLManager::DeserializeSecurityInfo(params_.security_info, &cert_id, &cert_status, - &security_bits); + &security_bits, + &connection_status); ssl.set_cert_id(cert_id); ssl.set_cert_status(cert_status); ssl.set_security_bits(security_bits); + ssl.set_connection_status(connection_status); } source_tab_contents_->ShowPageInfo(params_.frame_url, ssl, false); // Don't show the history. diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc index f0dd1d5..963ed7b 100644 --- a/chrome/browser/tab_contents/tab_contents.cc +++ b/chrome/browser/tab_contents/tab_contents.cc @@ -2032,10 +2032,11 @@ void TabContents::DidLoadResourceFromMemoryCache( const std::string& main_frame_origin, const std::string& security_info) { // Send out a notification that we loaded a resource from our memory cache. - int cert_id = 0, cert_status = 0, security_bits = 0; + int cert_id = 0, cert_status = 0, security_bits = 0, connection_status = 0; SSLManager::DeserializeSecurityInfo(security_info, &cert_id, &cert_status, - &security_bits); + &security_bits, + &connection_status); LoadFromMemoryCacheDetails details(url, frame_origin, main_frame_origin, GetRenderProcessHost()->id(), cert_id, cert_status); diff --git a/net/base/ssl_config_service.h b/net/base/ssl_config_service.h index d195039..3f0f479 100644 --- a/net/base/ssl_config_service.h +++ b/net/base/ssl_config_service.h @@ -18,7 +18,8 @@ struct SSLConfig { // Default to SSL 2.0 off, SSL 3.0 on, and TLS 1.0 on. SSLConfig() : rev_checking_enabled(true), ssl2_enabled(false), ssl3_enabled(true), - tls1_enabled(true), send_client_cert(false), verify_ev_cert(false) { + tls1_enabled(true), ssl3_fallback(false), send_client_cert(false), + verify_ev_cert(false) { } bool rev_checking_enabled; // True if server certificate revocation @@ -26,6 +27,8 @@ struct SSLConfig { bool ssl2_enabled; // True if SSL 2.0 is enabled. bool ssl3_enabled; // True if SSL 3.0 is enabled. bool tls1_enabled; // True if TLS 1.0 is enabled. + bool ssl3_fallback; // True if we are falling back to SSL 3.0 (one still + // needs to clear tls1_enabled). // TODO(wtc): move the following members to a new SSLParams structure. They // are not SSL configuration settings. diff --git a/net/base/ssl_connection_status_flags.h b/net/base/ssl_connection_status_flags.h new file mode 100644 index 0000000..2618f57 --- /dev/null +++ b/net/base/ssl_connection_status_flags.h @@ -0,0 +1,31 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_BASE_SSL_CONNECTION_STATUS_FLAGS_H_ +#define NET_BASE_SSL_CONNECTION_STATUS_FLAGS_H_ + +namespace net { + +// Status flags for SSLInfo::connection_status. +enum { + // The lower 16 bits are reserved for the TLS ciphersuite id. + SSL_CONNECTION_CIPHERSUITE_SHIFT = 0, + SSL_CONNECTION_CIPHERSUITE_MASK = 0xffff, + + // The next two bits are reserved for the compression used. + SSL_CONNECTION_COMPRESSION_SHIFT = 16, + SSL_CONNECTION_COMPRESSION_MASK = 3, + + // We fell back to SSLv3 for this connection. + SSL_CONNECTION_SSL3_FALLBACK = 1 << 18, + // The server doesn't support the renegotiation_info extension. + SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION = 1 << 19, + + // 1 << 31 (the sign bit) is reserved so that the SSL connection status will + // never be negative. +}; + +} // namespace net + +#endif // NET_BASE_SSL_CONNECTION_STATUS_FLAGS_H_ diff --git a/net/base/ssl_info.h b/net/base/ssl_info.h index 3fe0ce4..280b497 100644 --- a/net/base/ssl_info.h +++ b/net/base/ssl_info.h @@ -16,12 +16,13 @@ namespace net { // This is really a struct. All members are public. class SSLInfo { public: - SSLInfo() : cert_status(0), security_bits(-1) { } + SSLInfo() : cert_status(0), security_bits(-1), connection_status(0) { } void Reset() { cert = NULL; - security_bits = -1; cert_status = 0; + security_bits = -1; + connection_status = 0; } bool is_valid() const { return cert != NULL; } @@ -43,6 +44,10 @@ class SSLInfo { // 0 means the connection is not encrypted. // -1 means the security strength is unknown. int security_bits; + + // Bitmask of information about the SSL connection itself. See + // ssl_connection_status_flags.h for values. + int connection_status; }; } // namespace net diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index fed8af8..1d58863 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -22,6 +22,7 @@ #include "net/base/net_errors.h" #include "net/base/net_util.h" #include "net/base/ssl_cert_request_info.h" +#include "net/base/ssl_connection_status_flags.h" #include "net/base/upload_data_stream.h" #include "net/http/http_auth.h" #include "net/http/http_auth_handler.h" @@ -1084,9 +1085,13 @@ int HttpNetworkTransaction::DoSSLConnect() { if (ContainsKey(*g_tls_intolerant_servers, GetHostAndPort(request_->url))) { LOG(WARNING) << "Falling back to SSLv3 because host is TLS intolerant: " << GetHostAndPort(request_->url); + ssl_config_.ssl3_fallback = true; ssl_config_.tls1_enabled = false; } + UMA_HISTOGRAM_ENUMERATION("Net.ConnectionUsedSSLv3Fallback", + (int) ssl_config_.ssl3_fallback, 2); + if (request_->load_flags & LOAD_VERIFY_EV_CERT) ssl_config_.verify_ev_cert = true; diff --git a/net/socket/ssl_client_socket_mac.cc b/net/socket/ssl_client_socket_mac.cc index f1d2278..325df61 100644 --- a/net/socket/ssl_client_socket_mac.cc +++ b/net/socket/ssl_client_socket_mac.cc @@ -18,6 +18,7 @@ #include "net/base/net_errors.h" #include "net/base/net_log.h" #include "net/base/ssl_cert_request_info.h" +#include "net/base/ssl_connection_status_flags.h" #include "net/base/ssl_info.h" // Welcome to Mac SSL. We've been waiting for you. @@ -652,6 +653,9 @@ void SSLClientSocketMac::GetSSLInfo(SSLInfo* ssl_info) { OSStatus status = SSLGetNegotiatedCipher(ssl_context_, &suite); if (!status) ssl_info->security_bits = KeySizeOfCipherSuite(suite); + + if (ssl_config_.ssl3_fallback) + ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK; } void SSLClientSocketMac::GetSSLCertRequestInfo( diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index 285499e..5226c56 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -60,6 +60,7 @@ #include <pk11pub.h> #include "base/compiler_specific.h" +#include "base/histogram.h" #include "base/logging.h" #include "base/nss_util.h" #include "base/singleton.h" @@ -70,6 +71,7 @@ #include "net/base/net_log.h" #include "net/base/net_errors.h" #include "net/base/ssl_cert_request_info.h" +#include "net/base/ssl_connection_status_flags.h" #include "net/base/ssl_info.h" #include "net/base/sys_addrinfo.h" #include "net/ocsp/nss_ocsp.h" @@ -789,6 +791,19 @@ void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) { DCHECK(server_cert_ != NULL); ssl_info->cert = server_cert_; + 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_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION; + UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported", + (int)peer_supports_renego_ext, 2); + } + + if (ssl_config_.ssl3_fallback) + ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK; + LeaveFunction(""); } diff --git a/net/socket/ssl_client_socket_win.cc b/net/socket/ssl_client_socket_win.cc index a0da5f4..9a4be48 100644 --- a/net/socket/ssl_client_socket_win.cc +++ b/net/socket/ssl_client_socket_win.cc @@ -17,6 +17,7 @@ #include "net/base/net_log.h" #include "net/base/net_errors.h" #include "net/base/ssl_cert_request_info.h" +#include "net/base/ssl_connection_status_flags.h" #include "net/base/ssl_info.h" #pragma comment(lib, "secur32.lib") @@ -335,6 +336,8 @@ SSLClientSocketWin::~SSLClientSocketWin() { } void SSLClientSocketWin::GetSSLInfo(SSLInfo* ssl_info) { + ssl_info->Reset(); + if (!server_cert_) return; @@ -349,6 +352,9 @@ void SSLClientSocketWin::GetSSLInfo(SSLInfo* ssl_info) { // normalized. ssl_info->security_bits = connection_info.dwCipherStrength; } + + if (ssl_config_.ssl3_fallback) + ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK; } void SSLClientSocketWin::GetSSLCertRequestInfo( |