Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / net / socket / ssl_client_socket.cc
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