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/base/host_port_pair.h"
11 #include "net/ssl/channel_id_service.h"
12 #include "net/ssl/ssl_config_service.h"
16 SSLClientSocket::SSLClientSocket()
17 : was_npn_negotiated_(false),
18 was_spdy_negotiated_(false),
19 protocol_negotiated_(kProtoUnknown),
20 channel_id_sent_(false),
21 signed_cert_timestamps_received_(false),
22 stapled_ocsp_response_received_(false) {
26 NextProto SSLClientSocket::NextProtoFromString(
27 const std::string& proto_string) {
28 if (proto_string == "http1.1" || proto_string == "http/1.1") {
30 } else if (proto_string == "spdy/2") {
31 return kProtoDeprecatedSPDY2;
32 } else if (proto_string == "spdy/3") {
34 } else if (proto_string == "spdy/3.1") {
36 } else if (proto_string == "h2-14") {
37 // This is the HTTP/2 draft 14 identifier. For internal
38 // consistency, HTTP/2 is named SPDY4 within Chromium.
40 } else if (proto_string == "quic/1+spdy/3") {
41 return kProtoQUIC1SPDY3;
48 const char* SSLClientSocket::NextProtoToString(NextProto next_proto) {
52 case kProtoDeprecatedSPDY2:
59 // This is the HTTP/2 draft 14 identifier. For internal
60 // consistency, HTTP/2 is named SPDY4 within Chromium.
62 case kProtoQUIC1SPDY3:
63 return "quic/1+spdy/3";
71 const char* SSLClientSocket::NextProtoStatusToString(
72 const SSLClientSocket::NextProtoStatus status) {
74 case kNextProtoUnsupported:
76 case kNextProtoNegotiated:
78 case kNextProtoNoOverlap:
84 bool SSLClientSocket::WasNpnNegotiated() const {
85 return was_npn_negotiated_;
88 NextProto SSLClientSocket::GetNegotiatedProtocol() const {
89 return protocol_negotiated_;
92 bool SSLClientSocket::IgnoreCertError(int error, int load_flags) {
93 if (error == OK || load_flags & LOAD_IGNORE_ALL_CERT_ERRORS)
96 if (error == ERR_CERT_COMMON_NAME_INVALID &&
97 (load_flags & LOAD_IGNORE_CERT_COMMON_NAME_INVALID))
100 if (error == ERR_CERT_DATE_INVALID &&
101 (load_flags & LOAD_IGNORE_CERT_DATE_INVALID))
104 if (error == ERR_CERT_AUTHORITY_INVALID &&
105 (load_flags & LOAD_IGNORE_CERT_AUTHORITY_INVALID))
111 bool SSLClientSocket::set_was_npn_negotiated(bool negotiated) {
112 return was_npn_negotiated_ = negotiated;
115 bool SSLClientSocket::was_spdy_negotiated() const {
116 return was_spdy_negotiated_;
119 bool SSLClientSocket::set_was_spdy_negotiated(bool negotiated) {
120 return was_spdy_negotiated_ = negotiated;
123 void SSLClientSocket::set_protocol_negotiated(NextProto protocol_negotiated) {
124 protocol_negotiated_ = protocol_negotiated;
127 bool SSLClientSocket::WasChannelIDSent() const {
128 return channel_id_sent_;
131 void SSLClientSocket::set_channel_id_sent(bool channel_id_sent) {
132 channel_id_sent_ = channel_id_sent;
135 void SSLClientSocket::set_signed_cert_timestamps_received(
136 bool signed_cert_timestamps_received) {
137 signed_cert_timestamps_received_ = signed_cert_timestamps_received;
140 void SSLClientSocket::set_stapled_ocsp_response_received(
141 bool stapled_ocsp_response_received) {
142 stapled_ocsp_response_received_ = stapled_ocsp_response_received;
146 void SSLClientSocket::RecordChannelIDSupport(
147 ChannelIDService* channel_id_service,
148 bool negotiated_channel_id,
149 bool channel_id_enabled,
151 // Since this enum is used for a histogram, do not change or re-use values.
155 CLIENT_AND_SERVER = 2,
157 CLIENT_BAD_SYSTEM_TIME = 4,
158 CLIENT_NO_CHANNEL_ID_SERVICE = 5,
160 } supported = DISABLED;
161 if (negotiated_channel_id) {
162 supported = CLIENT_AND_SERVER;
163 } else if (channel_id_enabled) {
164 if (!channel_id_service)
165 supported = CLIENT_NO_CHANNEL_ID_SERVICE;
166 else if (!supports_ecc)
167 supported = CLIENT_NO_ECC;
168 else if (!channel_id_service->IsSystemTimeValid())
169 supported = CLIENT_BAD_SYSTEM_TIME;
171 supported = CLIENT_ONLY;
173 UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.Support", supported,
174 CHANNEL_ID_USAGE_MAX);
178 bool SSLClientSocket::IsChannelIDEnabled(
179 const SSLConfig& ssl_config,
180 ChannelIDService* channel_id_service) {
181 if (!ssl_config.channel_id_enabled)
183 if (!channel_id_service) {
184 DVLOG(1) << "NULL channel_id_service_, not enabling channel ID.";
187 if (!crypto::ECPrivateKey::IsSupported()) {
188 DVLOG(1) << "Elliptic Curve not supported, not enabling channel ID.";
191 if (!channel_id_service->IsSystemTimeValid()) {
192 DVLOG(1) << "System time is not within the supported range for certificate "
193 "generation, not enabling channel ID.";
200 std::vector<uint8_t> SSLClientSocket::SerializeNextProtos(
201 const std::vector<std::string>& next_protos) {
202 // Do a first pass to determine the total length.
203 size_t wire_length = 0;
204 for (std::vector<std::string>::const_iterator i = next_protos.begin();
205 i != next_protos.end(); ++i) {
206 if (i->size() > 255) {
207 LOG(WARNING) << "Ignoring overlong NPN/ALPN protocol: " << *i;
210 if (i->size() == 0) {
211 LOG(WARNING) << "Ignoring empty NPN/ALPN protocol";
214 wire_length += i->size();
218 // Allocate memory for the result and fill it in.
219 std::vector<uint8_t> wire_protos;
220 wire_protos.reserve(wire_length);
221 for (std::vector<std::string>::const_iterator i = next_protos.begin();
222 i != next_protos.end(); i++) {
223 if (i->size() == 0 || i->size() > 255)
225 wire_protos.push_back(i->size());
226 wire_protos.resize(wire_protos.size() + i->size());
227 memcpy(&wire_protos[wire_protos.size() - i->size()],
228 i->data(), i->size());
230 DCHECK_EQ(wire_protos.size(), wire_length);