• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
State()18 SSLHostInfo::State::State() {}
19 
~State()20 SSLHostInfo::State::~State() {}
21 
Clear()22 void SSLHostInfo::State::Clear() {
23   certs.clear();
24 }
25 
SSLHostInfo(const std::string & hostname,const SSLConfig & ssl_config,CertVerifier * cert_verifier)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 
~SSLHostInfo()46 SSLHostInfo::~SSLHostInfo() {
47   if (dns_handle_ != DnsRRResolver::kInvalidHandle) {
48     dnsrr_resolver_->CancelResolve(dns_handle_);
49     delete dns_callback_;
50   }
51 }
52 
StartDnsLookup(DnsRRResolver * dnsrr_resolver)53 void SSLHostInfo::StartDnsLookup(DnsRRResolver* dnsrr_resolver) {
54   dnsrr_resolver_ = dnsrr_resolver;
55   // Note: currently disabled.
56 }
57 
state() const58 const SSLHostInfo::State& SSLHostInfo::state() const {
59   return state_;
60 }
61 
mutable_state()62 SSLHostInfo::State* SSLHostInfo::mutable_state() {
63   return &state_;
64 }
65 
Parse(const std::string & data)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 
ParseInner(const std::string & data)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 
Serialize() const140 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 
cert_verify_result() const172 const CertVerifyResult& SSLHostInfo::cert_verify_result() const {
173   return cert_verify_result_;
174 }
175 
WaitForCertVerification(CompletionCallback * callback)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 
VerifyCallback(int rv)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 
~SSLHostInfoFactory()202 SSLHostInfoFactory::~SSLHostInfoFactory() {}
203 
204 }  // namespace net
205