Home | History | Annotate | Download | only in socket
      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