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