QUIC - enable persisting of QUICServerInfo (server config) to disk
[chromium-blink-merge.git] / net / socket / ssl_client_socket.cc
blob45e3fa9480e052e99d63aa73b18a530548fd7879
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.
5 #include "net/socket/ssl_client_socket.h"
7 #include "base/metrics/histogram.h"
8 #include "base/strings/string_util.h"
9 #include "crypto/ec_private_key.h"
10 #include "net/ssl/channel_id_service.h"
11 #include "net/ssl/ssl_config_service.h"
13 namespace net {
15 SSLClientSocket::SSLClientSocket()
16 : was_npn_negotiated_(false),
17 was_spdy_negotiated_(false),
18 protocol_negotiated_(kProtoUnknown),
19 channel_id_sent_(false),
20 signed_cert_timestamps_received_(false),
21 stapled_ocsp_response_received_(false) {
24 // static
25 NextProto SSLClientSocket::NextProtoFromString(
26 const std::string& proto_string) {
27 if (proto_string == "http1.1" || proto_string == "http/1.1") {
28 return kProtoHTTP11;
29 } else if (proto_string == "spdy/2") {
30 return kProtoDeprecatedSPDY2;
31 } else if (proto_string == "spdy/3") {
32 return kProtoSPDY3;
33 } else if (proto_string == "spdy/3.1") {
34 return kProtoSPDY31;
35 } else if (proto_string == "h2-13") {
36 // This is the HTTP/2 draft 13 identifier. For internal
37 // consistency, HTTP/2 is named SPDY4 within Chromium.
38 return kProtoSPDY4;
39 } else if (proto_string == "quic/1+spdy/3") {
40 return kProtoQUIC1SPDY3;
41 } else {
42 return kProtoUnknown;
46 // static
47 const char* SSLClientSocket::NextProtoToString(NextProto next_proto) {
48 switch (next_proto) {
49 case kProtoHTTP11:
50 return "http/1.1";
51 case kProtoDeprecatedSPDY2:
52 return "spdy/2";
53 case kProtoSPDY3:
54 return "spdy/3";
55 case kProtoSPDY31:
56 return "spdy/3.1";
57 case kProtoSPDY4:
58 // This is the HTTP/2 draft 13 identifier. For internal
59 // consistency, HTTP/2 is named SPDY4 within Chromium.
60 return "h2-13";
61 case kProtoQUIC1SPDY3:
62 return "quic/1+spdy/3";
63 case kProtoUnknown:
64 break;
66 return "unknown";
69 // static
70 const char* SSLClientSocket::NextProtoStatusToString(
71 const SSLClientSocket::NextProtoStatus status) {
72 switch (status) {
73 case kNextProtoUnsupported:
74 return "unsupported";
75 case kNextProtoNegotiated:
76 return "negotiated";
77 case kNextProtoNoOverlap:
78 return "no-overlap";
80 return NULL;
83 bool SSLClientSocket::WasNpnNegotiated() const {
84 return was_npn_negotiated_;
87 NextProto SSLClientSocket::GetNegotiatedProtocol() const {
88 return protocol_negotiated_;
91 bool SSLClientSocket::IgnoreCertError(int error, int load_flags) {
92 if (error == OK || load_flags & LOAD_IGNORE_ALL_CERT_ERRORS)
93 return true;
95 if (error == ERR_CERT_COMMON_NAME_INVALID &&
96 (load_flags & LOAD_IGNORE_CERT_COMMON_NAME_INVALID))
97 return true;
99 if (error == ERR_CERT_DATE_INVALID &&
100 (load_flags & LOAD_IGNORE_CERT_DATE_INVALID))
101 return true;
103 if (error == ERR_CERT_AUTHORITY_INVALID &&
104 (load_flags & LOAD_IGNORE_CERT_AUTHORITY_INVALID))
105 return true;
107 return false;
110 bool SSLClientSocket::set_was_npn_negotiated(bool negotiated) {
111 return was_npn_negotiated_ = negotiated;
114 bool SSLClientSocket::was_spdy_negotiated() const {
115 return was_spdy_negotiated_;
118 bool SSLClientSocket::set_was_spdy_negotiated(bool negotiated) {
119 return was_spdy_negotiated_ = negotiated;
122 void SSLClientSocket::set_protocol_negotiated(NextProto protocol_negotiated) {
123 protocol_negotiated_ = protocol_negotiated;
126 bool SSLClientSocket::WasChannelIDSent() const {
127 return channel_id_sent_;
130 void SSLClientSocket::set_channel_id_sent(bool channel_id_sent) {
131 channel_id_sent_ = channel_id_sent;
134 void SSLClientSocket::set_signed_cert_timestamps_received(
135 bool signed_cert_timestamps_received) {
136 signed_cert_timestamps_received_ = signed_cert_timestamps_received;
139 void SSLClientSocket::set_stapled_ocsp_response_received(
140 bool stapled_ocsp_response_received) {
141 stapled_ocsp_response_received_ = stapled_ocsp_response_received;
144 // static
145 void SSLClientSocket::RecordChannelIDSupport(
146 ChannelIDService* channel_id_service,
147 bool negotiated_channel_id,
148 bool channel_id_enabled,
149 bool supports_ecc) {
150 // Since this enum is used for a histogram, do not change or re-use values.
151 enum {
152 DISABLED = 0,
153 CLIENT_ONLY = 1,
154 CLIENT_AND_SERVER = 2,
155 CLIENT_NO_ECC = 3,
156 CLIENT_BAD_SYSTEM_TIME = 4,
157 CLIENT_NO_CHANNEL_ID_SERVICE = 5,
158 CHANNEL_ID_USAGE_MAX
159 } supported = DISABLED;
160 if (negotiated_channel_id) {
161 supported = CLIENT_AND_SERVER;
162 } else if (channel_id_enabled) {
163 if (!channel_id_service)
164 supported = CLIENT_NO_CHANNEL_ID_SERVICE;
165 else if (!supports_ecc)
166 supported = CLIENT_NO_ECC;
167 else if (!channel_id_service->IsSystemTimeValid())
168 supported = CLIENT_BAD_SYSTEM_TIME;
169 else
170 supported = CLIENT_ONLY;
172 UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.Support", supported,
173 CHANNEL_ID_USAGE_MAX);
176 // static
177 bool SSLClientSocket::IsChannelIDEnabled(
178 const SSLConfig& ssl_config,
179 ChannelIDService* channel_id_service) {
180 if (!ssl_config.channel_id_enabled)
181 return false;
182 if (!channel_id_service) {
183 DVLOG(1) << "NULL channel_id_service_, not enabling channel ID.";
184 return false;
186 if (!crypto::ECPrivateKey::IsSupported()) {
187 DVLOG(1) << "Elliptic Curve not supported, not enabling channel ID.";
188 return false;
190 if (!channel_id_service->IsSystemTimeValid()) {
191 DVLOG(1) << "System time is not within the supported range for certificate "
192 "generation, not enabling channel ID.";
193 return false;
195 return true;
198 // static
199 std::vector<uint8_t> SSLClientSocket::SerializeNextProtos(
200 const std::vector<std::string>& next_protos) {
201 // Do a first pass to determine the total length.
202 size_t wire_length = 0;
203 for (std::vector<std::string>::const_iterator i = next_protos.begin();
204 i != next_protos.end(); ++i) {
205 if (i->size() > 255) {
206 LOG(WARNING) << "Ignoring overlong NPN/ALPN protocol: " << *i;
207 continue;
209 if (i->size() == 0) {
210 LOG(WARNING) << "Ignoring empty NPN/ALPN protocol";
211 continue;
213 wire_length += i->size();
214 wire_length++;
217 // Allocate memory for the result and fill it in.
218 std::vector<uint8_t> wire_protos;
219 wire_protos.reserve(wire_length);
220 for (std::vector<std::string>::const_iterator i = next_protos.begin();
221 i != next_protos.end(); i++) {
222 if (i->size() == 0 || i->size() > 255)
223 continue;
224 wire_protos.push_back(i->size());
225 wire_protos.resize(wire_protos.size() + i->size());
226 memcpy(&wire_protos[wire_protos.size() - i->size()],
227 i->data(), i->size());
229 DCHECK_EQ(wire_protos.size(), wire_length);
231 return wire_protos;
234 } // namespace net