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
);