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
16namespace net {
17
18SSLHostInfo::State::State() {}
19
20SSLHostInfo::State::~State() {}
21
22void SSLHostInfo::State::Clear() {
23  certs.clear();
24}
25
26SSLHostInfo::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
46SSLHostInfo::~SSLHostInfo() {
47  if (dns_handle_ != DnsRRResolver::kInvalidHandle) {
48    dnsrr_resolver_->CancelResolve(dns_handle_);
49    delete dns_callback_;
50  }
51}
52
53void SSLHostInfo::StartDnsLookup(DnsRRResolver* dnsrr_resolver) {
54  dnsrr_resolver_ = dnsrr_resolver;
55  // Note: currently disabled.
56}
57
58const SSLHostInfo::State& SSLHostInfo::state() const {
59  return state_;
60}
61
62SSLHostInfo::State* SSLHostInfo::mutable_state() {
63  return &state_;
64}
65
66bool 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
78bool 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
140std::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
172const CertVerifyResult& SSLHostInfo::cert_verify_result() const {
173  return cert_verify_result_;
174}
175
176int 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
186void 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
202SSLHostInfoFactory::~SSLHostInfoFactory() {}
203
204}  // namespace net
205