diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-26 13:56:57 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-26 13:56:57 +0000 |
commit | 98f397e9a7720f1476e37b0966c9ad70ea4deebc (patch) | |
tree | 9e7374a3d50f0abc764343981c8b071850ff3c8d /net | |
parent | abf23550d6399dc647c984f9135447f658bbaf35 (diff) | |
download | chromium_src-98f397e9a7720f1476e37b0966c9ad70ea4deebc.zip chromium_src-98f397e9a7720f1476e37b0966c9ad70ea4deebc.tar.gz chromium_src-98f397e9a7720f1476e37b0966c9ad70ea4deebc.tar.bz2 |
net: always save certs and trigger verify in SSLHostInfo.
(This is still behind --enable-snap-start because the SSLHostInfo's
don't get created without it.)
Have ssl_client_socket_nss always save certificates to the SSLHostInfo
and have the SSLHostInfo kick off a validation as soon as possible if
it has the certificates.
For now the validation just primes the OCSP cache and isn't tied into
anything else. In future patches, the SSL socket will compare the
actual certificates against the predicted certificates and avoid a
second validation if they match.
BUG=none
TEST=none
http://codereview.chromium.org/3968003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63887 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/http/disk_cache_based_ssl_host_info.cc | 7 | ||||
-rw-r--r-- | net/http/disk_cache_based_ssl_host_info.h | 7 | ||||
-rw-r--r-- | net/http/http_cache.cc | 5 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 13 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_pool.cc | 3 | ||||
-rw-r--r-- | net/socket/ssl_host_info.cc | 48 | ||||
-rw-r--r-- | net/socket/ssl_host_info.h | 34 |
7 files changed, 102 insertions, 15 deletions
diff --git a/net/http/disk_cache_based_ssl_host_info.cc b/net/http/disk_cache_based_ssl_host_info.cc index 10b2e15..cd1cac8 100644 --- a/net/http/disk_cache_based_ssl_host_info.cc +++ b/net/http/disk_cache_based_ssl_host_info.cc @@ -13,8 +13,11 @@ namespace net { DiskCacheBasedSSLHostInfo::DiskCacheBasedSSLHostInfo( - const std::string& hostname, HttpCache* http_cache) - : callback_(new CancelableCompletionCallback<DiskCacheBasedSSLHostInfo>( + const std::string& hostname, + const SSLConfig& ssl_config, + HttpCache* http_cache) + : SSLHostInfo(hostname, ssl_config), + callback_(new CancelableCompletionCallback<DiskCacheBasedSSLHostInfo>( ALLOW_THIS_IN_INITIALIZER_LIST(this), &DiskCacheBasedSSLHostInfo::DoLoop)), state_(GET_BACKEND), diff --git a/net/http/disk_cache_based_ssl_host_info.h b/net/http/disk_cache_based_ssl_host_info.h index 51a4a91..1d53b90 100644 --- a/net/http/disk_cache_based_ssl_host_info.h +++ b/net/http/disk_cache_based_ssl_host_info.h @@ -16,8 +16,9 @@ namespace net { -class IOBuffer; class HttpCache; +class IOBuffer; +struct SSLConfig; // DiskCacheBasedSSLHostInfo fetches information about an SSL host from our // standard disk cache. Since the information is defined to be non-sensitive, @@ -25,7 +26,9 @@ class HttpCache; class DiskCacheBasedSSLHostInfo : public SSLHostInfo, public NonThreadSafe { public: - DiskCacheBasedSSLHostInfo(const std::string& hostname, HttpCache* http_cache); + DiskCacheBasedSSLHostInfo(const std::string& hostname, + const SSLConfig& ssl_config, + HttpCache* http_cache); // Implementation of SSLHostInfo virtual void Start(); diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc index d4a869f..0372222 100644 --- a/net/http/http_cache.cc +++ b/net/http/http_cache.cc @@ -267,8 +267,9 @@ class HttpCache::SSLHostInfoFactoryAdaptor : public SSLHostInfoFactory { : http_cache_(http_cache) { } - SSLHostInfo* GetForHost(const std::string& hostname) { - return new DiskCacheBasedSSLHostInfo(hostname, http_cache_); + SSLHostInfo* GetForHost(const std::string& hostname, + const SSLConfig& ssl_config) { + return new DiskCacheBasedSSLHostInfo(hostname, ssl_config, http_cache_); } private: diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index abbd2fa..fc9a360 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -451,17 +451,18 @@ void SSLClientSocketNSS::SaveSnapStartInfo() { NOTREACHED(); return; } - // If the server doesn't support Snap Start then |hello_data_len| is zero. - if (!hello_data_len) - return; if (hello_data_len > std::numeric_limits<uint16>::max()) return; SSLHostInfo::State* state = ssl_host_info_->mutable_state(); state->server_hello = std::string(reinterpret_cast<const char *>(hello_data), hello_data_len); - state->npn_valid = true; - state->npn_status = GetNextProto(&state->npn_protocol); + if (hello_data_len > 0) { + state->npn_valid = true; + state->npn_status = GetNextProto(&state->npn_protocol); + } else { + state->npn_valid = false; + } // TODO(wtc): CERT_GetCertChainFromCert might not return the same cert chain // that the Certificate message actually contained. http://crbug.com/48854 @@ -470,6 +471,7 @@ void SSLClientSocketNSS::SaveSnapStartInfo() { if (!cert_list) return; + state->certs.clear(); for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); !CERT_LIST_END(node, cert_list); node = CERT_LIST_NEXT(node)) { @@ -479,6 +481,7 @@ void SSLClientSocketNSS::SaveSnapStartInfo() { } if (node->cert->isRoot == PR_TRUE) continue; + state->certs.push_back(std::string( reinterpret_cast<char*>(node->cert->derCert.data), node->cert->derCert.len)); diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc index 98e3b09..bd4a09b 100644 --- a/net/socket/ssl_client_socket_pool.cc +++ b/net/socket/ssl_client_socket_pool.cc @@ -193,7 +193,8 @@ int SSLConnectJob::DoTCPConnect() { if (ssl_host_info_factory_ && SSLConfigService::snap_start_enabled()) { ssl_host_info_.reset( - ssl_host_info_factory_->GetForHost(params_->hostname())); + ssl_host_info_factory_->GetForHost(params_->hostname(), + params_->ssl_config())); } if (ssl_host_info_.get()) { // This starts fetching the SSL host info from the disk cache for Snap diff --git a/net/socket/ssl_host_info.cc b/net/socket/ssl_host_info.cc index 9056fef..ec97b66 100644 --- a/net/socket/ssl_host_info.cc +++ b/net/socket/ssl_host_info.cc @@ -4,6 +4,10 @@ #include "net/socket/ssl_host_info.h" +#include "base/string_piece.h" +#include "net/base/cert_verifier.h" +#include "net/base/ssl_config_service.h" +#include "net/base/x509_certificate.h" #include "net/socket/ssl_client_socket.h" #include "net/socket/ssl_host_info.pb.h" @@ -16,7 +20,16 @@ SSLHostInfo::State::State() SSLHostInfo::State::~State() {} -SSLHostInfo::SSLHostInfo() { +SSLHostInfo::SSLHostInfo( + const std::string& hostname, + const SSLConfig& ssl_config) + : hostname_(hostname), + cert_valid_(false), + rev_checking_enabled_(ssl_config.rev_checking_enabled), + verify_ev_cert_(ssl_config.verify_ev_cert), + callback_(new CancelableCompletionCallback<SSLHostInfo>( + ALLOW_THIS_IN_INITIALIZER_LIST(this), + &SSLHostInfo::VerifyCallback)) { state_.npn_valid = false; } @@ -67,6 +80,7 @@ bool SSLHostInfo::Parse(const std::string& data) { state->certs.clear(); state->server_hello.clear(); state->npn_valid = false; + cert_valid_ = false; if (!proto.ParseFromString(data)) return false; @@ -81,6 +95,26 @@ bool SSLHostInfo::Parse(const std::string& data) { state->npn_protocol = proto.npn_protocol(); } + if (state->certs.size() > 0) { + std::vector<base::StringPiece> der_certs(state->certs.size()); + for (size_t i = 0; i < state->certs.size(); i++) + der_certs[i] = state->certs[i]; + cert_ = X509Certificate::CreateFromDERCertChain(der_certs); + if (cert_.get()) { + int flags = 0; + if (verify_ev_cert_) + flags |= X509Certificate::VERIFY_EV_CERT; + if (rev_checking_enabled_) + flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; + verifier_.reset(new CertVerifier); + VLOG(1) << "Kicking off validation for " << hostname_; + if (verifier_->Verify(cert_.get(), hostname_, flags, + &cert_verify_result_, callback_) == OK) { + cert_valid_ = true; + } + } + } + return true; } @@ -102,6 +136,18 @@ std::string SSLHostInfo::Serialize() const { return proto.SerializeAsString(); } +bool SSLHostInfo::cert_valid() const { + return cert_valid_; +} + +const CertVerifyResult& SSLHostInfo::cert_verify_result() const { + return cert_verify_result_; +} + +void SSLHostInfo::VerifyCallback(int rv) { + cert_valid_ = rv == OK; +} + SSLHostInfoFactory::~SSLHostInfoFactory() {} } // namespace net diff --git a/net/socket/ssl_host_info.h b/net/socket/ssl_host_info.h index ea82f34..6d545a9 100644 --- a/net/socket/ssl_host_info.h +++ b/net/socket/ssl_host_info.h @@ -9,18 +9,24 @@ #include <vector> #include "base/ref_counted.h" +#include "base/scoped_ptr.h" +#include "net/base/cert_verify_result.h" #include "net/base/completion_callback.h" #include "net/socket/ssl_client_socket.h" namespace net { +class CertVerifier; +class X509Certificate; +struct SSLConfig; + // SSLHostInfo is an interface for fetching information about an SSL server. // This information may be stored on disk so does not include keys or session // information etc. Primarily it's intended for caching the server's // certificates. class SSLHostInfo { public: - SSLHostInfo(); + SSLHostInfo(const std::string& hostname, const SSLConfig& ssl_config); virtual ~SSLHostInfo(); // Start will commence the lookup. This must be called before any other @@ -72,6 +78,14 @@ class SSLHostInfo { const State& state() const; State* mutable_state(); + // This is true if state().certs.size() > 0 and state().certs[0] has been + // verified for |hostname_|. + bool cert_valid() const; + + // If |cert_valid()| returns true, then this contains the result of verifying + // the certificate. + const CertVerifyResult& cert_verify_result() const; + protected: // Parse parses an opaque blob of data and fills out the public member fields // of this object. It returns true iff the parse was successful. The public @@ -79,6 +93,21 @@ class SSLHostInfo { bool Parse(const std::string& data); std::string Serialize() const; State state_; + + private: + // This is the callback function which the CertVerifier calls via |callback_|. + void VerifyCallback(int rv); + + // This is the hostname that we'll validate the certificates against. + const std::string hostname_; + bool cert_valid_; // see the comments for |cert_valid|. + // These two members are taken from the SSLConfig. + bool rev_checking_enabled_; + bool verify_ev_cert_; + CertVerifyResult cert_verify_result_; + scoped_ptr<CertVerifier> verifier_; + scoped_refptr<X509Certificate> cert_; + scoped_refptr<CancelableCompletionCallback<SSLHostInfo> > callback_; }; class SSLHostInfoFactory { @@ -87,7 +116,8 @@ class SSLHostInfoFactory { // GetForHost returns a fresh, allocated SSLHostInfo for the given hostname // or NULL on failure. - virtual SSLHostInfo* GetForHost(const std::string& hostname) = 0; + virtual SSLHostInfo* GetForHost(const std::string& hostname, + const SSLConfig& ssl_config) = 0; }; } // namespace net |