| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2012 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/bind.h" |
| 8 #include "base/metrics/histogram.h" |
| 9 #include "base/pickle.h" |
| 10 #include "base/strings/string_piece.h" |
| 11 #include "net/cert/cert_verifier.h" |
| 12 #include "net/cert/crl_set.h" |
| 13 #include "net/cert/x509_certificate.h" |
| 14 #include "net/socket/ssl_client_socket.h" |
| 15 #include "net/ssl/ssl_config_service.h" |
| 16 |
| 17 namespace net { |
| 18 |
| 19 SSLHostInfo::State::State() {} |
| 20 |
| 21 SSLHostInfo::State::~State() {} |
| 22 |
| 23 void SSLHostInfo::State::Clear() { |
| 24 certs.clear(); |
| 25 } |
| 26 |
| 27 SSLHostInfo::SSLHostInfo( |
| 28 const std::string& hostname, |
| 29 const SSLConfig& ssl_config, |
| 30 CertVerifier* cert_verifier) |
| 31 : cert_verification_complete_(false), |
| 32 cert_verification_error_(ERR_CERT_INVALID), |
| 33 hostname_(hostname), |
| 34 cert_parsing_failed_(false), |
| 35 rev_checking_enabled_(ssl_config.rev_checking_enabled), |
| 36 verify_ev_cert_(ssl_config.verify_ev_cert), |
| 37 verifier_(cert_verifier), |
| 38 weak_factory_(this) { |
| 39 } |
| 40 |
| 41 SSLHostInfo::~SSLHostInfo() { |
| 42 } |
| 43 |
| 44 const SSLHostInfo::State& SSLHostInfo::state() const { |
| 45 return state_; |
| 46 } |
| 47 |
| 48 SSLHostInfo::State* SSLHostInfo::mutable_state() { |
| 49 return &state_; |
| 50 } |
| 51 |
| 52 bool SSLHostInfo::Parse(const std::string& data) { |
| 53 State* state = mutable_state(); |
| 54 |
| 55 state->Clear(); |
| 56 cert_verification_complete_ = false; |
| 57 |
| 58 bool r = ParseInner(data); |
| 59 if (!r) |
| 60 state->Clear(); |
| 61 return r; |
| 62 } |
| 63 |
| 64 bool SSLHostInfo::ParseInner(const std::string& data) { |
| 65 State* state = mutable_state(); |
| 66 |
| 67 Pickle p(data.data(), data.size()); |
| 68 PickleIterator iter(p); |
| 69 |
| 70 int num_der_certs; |
| 71 if (!p.ReadInt(&iter, &num_der_certs) || |
| 72 num_der_certs < 0) { |
| 73 return false; |
| 74 } |
| 75 |
| 76 for (int i = 0; i < num_der_certs; i++) { |
| 77 std::string der_cert; |
| 78 if (!p.ReadString(&iter, &der_cert)) |
| 79 return false; |
| 80 state->certs.push_back(der_cert); |
| 81 } |
| 82 |
| 83 // Ignore obsolete members of the State structure. |
| 84 std::string throwaway_string; |
| 85 bool throwaway_bool; |
| 86 // This was state->server_hello. |
| 87 if (!p.ReadString(&iter, &throwaway_string)) |
| 88 return false; |
| 89 |
| 90 // This was state->npn_valid. |
| 91 if (!p.ReadBool(&iter, &throwaway_bool)) |
| 92 return false; |
| 93 |
| 94 if (throwaway_bool) { |
| 95 int throwaway_int; |
| 96 // These were state->npn_status and state->npn_protocol. |
| 97 if (!p.ReadInt(&iter, &throwaway_int) || |
| 98 !p.ReadString(&iter, &throwaway_string)) { |
| 99 return false; |
| 100 } |
| 101 } |
| 102 |
| 103 if (!state->certs.empty()) { |
| 104 std::vector<base::StringPiece> der_certs(state->certs.size()); |
| 105 for (size_t i = 0; i < state->certs.size(); i++) |
| 106 der_certs[i] = state->certs[i]; |
| 107 cert_ = X509Certificate::CreateFromDERCertChain(der_certs); |
| 108 if (cert_.get()) { |
| 109 int flags = 0; |
| 110 if (verify_ev_cert_) |
| 111 flags |= CertVerifier::VERIFY_EV_CERT; |
| 112 if (rev_checking_enabled_) |
| 113 flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED; |
| 114 VLOG(1) << "Kicking off verification for " << hostname_; |
| 115 verification_start_time_ = base::TimeTicks::Now(); |
| 116 verification_end_time_ = base::TimeTicks(); |
| 117 scoped_refptr<CRLSet> crl_set(SSLConfigService::GetCRLSet()); |
| 118 int rv = verifier_.Verify( |
| 119 cert_.get(), hostname_, flags, crl_set, &cert_verify_result_, |
| 120 base::Bind(&SSLHostInfo::VerifyCallback, weak_factory_.GetWeakPtr()), |
| 121 // TODO(willchan): Figure out how to use NetLog here. |
| 122 BoundNetLog()); |
| 123 if (rv != ERR_IO_PENDING) |
| 124 VerifyCallback(rv); |
| 125 } else { |
| 126 cert_parsing_failed_ = true; |
| 127 DCHECK(cert_verification_callback_.is_null()); |
| 128 } |
| 129 } |
| 130 |
| 131 return true; |
| 132 } |
| 133 |
| 134 std::string SSLHostInfo::Serialize() const { |
| 135 Pickle p(sizeof(Pickle::Header)); |
| 136 |
| 137 static const unsigned kMaxCertificatesSize = 32 * 1024; |
| 138 unsigned der_certs_size = 0; |
| 139 |
| 140 for (std::vector<std::string>::const_iterator |
| 141 i = state_.certs.begin(); i != state_.certs.end(); i++) { |
| 142 der_certs_size += i->size(); |
| 143 } |
| 144 |
| 145 // We don't care to save the certificates over a certain size. |
| 146 if (der_certs_size > kMaxCertificatesSize) |
| 147 return ""; |
| 148 |
| 149 if (!p.WriteInt(state_.certs.size())) |
| 150 return ""; |
| 151 |
| 152 for (std::vector<std::string>::const_iterator |
| 153 i = state_.certs.begin(); i != state_.certs.end(); i++) { |
| 154 if (!p.WriteString(*i)) |
| 155 return ""; |
| 156 } |
| 157 |
| 158 // Write dummy values for obsolete members of the State structure: |
| 159 // state->server_hello and state->npn_valid. |
| 160 if (!p.WriteString("") || |
| 161 !p.WriteBool(false)) { |
| 162 return ""; |
| 163 } |
| 164 |
| 165 return std::string(reinterpret_cast<const char *>(p.data()), p.size()); |
| 166 } |
| 167 |
| 168 const CertVerifyResult& SSLHostInfo::cert_verify_result() const { |
| 169 return cert_verify_result_; |
| 170 } |
| 171 |
| 172 int SSLHostInfo::WaitForCertVerification(const CompletionCallback& callback) { |
| 173 if (cert_verification_complete_) |
| 174 return cert_verification_error_; |
| 175 |
| 176 DCHECK(!cert_parsing_failed_); |
| 177 DCHECK(cert_verification_callback_.is_null()); |
| 178 DCHECK(!state_.certs.empty()); |
| 179 cert_verification_callback_ = callback; |
| 180 return ERR_IO_PENDING; |
| 181 } |
| 182 |
| 183 void SSLHostInfo::VerifyCallback(int rv) { |
| 184 DCHECK(!verification_start_time_.is_null()); |
| 185 base::TimeTicks now = base::TimeTicks::Now(); |
| 186 const base::TimeDelta duration = now - verification_start_time(); |
| 187 bool is_google = hostname_ == "google.com" || |
| 188 (hostname_.size() > 11 && |
| 189 hostname_.rfind(".google.com") == hostname_.size() - 11); |
| 190 if (is_google) { |
| 191 UMA_HISTOGRAM_TIMES("Net.SSLHostInfoVerificationTimeMs_Google", duration); |
| 192 } |
| 193 UMA_HISTOGRAM_TIMES("Net.SSLHostInfoVerificationTimeMs", duration); |
| 194 VLOG(1) << "Verification took " << duration.InMilliseconds() << "ms"; |
| 195 verification_end_time_ = now; |
| 196 cert_verification_complete_ = true; |
| 197 cert_verification_error_ = rv; |
| 198 if (!cert_verification_callback_.is_null()) { |
| 199 CompletionCallback callback = cert_verification_callback_; |
| 200 cert_verification_callback_.Reset(); |
| 201 callback.Run(rv); |
| 202 } |
| 203 } |
| 204 |
| 205 SSLHostInfoFactory::~SSLHostInfoFactory() {} |
| 206 |
| 207 } // namespace net |
| OLD | NEW |