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/ssl/server_bound_cert_service.h" 11 #include "net/ssl/ssl_config_service.h" 12 13 namespace net { 14 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) { 22 } 23 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 == "spdy/4a2") { 36 return kProtoSPDY4a2; 37 } else if (proto_string == "HTTP-draft-04/2.0") { 38 return kProtoHTTP2Draft04; 39 } else if (proto_string == "quic/1+spdy/3") { 40 return kProtoQUIC1SPDY3; 41 } else { 42 return kProtoUnknown; 43 } 44 } 45 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 kProtoSPDY4a2: 58 return "spdy/4a2"; 59 case kProtoHTTP2Draft04: 60 return "HTTP-draft-04/2.0"; 61 case kProtoQUIC1SPDY3: 62 return "quic/1+spdy/3"; 63 case kProtoUnknown: 64 break; 65 } 66 return "unknown"; 67 } 68 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"; 79 } 80 return NULL; 81 } 82 83 // static 84 std::string SSLClientSocket::ServerProtosToString( 85 const std::string& server_protos) { 86 const char* protos = server_protos.c_str(); 87 size_t protos_len = server_protos.length(); 88 std::vector<std::string> server_protos_with_commas; 89 for (size_t i = 0; i < protos_len; ) { 90 const size_t len = protos[i]; 91 std::string proto_str(&protos[i + 1], len); 92 server_protos_with_commas.push_back(proto_str); 93 i += len + 1; 94 } 95 return JoinString(server_protos_with_commas, ','); 96 } 97 98 bool SSLClientSocket::WasNpnNegotiated() const { 99 return was_npn_negotiated_; 100 } 101 102 NextProto SSLClientSocket::GetNegotiatedProtocol() const { 103 return protocol_negotiated_; 104 } 105 106 bool SSLClientSocket::IgnoreCertError(int error, int load_flags) { 107 if (error == OK || load_flags & LOAD_IGNORE_ALL_CERT_ERRORS) 108 return true; 109 110 if (error == ERR_CERT_COMMON_NAME_INVALID && 111 (load_flags & LOAD_IGNORE_CERT_COMMON_NAME_INVALID)) 112 return true; 113 114 if (error == ERR_CERT_DATE_INVALID && 115 (load_flags & LOAD_IGNORE_CERT_DATE_INVALID)) 116 return true; 117 118 if (error == ERR_CERT_AUTHORITY_INVALID && 119 (load_flags & LOAD_IGNORE_CERT_AUTHORITY_INVALID)) 120 return true; 121 122 return false; 123 } 124 125 bool SSLClientSocket::set_was_npn_negotiated(bool negotiated) { 126 return was_npn_negotiated_ = negotiated; 127 } 128 129 bool SSLClientSocket::was_spdy_negotiated() const { 130 return was_spdy_negotiated_; 131 } 132 133 bool SSLClientSocket::set_was_spdy_negotiated(bool negotiated) { 134 return was_spdy_negotiated_ = negotiated; 135 } 136 137 void SSLClientSocket::set_protocol_negotiated(NextProto protocol_negotiated) { 138 protocol_negotiated_ = protocol_negotiated; 139 } 140 141 bool SSLClientSocket::WasChannelIDSent() const { 142 return channel_id_sent_; 143 } 144 145 void SSLClientSocket::set_channel_id_sent(bool channel_id_sent) { 146 channel_id_sent_ = channel_id_sent; 147 } 148 149 void SSLClientSocket::set_signed_cert_timestamps_received( 150 bool signed_cert_timestamps_received) { 151 signed_cert_timestamps_received_ = signed_cert_timestamps_received; 152 } 153 154 void SSLClientSocket::set_stapled_ocsp_response_received( 155 bool stapled_ocsp_response_received) { 156 stapled_ocsp_response_received_ = stapled_ocsp_response_received; 157 } 158 159 // static 160 void SSLClientSocket::RecordChannelIDSupport( 161 ServerBoundCertService* server_bound_cert_service, 162 bool negotiated_channel_id, 163 bool channel_id_enabled, 164 bool supports_ecc) { 165 // Since this enum is used for a histogram, do not change or re-use values. 166 enum { 167 DISABLED = 0, 168 CLIENT_ONLY = 1, 169 CLIENT_AND_SERVER = 2, 170 CLIENT_NO_ECC = 3, 171 CLIENT_BAD_SYSTEM_TIME = 4, 172 CLIENT_NO_SERVER_BOUND_CERT_SERVICE = 5, 173 DOMAIN_BOUND_CERT_USAGE_MAX 174 } supported = DISABLED; 175 if (negotiated_channel_id) { 176 supported = CLIENT_AND_SERVER; 177 } else if (channel_id_enabled) { 178 if (!server_bound_cert_service) 179 supported = CLIENT_NO_SERVER_BOUND_CERT_SERVICE; 180 else if (!supports_ecc) 181 supported = CLIENT_NO_ECC; 182 else if (!server_bound_cert_service->IsSystemTimeValid()) 183 supported = CLIENT_BAD_SYSTEM_TIME; 184 else 185 supported = CLIENT_ONLY; 186 } 187 UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.Support", supported, 188 DOMAIN_BOUND_CERT_USAGE_MAX); 189 } 190 191 // static 192 bool SSLClientSocket::IsChannelIDEnabled( 193 const SSLConfig& ssl_config, 194 ServerBoundCertService* server_bound_cert_service) { 195 if (!ssl_config.channel_id_enabled) 196 return false; 197 if (!server_bound_cert_service) { 198 DVLOG(1) << "NULL server_bound_cert_service_, not enabling channel ID."; 199 return false; 200 } 201 if (!crypto::ECPrivateKey::IsSupported()) { 202 DVLOG(1) << "Elliptic Curve not supported, not enabling channel ID."; 203 return false; 204 } 205 if (!server_bound_cert_service->IsSystemTimeValid()) { 206 DVLOG(1) << "System time is not within the supported range for certificate " 207 "generation, not enabling channel ID."; 208 return false; 209 } 210 return true; 211 } 212 213 } // namespace net 214