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.
4
5 #include "net/socket/ssl_client_socket.h"
6
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"
13
14 namespace net {
15
SSLClientSocket()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) {
23 }
24
25 // static
NextProtoFromString(const std::string & proto_string)26 NextProto SSLClientSocket::NextProtoFromString(
27 const std::string& proto_string) {
28 if (proto_string == "http1.1" || proto_string == "http/1.1") {
29 return kProtoHTTP11;
30 } else if (proto_string == "spdy/2") {
31 return kProtoDeprecatedSPDY2;
32 } else if (proto_string == "spdy/3") {
33 return kProtoSPDY3;
34 } else if (proto_string == "spdy/3.1") {
35 return kProtoSPDY31;
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.
39 return kProtoSPDY4;
40 } else if (proto_string == "quic/1+spdy/3") {
41 return kProtoQUIC1SPDY3;
42 } else {
43 return kProtoUnknown;
44 }
45 }
46
47 // static
NextProtoToString(NextProto next_proto)48 const char* SSLClientSocket::NextProtoToString(NextProto next_proto) {
49 switch (next_proto) {
50 case kProtoHTTP11:
51 return "http/1.1";
52 case kProtoDeprecatedSPDY2:
53 return "spdy/2";
54 case kProtoSPDY3:
55 return "spdy/3";
56 case kProtoSPDY31:
57 return "spdy/3.1";
58 case kProtoSPDY4:
59 // This is the HTTP/2 draft 14 identifier. For internal
60 // consistency, HTTP/2 is named SPDY4 within Chromium.
61 return "h2-14";
62 case kProtoQUIC1SPDY3:
63 return "quic/1+spdy/3";
64 case kProtoUnknown:
65 break;
66 }
67 return "unknown";
68 }
69
70 // static
NextProtoStatusToString(const SSLClientSocket::NextProtoStatus status)71 const char* SSLClientSocket::NextProtoStatusToString(
72 const SSLClientSocket::NextProtoStatus status) {
73 switch (status) {
74 case kNextProtoUnsupported:
75 return "unsupported";
76 case kNextProtoNegotiated:
77 return "negotiated";
78 case kNextProtoNoOverlap:
79 return "no-overlap";
80 }
81 return NULL;
82 }
83
WasNpnNegotiated() const84 bool SSLClientSocket::WasNpnNegotiated() const {
85 return was_npn_negotiated_;
86 }
87
GetNegotiatedProtocol() const88 NextProto SSLClientSocket::GetNegotiatedProtocol() const {
89 return protocol_negotiated_;
90 }
91
IgnoreCertError(int error,int load_flags)92 bool SSLClientSocket::IgnoreCertError(int error, int load_flags) {
93 if (error == OK || load_flags & LOAD_IGNORE_ALL_CERT_ERRORS)
94 return true;
95
96 if (error == ERR_CERT_COMMON_NAME_INVALID &&
97 (load_flags & LOAD_IGNORE_CERT_COMMON_NAME_INVALID))
98 return true;
99
100 if (error == ERR_CERT_DATE_INVALID &&
101 (load_flags & LOAD_IGNORE_CERT_DATE_INVALID))
102 return true;
103
104 if (error == ERR_CERT_AUTHORITY_INVALID &&
105 (load_flags & LOAD_IGNORE_CERT_AUTHORITY_INVALID))
106 return true;
107
108 return false;
109 }
110
set_was_npn_negotiated(bool negotiated)111 bool SSLClientSocket::set_was_npn_negotiated(bool negotiated) {
112 return was_npn_negotiated_ = negotiated;
113 }
114
was_spdy_negotiated() const115 bool SSLClientSocket::was_spdy_negotiated() const {
116 return was_spdy_negotiated_;
117 }
118
set_was_spdy_negotiated(bool negotiated)119 bool SSLClientSocket::set_was_spdy_negotiated(bool negotiated) {
120 return was_spdy_negotiated_ = negotiated;
121 }
122
set_protocol_negotiated(NextProto protocol_negotiated)123 void SSLClientSocket::set_protocol_negotiated(NextProto protocol_negotiated) {
124 protocol_negotiated_ = protocol_negotiated;
125 }
126
WasChannelIDSent() const127 bool SSLClientSocket::WasChannelIDSent() const {
128 return channel_id_sent_;
129 }
130
set_channel_id_sent(bool channel_id_sent)131 void SSLClientSocket::set_channel_id_sent(bool channel_id_sent) {
132 channel_id_sent_ = channel_id_sent;
133 }
134
set_signed_cert_timestamps_received(bool signed_cert_timestamps_received)135 void SSLClientSocket::set_signed_cert_timestamps_received(
136 bool signed_cert_timestamps_received) {
137 signed_cert_timestamps_received_ = signed_cert_timestamps_received;
138 }
139
set_stapled_ocsp_response_received(bool stapled_ocsp_response_received)140 void SSLClientSocket::set_stapled_ocsp_response_received(
141 bool stapled_ocsp_response_received) {
142 stapled_ocsp_response_received_ = stapled_ocsp_response_received;
143 }
144
145 // static
RecordChannelIDSupport(ChannelIDService * channel_id_service,bool negotiated_channel_id,bool channel_id_enabled,bool supports_ecc)146 void SSLClientSocket::RecordChannelIDSupport(
147 ChannelIDService* channel_id_service,
148 bool negotiated_channel_id,
149 bool channel_id_enabled,
150 bool supports_ecc) {
151 // Since this enum is used for a histogram, do not change or re-use values.
152 enum {
153 DISABLED = 0,
154 CLIENT_ONLY = 1,
155 CLIENT_AND_SERVER = 2,
156 CLIENT_NO_ECC = 3,
157 CLIENT_BAD_SYSTEM_TIME = 4,
158 CLIENT_NO_CHANNEL_ID_SERVICE = 5,
159 CHANNEL_ID_USAGE_MAX
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;
170 else
171 supported = CLIENT_ONLY;
172 }
173 UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.Support", supported,
174 CHANNEL_ID_USAGE_MAX);
175 }
176
177 // static
IsChannelIDEnabled(const SSLConfig & ssl_config,ChannelIDService * channel_id_service)178 bool SSLClientSocket::IsChannelIDEnabled(
179 const SSLConfig& ssl_config,
180 ChannelIDService* channel_id_service) {
181 if (!ssl_config.channel_id_enabled)
182 return false;
183 if (!channel_id_service) {
184 DVLOG(1) << "NULL channel_id_service_, not enabling channel ID.";
185 return false;
186 }
187 if (!crypto::ECPrivateKey::IsSupported()) {
188 DVLOG(1) << "Elliptic Curve not supported, not enabling channel ID.";
189 return false;
190 }
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.";
194 return false;
195 }
196 return true;
197 }
198
199 // static
SerializeNextProtos(const std::vector<std::string> & next_protos)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;
208 continue;
209 }
210 if (i->size() == 0) {
211 LOG(WARNING) << "Ignoring empty NPN/ALPN protocol";
212 continue;
213 }
214 wire_length += i->size();
215 wire_length++;
216 }
217
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)
224 continue;
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());
229 }
230 DCHECK_EQ(wire_protos.size(), wire_length);
231
232 return wire_protos;
233 }
234
235 } // namespace net
236