1731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Use of this source code is governed by a BSD-style license that can be 3731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// found in the LICENSE file. 4731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 5731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/socket/ssl_host_info.h" 6731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 7513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/metrics/histogram.h" 821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/pickle.h" 9513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/string_piece.h" 103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "net/base/dns_util.h" 113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "net/base/dnsrr_resolver.h" 12513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "net/base/ssl_config_service.h" 13513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "net/base/x509_certificate.h" 14731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/socket/ssl_client_socket.h" 15731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 16731df977c0511bca2206b5f333555b1205ff1f43Iain Merricknamespace net { 17731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSSLHostInfo::State::State() {} 19513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 20513209b27ff55e2841eac0e4120199c23acce758Ben MurdochSSLHostInfo::State::~State() {} 21513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 2221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid SSLHostInfo::State::Clear() { 2321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen certs.clear(); 2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 2521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 26513209b27ff55e2841eac0e4120199c23acce758Ben MurdochSSLHostInfo::SSLHostInfo( 27513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::string& hostname, 2821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const SSLConfig& ssl_config, 2921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifier* cert_verifier) 304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch : cert_verification_complete_(false), 314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch cert_verification_error_(ERR_CERT_INVALID), 324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch hostname_(hostname), 33513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch cert_parsing_failed_(false), 34513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch cert_verification_callback_(NULL), 35513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch rev_checking_enabled_(ssl_config.rev_checking_enabled), 36513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch verify_ev_cert_(ssl_config.verify_ev_cert), 3721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen verifier_(cert_verifier), 38513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch callback_(new CancelableCompletionCallback<SSLHostInfo>( 39513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ALLOW_THIS_IN_INITIALIZER_LIST(this), 403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen &SSLHostInfo::VerifyCallback)), 413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen dnsrr_resolver_(NULL), 423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen dns_callback_(NULL), 433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen dns_handle_(DnsRRResolver::kInvalidHandle) { 44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 463f50c38dc070f4bb515c1b64450dae14f316474eKristian MonsenSSLHostInfo::~SSLHostInfo() { 473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (dns_handle_ != DnsRRResolver::kInvalidHandle) { 483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen dnsrr_resolver_->CancelResolve(dns_handle_); 493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen delete dns_callback_; 503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid SSLHostInfo::StartDnsLookup(DnsRRResolver* dnsrr_resolver) { 543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen dnsrr_resolver_ = dnsrr_resolver; 5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Note: currently disabled. 563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 57731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 58731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickconst SSLHostInfo::State& SSLHostInfo::state() const { 59731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return state_; 60731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 61731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 62731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickSSLHostInfo::State* SSLHostInfo::mutable_state() { 63731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return &state_; 64731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 65731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 66731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool SSLHostInfo::Parse(const std::string& data) { 67731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick State* state = mutable_state(); 68731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 6921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen state->Clear(); 70513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch cert_verification_complete_ = false; 71731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 7221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen bool r = ParseInner(data); 7321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!r) 7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen state->Clear(); 7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return r; 7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 7721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 7821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool SSLHostInfo::ParseInner(const std::string& data) { 7921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen State* state = mutable_state(); 8021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen Pickle p(data.data(), data.size()); 8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void* iter = NULL; 8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 8421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int num_der_certs; 8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!p.ReadInt(&iter, &num_der_certs) || 8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen num_der_certs < 0) { 87731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return false; 8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen for (int i = 0; i < num_der_certs; i++) { 9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::string der_cert; 9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!p.ReadString(&iter, &der_cert)) 9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 9421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen state->certs.push_back(der_cert); 9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 9621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string throwaway_string; 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool throwaway_bool; 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!p.ReadString(&iter, &throwaway_string)) 10021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 10121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!p.ReadBool(&iter, &throwaway_bool)) 10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (throwaway_bool) { 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int throwaway_int; 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!p.ReadInt(&iter, &throwaway_int) || 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen !p.ReadString(&iter, &throwaway_string)) { 10921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 111731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 112731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!state->certs.empty()) { 114513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::vector<base::StringPiece> der_certs(state->certs.size()); 115513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (size_t i = 0; i < state->certs.size(); i++) 116513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch der_certs[i] = state->certs[i]; 117513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch cert_ = X509Certificate::CreateFromDERCertChain(der_certs); 118513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (cert_.get()) { 119513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int flags = 0; 120513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (verify_ev_cert_) 121513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch flags |= X509Certificate::VERIFY_EV_CERT; 122513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (rev_checking_enabled_) 123513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; 124513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "Kicking off verification for " << hostname_; 125513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch verification_start_time_ = base::TimeTicks::Now(); 12621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen verification_end_time_ = base::TimeTicks(); 12721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int rv = verifier_.Verify(cert_.get(), hostname_, flags, 12821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen &cert_verify_result_, callback_); 12921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (rv != ERR_IO_PENDING) 13021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen VerifyCallback(rv); 131513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 132513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch cert_parsing_failed_ = true; 133513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(!cert_verification_callback_); 134513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 135513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 136513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 137731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return true; 138731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 139731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 140731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstd::string SSLHostInfo::Serialize() const { 14121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen Pickle p(sizeof(Pickle::Header)); 14221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 14321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen static const unsigned kMaxCertificatesSize = 32 * 1024; 14421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen unsigned der_certs_size = 0; 145731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 146731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (std::vector<std::string>::const_iterator 147731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick i = state_.certs.begin(); i != state_.certs.end(); i++) { 14821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen der_certs_size += i->size(); 14921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 15021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 15121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // We don't care to save the certificates over a certain size. 15221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (der_certs_size > kMaxCertificatesSize) 15321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return ""; 15421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 15521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!p.WriteInt(state_.certs.size())) 15621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return ""; 15721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 15821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen for (std::vector<std::string>::const_iterator 15921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen i = state_.certs.begin(); i != state_.certs.end(); i++) { 16021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!p.WriteString(*i)) 16121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return ""; 16221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 16321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!p.WriteString("") || 165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen !p.WriteBool(false)) { 16621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return ""; 167731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 168731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 16921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return std::string(reinterpret_cast<const char *>(p.data()), p.size()); 170731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 171731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 172513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst CertVerifyResult& SSLHostInfo::cert_verify_result() const { 173513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return cert_verify_result_; 174513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 175513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 176513209b27ff55e2841eac0e4120199c23acce758Ben Murdochint SSLHostInfo::WaitForCertVerification(CompletionCallback* callback) { 177513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (cert_verification_complete_) 1784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return cert_verification_error_; 179513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(!cert_parsing_failed_); 180513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(!cert_verification_callback_); 181513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(!state_.certs.empty()); 182513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch cert_verification_callback_ = callback; 183513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return ERR_IO_PENDING; 184513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 185513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 186513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid SSLHostInfo::VerifyCallback(int rv) { 187513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(!verification_start_time_.is_null()); 188513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::TimeTicks now = base::TimeTicks::Now(); 189513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const base::TimeDelta duration = now - verification_start_time(); 190513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch UMA_HISTOGRAM_TIMES("Net.SSLHostInfoVerificationTimeMs", duration); 191513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "Verification took " << duration.InMilliseconds() << "ms"; 19221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen verification_end_time_ = now; 193513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch cert_verification_complete_ = true; 1944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch cert_verification_error_ = rv; 195513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (cert_verification_callback_) { 196513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch CompletionCallback* callback = cert_verification_callback_; 197513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch cert_verification_callback_ = NULL; 198513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch callback->Run(rv); 199513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 200513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 201513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 202731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickSSLHostInfoFactory::~SSLHostInfoFactory() {} 203731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 204731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} // namespace net 205