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 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 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 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 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 84 bool SSLClientSocket::WasNpnNegotiated() const { 85 return was_npn_negotiated_; 86 } 87 88 NextProto SSLClientSocket::GetNegotiatedProtocol() const { 89 return protocol_negotiated_; 90 } 91 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 111 bool SSLClientSocket::set_was_npn_negotiated(bool negotiated) { 112 return was_npn_negotiated_ = negotiated; 113 } 114 115 bool SSLClientSocket::was_spdy_negotiated() const { 116 return was_spdy_negotiated_; 117 } 118 119 bool SSLClientSocket::set_was_spdy_negotiated(bool negotiated) { 120 return was_spdy_negotiated_ = negotiated; 121 } 122 123 void SSLClientSocket::set_protocol_negotiated(NextProto protocol_negotiated) { 124 protocol_negotiated_ = protocol_negotiated; 125 } 126 127 bool SSLClientSocket::WasChannelIDSent() const { 128 return channel_id_sent_; 129 } 130 131 void SSLClientSocket::set_channel_id_sent(bool channel_id_sent) { 132 channel_id_sent_ = channel_id_sent; 133 } 134 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 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 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 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 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