1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/socket/ssl_host_info.h" 6 7 #include "base/metrics/histogram.h" 8 #include "base/pickle.h" 9 #include "base/string_piece.h" 10 #include "net/base/dns_util.h" 11 #include "net/base/dnsrr_resolver.h" 12 #include "net/base/ssl_config_service.h" 13 #include "net/base/x509_certificate.h" 14 #include "net/socket/ssl_client_socket.h" 15 16 namespace net { 17 18 SSLHostInfo::State::State() {} 19 20 SSLHostInfo::State::~State() {} 21 22 void SSLHostInfo::State::Clear() { 23 certs.clear(); 24 } 25 26 SSLHostInfo::SSLHostInfo( 27 const std::string& hostname, 28 const SSLConfig& ssl_config, 29 CertVerifier* cert_verifier) 30 : cert_verification_complete_(false), 31 cert_verification_error_(ERR_CERT_INVALID), 32 hostname_(hostname), 33 cert_parsing_failed_(false), 34 cert_verification_callback_(NULL), 35 rev_checking_enabled_(ssl_config.rev_checking_enabled), 36 verify_ev_cert_(ssl_config.verify_ev_cert), 37 verifier_(cert_verifier), 38 callback_(new CancelableCompletionCallback<SSLHostInfo>( 39 ALLOW_THIS_IN_INITIALIZER_LIST(this), 40 &SSLHostInfo::VerifyCallback)), 41 dnsrr_resolver_(NULL), 42 dns_callback_(NULL), 43 dns_handle_(DnsRRResolver::kInvalidHandle) { 44 } 45 46 SSLHostInfo::~SSLHostInfo() { 47 if (dns_handle_ != DnsRRResolver::kInvalidHandle) { 48 dnsrr_resolver_->CancelResolve(dns_handle_); 49 delete dns_callback_; 50 } 51 } 52 53 void SSLHostInfo::StartDnsLookup(DnsRRResolver* dnsrr_resolver) { 54 dnsrr_resolver_ = dnsrr_resolver; 55 // Note: currently disabled. 56 } 57 58 const SSLHostInfo::State& SSLHostInfo::state() const { 59 return state_; 60 } 61 62 SSLHostInfo::State* SSLHostInfo::mutable_state() { 63 return &state_; 64 } 65 66 bool SSLHostInfo::Parse(const std::string& data) { 67 State* state = mutable_state(); 68 69 state->Clear(); 70 cert_verification_complete_ = false; 71 72 bool r = ParseInner(data); 73 if (!r) 74 state->Clear(); 75 return r; 76 } 77 78 bool SSLHostInfo::ParseInner(const std::string& data) { 79 State* state = mutable_state(); 80 81 Pickle p(data.data(), data.size()); 82 void* iter = NULL; 83 84 int num_der_certs; 85 if (!p.ReadInt(&iter, &num_der_certs) || 86 num_der_certs < 0) { 87 return false; 88 } 89 90 for (int i = 0; i < num_der_certs; i++) { 91 std::string der_cert; 92 if (!p.ReadString(&iter, &der_cert)) 93 return false; 94 state->certs.push_back(der_cert); 95 } 96 97 std::string throwaway_string; 98 bool throwaway_bool; 99 if (!p.ReadString(&iter, &throwaway_string)) 100 return false; 101 102 if (!p.ReadBool(&iter, &throwaway_bool)) 103 return false; 104 105 if (throwaway_bool) { 106 int throwaway_int; 107 if (!p.ReadInt(&iter, &throwaway_int) || 108 !p.ReadString(&iter, &throwaway_string)) { 109 return false; 110 } 111 } 112 113 if (!state->certs.empty()) { 114 std::vector<base::StringPiece> der_certs(state->certs.size()); 115 for (size_t i = 0; i < state->certs.size(); i++) 116 der_certs[i] = state->certs[i]; 117 cert_ = X509Certificate::CreateFromDERCertChain(der_certs); 118 if (cert_.get()) { 119 int flags = 0; 120 if (verify_ev_cert_) 121 flags |= X509Certificate::VERIFY_EV_CERT; 122 if (rev_checking_enabled_) 123 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; 124 VLOG(1) << "Kicking off verification for " << hostname_; 125 verification_start_time_ = base::TimeTicks::Now(); 126 verification_end_time_ = base::TimeTicks(); 127 int rv = verifier_.Verify(cert_.get(), hostname_, flags, 128 &cert_verify_result_, callback_); 129 if (rv != ERR_IO_PENDING) 130 VerifyCallback(rv); 131 } else { 132 cert_parsing_failed_ = true; 133 DCHECK(!cert_verification_callback_); 134 } 135 } 136 137 return true; 138 } 139 140 std::string SSLHostInfo::Serialize() const { 141 Pickle p(sizeof(Pickle::Header)); 142 143 static const unsigned kMaxCertificatesSize = 32 * 1024; 144 unsigned der_certs_size = 0; 145 146 for (std::vector<std::string>::const_iterator 147 i = state_.certs.begin(); i != state_.certs.end(); i++) { 148 der_certs_size += i->size(); 149 } 150 151 // We don't care to save the certificates over a certain size. 152 if (der_certs_size > kMaxCertificatesSize) 153 return ""; 154 155 if (!p.WriteInt(state_.certs.size())) 156 return ""; 157 158 for (std::vector<std::string>::const_iterator 159 i = state_.certs.begin(); i != state_.certs.end(); i++) { 160 if (!p.WriteString(*i)) 161 return ""; 162 } 163 164 if (!p.WriteString("") || 165 !p.WriteBool(false)) { 166 return ""; 167 } 168 169 return std::string(reinterpret_cast<const char *>(p.data()), p.size()); 170 } 171 172 const CertVerifyResult& SSLHostInfo::cert_verify_result() const { 173 return cert_verify_result_; 174 } 175 176 int SSLHostInfo::WaitForCertVerification(CompletionCallback* callback) { 177 if (cert_verification_complete_) 178 return cert_verification_error_; 179 DCHECK(!cert_parsing_failed_); 180 DCHECK(!cert_verification_callback_); 181 DCHECK(!state_.certs.empty()); 182 cert_verification_callback_ = callback; 183 return ERR_IO_PENDING; 184 } 185 186 void SSLHostInfo::VerifyCallback(int rv) { 187 DCHECK(!verification_start_time_.is_null()); 188 base::TimeTicks now = base::TimeTicks::Now(); 189 const base::TimeDelta duration = now - verification_start_time(); 190 UMA_HISTOGRAM_TIMES("Net.SSLHostInfoVerificationTimeMs", duration); 191 VLOG(1) << "Verification took " << duration.InMilliseconds() << "ms"; 192 verification_end_time_ = now; 193 cert_verification_complete_ = true; 194 cert_verification_error_ = rv; 195 if (cert_verification_callback_) { 196 CompletionCallback* callback = cert_verification_callback_; 197 cert_verification_callback_ = NULL; 198 callback->Run(rv); 199 } 200 } 201 202 SSLHostInfoFactory::~SSLHostInfoFactory() {} 203 204 } // namespace net 205