blob: b9c6dffd046c323f35d551c7b90a2d1a12fd268a [file] [log] [blame]
[email protected]a2006ece2010-04-23 16:44:021// Copyright (c) 2010 The Chromium Authors. All rights reserved.
[email protected]b43c97c2008-10-22 19:50:582// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]e83ba1c42009-11-30 18:18:325// This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived
6// from AuthCertificateCallback() in
[email protected]bf0136d2009-05-29 05:55:047// mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp.
8
9/* ***** BEGIN LICENSE BLOCK *****
10 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
11 *
12 * The contents of this file are subject to the Mozilla Public License Version
13 * 1.1 (the "License"); you may not use this file except in compliance with
14 * the License. You may obtain a copy of the License at
15 * http://www.mozilla.org/MPL/
16 *
17 * Software distributed under the License is distributed on an "AS IS" basis,
18 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
19 * for the specific language governing rights and limitations under the
20 * License.
21 *
22 * The Original Code is the Netscape security libraries.
23 *
24 * The Initial Developer of the Original Code is
25 * Netscape Communications Corporation.
26 * Portions created by the Initial Developer are Copyright (C) 2000
27 * the Initial Developer. All Rights Reserved.
28 *
29 * Contributor(s):
30 * Ian McGreer <[email protected]>
31 * Javier Delgadillo <[email protected]>
32 * Kai Engert <[email protected]>
33 *
34 * Alternatively, the contents of this file may be used under the terms of
35 * either the GNU General Public License Version 2 or later (the "GPL"), or
36 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
37 * in which case the provisions of the GPL or the LGPL are applicable instead
38 * of those above. If you wish to allow use of your version of this file only
39 * under the terms of either the GPL or the LGPL, and not to allow others to
40 * use your version of this file under the terms of the MPL, indicate your
41 * decision by deleting the provisions above and replace them with the notice
42 * and other provisions required by the GPL or the LGPL. If you do not delete
43 * the provisions above, a recipient may use your version of this file under
44 * the terms of any one of the MPL, the GPL or the LGPL.
45 *
46 * ***** END LICENSE BLOCK ***** */
47
[email protected]f7984fc62009-06-22 23:26:4448#include "net/socket/ssl_client_socket_nss.h"
[email protected]b43c97c2008-10-22 19:50:5849
[email protected]bf0136d2009-05-29 05:55:0450#include <certdb.h>
[email protected]b24713592010-08-11 19:50:0251#include <hasht.h>
[email protected]d84b3722009-10-15 21:23:3752#include <keyhi.h>
[email protected]b43c97c2008-10-22 19:50:5853#include <nspr.h>
54#include <nss.h>
[email protected]d8eb84242010-09-25 02:25:0655#include <pk11pub.h>
[email protected]ea224582008-12-07 20:25:4656#include <secerr.h>
[email protected]b24713592010-08-11 19:50:0257#include <sechash.h>
[email protected]b43c97c2008-10-22 19:50:5858#include <ssl.h>
[email protected]ea224582008-12-07 20:25:4659#include <sslerr.h>
[email protected]757f2e2b2010-10-27 23:28:3560#include <sslproto.h>
[email protected]b43c97c2008-10-22 19:50:5861
[email protected]7a8de3072010-10-01 16:25:5462#include <limits>
63
[email protected]bacff652009-03-31 17:50:3364#include "base/compiler_specific.h"
[email protected]835d7c82010-10-14 04:38:3865#include "base/metrics/histogram.h"
[email protected]b43c97c2008-10-22 19:50:5866#include "base/logging.h"
[email protected]1b1a264a2010-01-14 22:36:3567#include "base/nss_util.h"
[email protected]829296f2010-01-27 02:58:0368#include "base/singleton.h"
[email protected]899c3e92010-08-28 15:53:5069#include "base/string_number_conversions.h"
[email protected]b43c97c2008-10-22 19:50:5870#include "base/string_util.h"
[email protected]d8eb84242010-09-25 02:25:0671#include "base/stringprintf.h"
[email protected]ba74b0d22010-10-23 05:19:2072#include "base/thread_restrictions.h"
[email protected]7cbc6df12010-10-04 16:25:3973#include "base/values.h"
[email protected]ac9eec62010-02-20 18:50:3874#include "net/base/address_list.h"
[email protected]43025b7a2010-09-16 19:24:4575#include "net/base/cert_status_flags.h"
[email protected]92d9cad2009-06-25 23:40:2476#include "net/base/cert_verifier.h"
[email protected]757f2e2b2010-10-27 23:28:3577#include "net/base/connection_type_histograms.h"
[email protected]d8eb84242010-09-25 02:25:0678#include "net/base/dns_util.h"
[email protected]899c3e92010-08-28 15:53:5079#include "net/base/dnsrr_resolver.h"
[email protected]b24713592010-08-11 19:50:0280#include "net/base/dnssec_chain_verifier.h"
[email protected]597cf6e2009-05-29 09:43:2681#include "net/base/io_buffer.h"
[email protected]b43c97c2008-10-22 19:50:5882#include "net/base/net_errors.h"
[email protected]899c3e92010-08-28 15:53:5083#include "net/base/net_log.h"
[email protected]d84b3722009-10-15 21:23:3784#include "net/base/ssl_cert_request_info.h"
[email protected]fc7de492010-07-12 14:49:0485#include "net/base/ssl_connection_status_flags.h"
[email protected]b43c97c2008-10-22 19:50:5886#include "net/base/ssl_info.h"
[email protected]ac9eec62010-02-20 18:50:3887#include "net/base/sys_addrinfo.h"
[email protected]2a0c0a52009-07-31 07:51:3288#include "net/ocsp/nss_ocsp.h"
[email protected]e60e47a2010-07-14 03:37:1889#include "net/socket/client_socket_handle.h"
[email protected]345c613b2010-11-22 19:33:1890#include "net/socket/dns_cert_provenance_checker.h"
[email protected]47f7d742010-11-11 04:12:5391#include "net/socket/ssl_error_params.h"
[email protected]d0672be2010-10-20 16:30:1992#include "net/socket/ssl_host_info.h"
[email protected]b43c97c2008-10-22 19:50:5893
[email protected]11f40342010-11-22 13:35:4994#if defined(USE_SYSTEM_SSL)
95#include <dlfcn.h>
96#endif
97#if defined(OS_WIN)
98#include <windows.h>
99#include <wincrypt.h>
100#elif defined(OS_MACOSX)
101#include <Security/SecBase.h>
102#include <Security/SecCertificate.h>
103#include <Security/SecIdentity.h>
104#endif
105
[email protected]b43c97c2008-10-22 19:50:58106static const int kRecvBufferSize = 4096;
107
[email protected]fa788512010-10-08 14:48:06108// kCorkTimeoutMs is the number of milliseconds for which we'll wait for a
109// Write to an SSL socket which we're False Starting. Since corking stops the
110// Finished message from being sent, the server sees an incomplete handshake
111// and some will time out such sockets quite aggressively.
112static const int kCorkTimeoutMs = 200;
113
[email protected]b43c97c2008-10-22 19:50:58114namespace net {
115
[email protected]e17b4c12008-11-05 22:04:08116// State machines are easier to debug if you log state transitions.
117// Enable these if you want to see what's going on.
118#if 1
119#define EnterFunction(x)
120#define LeaveFunction(x)
[email protected]a3ff5e92009-10-13 04:48:06121#define GotoState(s) next_handshake_state_ = s
[email protected]ea224582008-12-07 20:25:46122#define LogData(s, len)
[email protected]e17b4c12008-11-05 22:04:08123#else
[email protected]b30a3f52010-10-16 01:05:46124#define EnterFunction(x)\
125 VLOG(1) << (void *)this << " " << __FUNCTION__ << " enter " << x\
126 << "; next_handshake_state " << next_handshake_state_
127#define LeaveFunction(x)\
128 VLOG(1) << (void *)this << " " << __FUNCTION__ << " leave " << x\
129 << "; next_handshake_state " << next_handshake_state_
130#define GotoState(s)\
131 do {\
132 VLOG(1) << (void *)this << " " << __FUNCTION__ << " jump to state " << s;\
133 next_handshake_state_ = s;\
134 } while (0)
135#define LogData(s, len)\
136 VLOG(1) << (void *)this << " " << __FUNCTION__\
137 << " data [" << std::string(s, len) << "]"
[email protected]e17b4c12008-11-05 22:04:08138#endif
139
[email protected]ea224582008-12-07 20:25:46140namespace {
141
[email protected]829296f2010-01-27 02:58:03142class NSSSSLInitSingleton {
143 public:
144 NSSSSLInitSingleton() {
145 base::EnsureNSSInit();
146
147 NSS_SetDomesticPolicy();
148
149#if defined(USE_SYSTEM_SSL)
150 // Use late binding to avoid scary but benign warning
151 // "Symbol `SSL_ImplementedCiphers' has different size in shared object,
152 // consider re-linking"
[email protected]4d3040f42010-04-14 02:40:20153 // TODO(wtc): Use the new SSL_GetImplementedCiphers and
154 // SSL_GetNumImplementedCiphers functions when we require NSS 3.12.6.
155 // See https://bugzilla.mozilla.org/show_bug.cgi?id=496993.
[email protected]829296f2010-01-27 02:58:03156 const PRUint16* pSSL_ImplementedCiphers = static_cast<const PRUint16*>(
157 dlsym(RTLD_DEFAULT, "SSL_ImplementedCiphers"));
158 if (pSSL_ImplementedCiphers == NULL) {
159 NOTREACHED() << "Can't get list of supported ciphers";
160 return;
161 }
162#else
163#define pSSL_ImplementedCiphers SSL_ImplementedCiphers
164#endif
165
166 // Explicitly enable exactly those ciphers with keys of at least 80 bits
167 for (int i = 0; i < SSL_NumImplementedCiphers; i++) {
168 SSLCipherSuiteInfo info;
169 if (SSL_GetCipherSuiteInfo(pSSL_ImplementedCiphers[i], &info,
170 sizeof(info)) == SECSuccess) {
171 SSL_CipherPrefSetDefault(pSSL_ImplementedCiphers[i],
172 (info.effectiveKeyBits >= 80));
173 }
174 }
175
176 // Enable SSL.
177 SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE);
178
179 // All other SSL options are set per-session by SSLClientSocket.
180 }
181
182 ~NSSSSLInitSingleton() {
183 // Have to clear the cache, or NSS_Shutdown fails with SEC_ERROR_BUSY.
184 SSL_ClearSessionCache();
185 }
186};
187
188// Initialize the NSS SSL library if it isn't already initialized. This must
189// be called before any other NSS SSL functions. This function is
190// thread-safe, and the NSS SSL library will only ever be initialized once.
191// The NSS SSL library will be properly shut down on program exit.
192void EnsureNSSSSLInit() {
[email protected]ba74b0d22010-10-23 05:19:20193 // Initializing SSL causes us to do blocking IO.
194 // Temporarily allow it until we fix
195 // http://code.google.com/p/chromium/issues/detail?id=59847
196 base::ThreadRestrictions::ScopedAllowIO allow_io;
197
[email protected]829296f2010-01-27 02:58:03198 Singleton<NSSSSLInitSingleton>::get();
199}
200
[email protected]2e9a5b6982010-01-15 22:29:03201// The default error mapping function.
202// Maps an NSPR error code to a network error code.
203int MapNSPRError(PRErrorCode err) {
[email protected]ea224582008-12-07 20:25:46204 // TODO(port): fill this out as we learn what's important
205 switch (err) {
206 case PR_WOULD_BLOCK_ERROR:
207 return ERR_IO_PENDING;
[email protected]b0735462009-11-04 22:11:26208 case PR_ADDRESS_NOT_SUPPORTED_ERROR: // For connect.
209 case PR_NO_ACCESS_RIGHTS_ERROR:
210 return ERR_ACCESS_DENIED;
211 case PR_IO_TIMEOUT_ERROR:
212 return ERR_TIMED_OUT;
213 case PR_CONNECT_RESET_ERROR:
214 return ERR_CONNECTION_RESET;
215 case PR_CONNECT_ABORTED_ERROR:
216 return ERR_CONNECTION_ABORTED;
217 case PR_CONNECT_REFUSED_ERROR:
218 return ERR_CONNECTION_REFUSED;
219 case PR_HOST_UNREACHABLE_ERROR:
220 case PR_NETWORK_UNREACHABLE_ERROR:
221 return ERR_ADDRESS_UNREACHABLE;
222 case PR_ADDRESS_NOT_AVAILABLE_ERROR:
223 return ERR_ADDRESS_INVALID;
[email protected]58f43332010-08-11 17:21:16224 case PR_INVALID_ARGUMENT_ERROR:
225 return ERR_INVALID_ARGUMENT;
[email protected]0428acf12010-10-01 22:59:16226 case PR_END_OF_FILE_ERROR:
227 return ERR_CONNECTION_CLOSED;
[email protected]4a842342010-11-04 16:21:33228 case PR_NOT_IMPLEMENTED_ERROR:
229 return ERR_NOT_IMPLEMENTED;
[email protected]58f43332010-08-11 17:21:16230
231 case SEC_ERROR_INVALID_ARGS:
232 return ERR_INVALID_ARGUMENT;
[email protected]b0735462009-11-04 22:11:26233
[email protected]4d3040f42010-04-14 02:40:20234 case SSL_ERROR_SSL_DISABLED:
235 return ERR_NO_SSL_VERSIONS_ENABLED;
[email protected]ea224582008-12-07 20:25:46236 case SSL_ERROR_NO_CYPHER_OVERLAP:
[email protected]2e9a5b6982010-01-15 22:29:03237 case SSL_ERROR_UNSUPPORTED_VERSION:
[email protected]ea224582008-12-07 20:25:46238 return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
[email protected]d84b3722009-10-15 21:23:37239 case SSL_ERROR_HANDSHAKE_FAILURE_ALERT:
[email protected]4d3040f42010-04-14 02:40:20240 case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT:
241 case SSL_ERROR_ILLEGAL_PARAMETER_ALERT:
[email protected]d84b3722009-10-15 21:23:37242 return ERR_SSL_PROTOCOL_ERROR;
[email protected]aeaca1f2010-04-20 22:05:21243 case SSL_ERROR_DECOMPRESSION_FAILURE_ALERT:
244 return ERR_SSL_DECOMPRESSION_FAILURE_ALERT;
[email protected]0ed94682010-05-18 15:09:00245 case SSL_ERROR_BAD_MAC_ALERT:
246 return ERR_SSL_BAD_RECORD_MAC_ALERT;
[email protected]d102f542010-06-30 14:51:05247 case SSL_ERROR_UNSAFE_NEGOTIATION:
248 return ERR_SSL_UNSAFE_NEGOTIATION;
[email protected]e7bad86e2010-08-17 00:56:40249 case SSL_ERROR_WEAK_SERVER_KEY:
[email protected]b9a3dc32010-08-30 16:44:23250 return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY;
[email protected]ea224582008-12-07 20:25:46251
252 default: {
253 if (IS_SSL_ERROR(err)) {
254 LOG(WARNING) << "Unknown SSL error " << err <<
255 " mapped to net::ERR_SSL_PROTOCOL_ERROR";
256 return ERR_SSL_PROTOCOL_ERROR;
257 }
[email protected]ea224582008-12-07 20:25:46258 LOG(WARNING) << "Unknown error " << err <<
259 " mapped to net::ERR_FAILED";
260 return ERR_FAILED;
261 }
262 }
263}
264
[email protected]2e9a5b6982010-01-15 22:29:03265// Context-sensitive error mapping functions.
266
267int MapHandshakeError(PRErrorCode err) {
268 switch (err) {
269 // If the server closed on us, it is a protocol error.
270 // Some TLS-intolerant servers do this when we request TLS.
271 case PR_END_OF_FILE_ERROR:
272 // The handshake may fail because some signature (for example, the
273 // signature in the ServerKeyExchange message for an ephemeral
274 // Diffie-Hellman cipher suite) is invalid.
275 case SEC_ERROR_BAD_SIGNATURE:
276 return ERR_SSL_PROTOCOL_ERROR;
277 default:
278 return MapNSPRError(err);
279 }
280}
281
[email protected]7cbc6df12010-10-04 16:25:39282// Extra parameters to attach to the NetLog when we receive an error in response
283// to a call to an NSS function. Used instead of SSLErrorParams with
284// events of type TYPE_SSL_NSS_ERROR. Automatically looks up last PR error.
285class SSLFailedNSSFunctionParams : public NetLog::EventParameters {
286 public:
287 // |param| is ignored if it has a length of 0.
288 SSLFailedNSSFunctionParams(const std::string& function,
289 const std::string& param)
290 : function_(function), param_(param), ssl_lib_error_(PR_GetError()) {
291 }
292
293 virtual Value* ToValue() const {
294 DictionaryValue* dict = new DictionaryValue();
295 dict->SetString("function", function_);
296 if (!param_.empty())
297 dict->SetString("param", param_);
298 dict->SetInteger("ssl_lib_error", ssl_lib_error_);
299 return dict;
300 }
301
302 private:
303 const std::string function_;
304 const std::string param_;
305 const PRErrorCode ssl_lib_error_;
306};
307
308void LogFailedNSSFunction(const BoundNetLog& net_log,
309 const char* function,
310 const char* param) {
[email protected]00cd9c42010-11-02 20:15:57311 net_log.AddEvent(
312 NetLog::TYPE_SSL_NSS_ERROR,
313 make_scoped_refptr(new SSLFailedNSSFunctionParams(function, param)));
[email protected]7cbc6df12010-10-04 16:25:39314}
315
[email protected]37a0b112010-05-08 02:23:46316#if defined(OS_WIN)
317
[email protected]01640f62010-08-10 19:42:12318// This callback is intended to be used with CertFindChainInStore. In addition
319// to filtering by extended/enhanced key usage, we do not show expired
320// certificates and require digital signature usage in the key usage
321// extension.
322//
323// This matches our behavior on Mac OS X and that of NSS. It also matches the
324// default behavior of IE8. See http://support.microsoft.com/kb/890326 and
325// http://blogs.msdn.com/b/askie/archive/2009/06/09/my-expired-client-certificates-no-longer-display-when-connecting-to-my-web-server-using-ie8.aspx
326BOOL WINAPI ClientCertFindCallback(PCCERT_CONTEXT cert_context,
327 void* find_arg) {
[email protected]b30a3f52010-10-16 01:05:46328 VLOG(1) << "Calling ClientCertFindCallback from _nss";
[email protected]01640f62010-08-10 19:42:12329 // Verify the certificate's KU is good.
330 BYTE key_usage;
331 if (CertGetIntendedKeyUsage(X509_ASN_ENCODING, cert_context->pCertInfo,
332 &key_usage, 1)) {
333 if (!(key_usage & CERT_DIGITAL_SIGNATURE_KEY_USAGE))
334 return FALSE;
335 } else {
336 DWORD err = GetLastError();
337 // If |err| is non-zero, it's an actual error. Otherwise the extension
338 // just isn't present, and we treat it as if everything was allowed.
339 if (err) {
340 DLOG(ERROR) << "CertGetIntendedKeyUsage failed: " << err;
341 return FALSE;
342 }
343 }
344
345 // Verify the current time is within the certificate's validity period.
346 if (CertVerifyTimeValidity(NULL, cert_context->pCertInfo) != 0)
347 return FALSE;
348
349 return TRUE;
350}
351
[email protected]37a0b112010-05-08 02:23:46352#endif
353
[email protected]17570702010-10-28 15:16:09354// PeerCertificateChain is a helper object which extracts the certificate
355// chain, as given by the server, from an NSS socket and performs the needed
356// resource management. The first element of the chain is the leaf certificate
357// and the other elements are in the order given by the server.
358class PeerCertificateChain {
359 public:
[email protected]b92a96e2010-11-02 21:03:05360 explicit PeerCertificateChain(PRFileDesc* nss_fd)
[email protected]17570702010-10-28 15:16:09361 : num_certs_(0),
362 certs_(NULL) {
363 SECStatus rv = SSL_PeerCertificateChain(nss_fd, NULL, &num_certs_);
364 DCHECK_EQ(rv, SECSuccess);
365
366 certs_ = new CERTCertificate*[num_certs_];
367 const unsigned expected_num_certs = num_certs_;
368 rv = SSL_PeerCertificateChain(nss_fd, certs_, &num_certs_);
369 DCHECK_EQ(rv, SECSuccess);
370 DCHECK_EQ(num_certs_, expected_num_certs);
371 }
372
373 ~PeerCertificateChain() {
374 for (unsigned i = 0; i < num_certs_; i++)
375 CERT_DestroyCertificate(certs_[i]);
376 delete[] certs_;
377 }
378
379 unsigned size() const { return num_certs_; }
380
381 CERTCertificate* operator[](unsigned i) {
382 DCHECK_LT(i, num_certs_);
383 return certs_[i];
384 }
385
[email protected]d8fbf582010-11-04 21:51:12386 std::vector<base::StringPiece> AsStringPieceVector() const {
387 std::vector<base::StringPiece> v(size());
388 for (unsigned i = 0; i < size(); i++) {
389 v[i] = base::StringPiece(
390 reinterpret_cast<const char*>(certs_[i]->derCert.data),
391 certs_[i]->derCert.len);
392 }
393
394 return v;
395 }
396
[email protected]17570702010-10-28 15:16:09397 private:
398 unsigned num_certs_;
399 CERTCertificate** certs_;
400};
401
[email protected]ea224582008-12-07 20:25:46402} // namespace
403
[email protected]e60e47a2010-07-14 03:37:18404SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket,
[email protected]4f4de7e62010-11-12 19:55:27405 const HostPortPair& host_and_port,
[email protected]7ab5bbd12010-10-19 13:33:21406 const SSLConfig& ssl_config,
[email protected]d8fbf582010-11-04 21:51:12407 SSLHostInfo* ssl_host_info,
[email protected]345c613b2010-11-22 19:33:18408 DnsCertProvenanceChecker* dns_ctx)
[email protected]f505a9b2010-01-28 19:44:02409 : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_(
410 this, &SSLClientSocketNSS::BufferSendComplete)),
411 ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_(
412 this, &SSLClientSocketNSS::BufferRecvComplete)),
[email protected]b43c97c2008-10-22 19:50:58413 transport_send_busy_(false),
414 transport_recv_busy_(false),
[email protected]9ae2ee02010-09-08 16:41:14415 corked_(false),
[email protected]f505a9b2010-01-28 19:44:02416 ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_(
417 this, &SSLClientSocketNSS::OnHandshakeIOComplete)),
[email protected]b43c97c2008-10-22 19:50:58418 transport_(transport_socket),
[email protected]4f4de7e62010-11-12 19:55:27419 host_and_port_(host_and_port),
[email protected]b43c97c2008-10-22 19:50:58420 ssl_config_(ssl_config),
[email protected]a6eb576292009-06-30 16:19:00421 user_connect_callback_(NULL),
[email protected]a3ff5e92009-10-13 04:48:06422 user_read_callback_(NULL),
423 user_write_callback_(NULL),
424 user_read_buf_len_(0),
425 user_write_buf_len_(0),
[email protected]f505a9b2010-01-28 19:44:02426 server_cert_nss_(NULL),
[email protected]3b1d3db2010-10-28 16:39:40427 server_cert_verify_result_(NULL),
[email protected]757f2e2b2010-10-27 23:28:35428 ssl_connection_status_(0),
[email protected]d84b3722009-10-15 21:23:37429 client_auth_cert_needed_(false),
[email protected]39afe642010-04-29 14:55:18430 handshake_callback_called_(false),
[email protected]b43c97c2008-10-22 19:50:58431 completed_handshake_(false),
[email protected]7a8de3072010-10-01 16:25:54432 pseudo_connected_(false),
[email protected]563cbcc62010-10-11 23:07:52433 eset_mitm_detected_(false),
[email protected]3b1d3db2010-10-28 16:39:40434 predicted_cert_chain_correct_(false),
[email protected]7f7e92392010-10-26 18:29:29435 peername_initialized_(false),
[email protected]899c3e92010-08-28 15:53:50436 dnssec_provider_(NULL),
[email protected]a3ff5e92009-10-13 04:48:06437 next_handshake_state_(STATE_NONE),
[email protected]b43c97c2008-10-22 19:50:58438 nss_fd_(NULL),
[email protected]a2006ece2010-04-23 16:44:02439 nss_bufs_(NULL),
[email protected]7a8de3072010-10-01 16:25:54440 net_log_(transport_socket->socket()->NetLog()),
441 predicted_npn_status_(kNextProtoUnsupported),
[email protected]7ab5bbd12010-10-19 13:33:21442 predicted_npn_proto_used_(false),
[email protected]d8fbf582010-11-04 21:51:12443 ssl_host_info_(ssl_host_info),
[email protected]345c613b2010-11-22 19:33:18444 dns_cert_checker_(dns_ctx) {
[email protected]e17b4c12008-11-05 22:04:08445 EnterFunction("");
[email protected]b43c97c2008-10-22 19:50:58446}
447
448SSLClientSocketNSS::~SSLClientSocketNSS() {
[email protected]e17b4c12008-11-05 22:04:08449 EnterFunction("");
[email protected]b43c97c2008-10-22 19:50:58450 Disconnect();
[email protected]e17b4c12008-11-05 22:04:08451 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:58452}
453
454int SSLClientSocketNSS::Init() {
[email protected]e17b4c12008-11-05 22:04:08455 EnterFunction("");
[email protected]829296f2010-01-27 02:58:03456 // Initialize the NSS SSL library in a threadsafe way. This also
457 // initializes the NSS base library.
458 EnsureNSSSSLInit();
[email protected]dbc13b52010-04-16 00:59:56459 if (!NSS_IsInitialized())
460 return ERR_UNEXPECTED;
[email protected]3dd6f5e2010-06-01 20:28:03461#if !defined(OS_MACOSX) && !defined(OS_WIN)
[email protected]2a0c0a52009-07-31 07:51:32462 // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop
463 // by MessageLoopForIO::current().
464 // X509Certificate::Verify() runs on a worker thread of CertVerifier.
465 EnsureOCSPInit();
[email protected]f505a9b2010-01-28 19:44:02466#endif
[email protected]b43c97c2008-10-22 19:50:58467
[email protected]e17b4c12008-11-05 22:04:08468 LeaveFunction("");
469 return OK;
[email protected]b43c97c2008-10-22 19:50:58470}
471
[email protected]d0672be2010-10-20 16:30:19472// SaveSnapStartInfo extracts the information needed to perform a Snap Start
473// with this server in the future (if any) and tells |ssl_host_info_| to
474// preserve it.
[email protected]7a8de3072010-10-01 16:25:54475void SSLClientSocketNSS::SaveSnapStartInfo() {
[email protected]7ab5bbd12010-10-19 13:33:21476 if (!ssl_host_info_.get())
[email protected]7a8de3072010-10-01 16:25:54477 return;
478
479 SECStatus rv;
480 SSLSnapStartResult snap_start_type;
481 rv = SSL_GetSnapStartResult(nss_fd_, &snap_start_type);
482 if (rv != SECSuccess) {
483 NOTREACHED();
484 return;
485 }
[email protected]09125792010-11-03 23:23:22486 net_log_.AddEvent(NetLog::TYPE_SSL_SNAP_START,
487 new NetLogIntegerParameter("type", snap_start_type));
[email protected]4f4de7e62010-11-12 19:55:27488 LOG(ERROR) << "Snap Start: " << snap_start_type << " "
489 << host_and_port_.ToString();
[email protected]7a8de3072010-10-01 16:25:54490 if (snap_start_type == SSL_SNAP_START_FULL ||
491 snap_start_type == SSL_SNAP_START_RESUME) {
492 // If we did a successful Snap Start then our information was correct and
493 // there's no point saving it again.
494 return;
495 }
496
497 const unsigned char* hello_data;
498 unsigned hello_data_len;
499 rv = SSL_GetPredictedServerHelloData(nss_fd_, &hello_data, &hello_data_len);
500 if (rv != SECSuccess) {
501 NOTREACHED();
502 return;
503 }
[email protected]7a8de3072010-10-01 16:25:54504 if (hello_data_len > std::numeric_limits<uint16>::max())
505 return;
[email protected]d0672be2010-10-20 16:30:19506 SSLHostInfo::State* state = ssl_host_info_->mutable_state();
507 state->server_hello =
508 std::string(reinterpret_cast<const char *>(hello_data), hello_data_len);
[email protected]7a8de3072010-10-01 16:25:54509
[email protected]98f397e2010-10-26 13:56:57510 if (hello_data_len > 0) {
511 state->npn_valid = true;
512 state->npn_status = GetNextProto(&state->npn_protocol);
513 } else {
514 state->npn_valid = false;
515 }
[email protected]7a8de3072010-10-01 16:25:54516
[email protected]98f397e2010-10-26 13:56:57517 state->certs.clear();
[email protected]17570702010-10-28 15:16:09518 PeerCertificateChain certs(nss_fd_);
519 for (unsigned i = 0; i < certs.size(); i++) {
520 if (certs[i]->derCert.len > std::numeric_limits<uint16>::max())
[email protected]7a8de3072010-10-01 16:25:54521 return;
[email protected]98f397e2010-10-26 13:56:57522
[email protected]d0672be2010-10-20 16:30:19523 state->certs.push_back(std::string(
[email protected]17570702010-10-28 15:16:09524 reinterpret_cast<char*>(certs[i]->derCert.data),
525 certs[i]->derCert.len));
[email protected]7a8de3072010-10-01 16:25:54526 }
527
[email protected]4f4de7e62010-11-12 19:55:27528 LOG(ERROR) << "Setting Snap Start info " << host_and_port_.ToString();
[email protected]d0672be2010-10-20 16:30:19529 ssl_host_info_->Persist();
[email protected]7a8de3072010-10-01 16:25:54530}
531
532static void DestroyCertificates(CERTCertificate** certs, unsigned len) {
533 for (unsigned i = 0; i < len; i++)
534 CERT_DestroyCertificate(certs[i]);
535}
536
537// LoadSnapStartInfo parses |info|, which contains data previously serialised
538// by |SaveSnapStartInfo|, and sets the predicted certificates and ServerHello
539// data on the NSS socket. Returns true on success. If this function returns
540// false, the caller should try a normal TLS handshake.
[email protected]d0672be2010-10-20 16:30:19541bool SSLClientSocketNSS::LoadSnapStartInfo() {
542 const SSLHostInfo::State& state(ssl_host_info_->state());
543
544 if (state.server_hello.empty() ||
545 state.certs.empty() ||
546 !state.npn_valid) {
547 return false;
548 }
549
[email protected]7a8de3072010-10-01 16:25:54550 SECStatus rv;
[email protected]d0672be2010-10-20 16:30:19551 rv = SSL_SetPredictedServerHelloData(
552 nss_fd_,
553 reinterpret_cast<const uint8*>(state.server_hello.data()),
554 state.server_hello.size());
[email protected]7a8de3072010-10-01 16:25:54555 DCHECK_EQ(SECSuccess, rv);
[email protected]7a8de3072010-10-01 16:25:54556
[email protected]d0672be2010-10-20 16:30:19557 const std::vector<std::string>& certs_in = state.certs;
558 scoped_array<CERTCertificate*> certs(new CERTCertificate*[certs_in.size()]);
559 for (size_t i = 0; i < certs_in.size(); i++) {
[email protected]7a8de3072010-10-01 16:25:54560 SECItem derCert;
[email protected]d0672be2010-10-20 16:30:19561 derCert.data =
562 const_cast<uint8*>(reinterpret_cast<const uint8*>(certs_in[i].data()));
563 derCert.len = certs_in[i].size();
[email protected]7a8de3072010-10-01 16:25:54564 certs[i] = CERT_NewTempCertificate(
565 CERT_GetDefaultCertDB(), &derCert, NULL /* no nickname given */,
566 PR_FALSE /* not permanent */, PR_TRUE /* copy DER data */);
567 if (!certs[i]) {
568 DestroyCertificates(&certs[0], i);
569 NOTREACHED();
570 return false;
571 }
572 }
573
[email protected]d0672be2010-10-20 16:30:19574 rv = SSL_SetPredictedPeerCertificates(nss_fd_, certs.get(), certs_in.size());
575 DestroyCertificates(&certs[0], certs_in.size());
[email protected]7a8de3072010-10-01 16:25:54576 DCHECK_EQ(SECSuccess, rv);
577
[email protected]d0672be2010-10-20 16:30:19578 if (state.npn_valid) {
579 predicted_npn_status_ = state.npn_status;
580 predicted_npn_proto_ = state.npn_protocol;
581 }
[email protected]7a8de3072010-10-01 16:25:54582
583 return true;
584}
585
586bool SSLClientSocketNSS::IsNPNProtocolMispredicted() {
587 DCHECK(handshake_callback_called_);
588 if (!predicted_npn_proto_used_)
589 return false;
590 std::string npn_proto;
591 GetNextProto(&npn_proto);
592 return predicted_npn_proto_ != npn_proto;
593}
594
[email protected]fa788512010-10-08 14:48:06595void SSLClientSocketNSS::UncorkAfterTimeout() {
596 corked_ = false;
597 int nsent;
598 do {
599 nsent = BufferSend();
600 } while (nsent > 0);
601}
602
[email protected]a2006ece2010-04-23 16:44:02603int SSLClientSocketNSS::Connect(CompletionCallback* callback) {
[email protected]e17b4c12008-11-05 22:04:08604 EnterFunction("");
[email protected]b43c97c2008-10-22 19:50:58605 DCHECK(transport_.get());
[email protected]a3ff5e92009-10-13 04:48:06606 DCHECK(next_handshake_state_ == STATE_NONE);
607 DCHECK(!user_read_callback_);
608 DCHECK(!user_write_callback_);
[email protected]a6eb576292009-06-30 16:19:00609 DCHECK(!user_connect_callback_);
[email protected]a3ff5e92009-10-13 04:48:06610 DCHECK(!user_read_buf_);
611 DCHECK(!user_write_buf_);
[email protected]7a8de3072010-10-01 16:25:54612 DCHECK(!pseudo_connected_);
[email protected]b43c97c2008-10-22 19:50:58613
[email protected]ec11be62010-04-28 19:28:09614 net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT, NULL);
[email protected]5a05c47a2009-11-02 23:25:19615
[email protected]dbc13b52010-04-16 00:59:56616 int rv = Init();
617 if (rv != OK) {
[email protected]ec11be62010-04-28 19:28:09618 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
[email protected]dbc13b52010-04-16 00:59:56619 return rv;
[email protected]0ef0bcf2009-04-03 20:39:43620 }
621
[email protected]dbc13b52010-04-16 00:59:56622 rv = InitializeSSLOptions();
[email protected]5a05c47a2009-11-02 23:25:19623 if (rv != OK) {
[email protected]ec11be62010-04-28 19:28:09624 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
[email protected]5a05c47a2009-11-02 23:25:19625 return rv;
626 }
627
[email protected]7f7e92392010-10-26 18:29:29628 // Attempt to initialize the peer name. In the case of TCP FastOpen,
629 // we don't have the peer yet.
630 if (!UsingTCPFastOpen()) {
631 rv = InitializeSSLPeerName();
632 if (rv != OK) {
633 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
634 return rv;
635 }
636 }
637
[email protected]7ab5bbd12010-10-19 13:33:21638 if (ssl_config_.snap_start_enabled && ssl_host_info_.get()) {
[email protected]7a8de3072010-10-01 16:25:54639 GotoState(STATE_SNAP_START_LOAD_INFO);
640 } else {
641 GotoState(STATE_HANDSHAKE);
642 }
643
[email protected]5a05c47a2009-11-02 23:25:19644 rv = DoHandshakeLoop(OK);
645 if (rv == ERR_IO_PENDING) {
[email protected]7a8de3072010-10-01 16:25:54646 if (pseudo_connected_) {
647 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
648 rv = OK;
649 } else {
650 user_connect_callback_ = callback;
651 }
[email protected]5a05c47a2009-11-02 23:25:19652 } else {
[email protected]ec11be62010-04-28 19:28:09653 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
[email protected]5a05c47a2009-11-02 23:25:19654 }
655
656 LeaveFunction("");
657 return rv > OK ? OK : rv;
658}
659
660int SSLClientSocketNSS::InitializeSSLOptions() {
[email protected]0ef0bcf2009-04-03 20:39:43661 // Transport connected, now hook it up to nss
662 // TODO(port): specify rx and tx buffer sizes separately
663 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize);
664 if (nss_fd_ == NULL) {
[email protected]38a18722009-12-04 00:09:04665 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code.
[email protected]0ef0bcf2009-04-03 20:39:43666 }
667
[email protected]0ef0bcf2009-04-03 20:39:43668 // Grab pointer to buffers
669 nss_bufs_ = memio_GetSecret(nss_fd_);
670
671 /* Create SSL state machine */
672 /* Push SSL onto our fake I/O socket */
673 nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
674 if (nss_fd_ == NULL) {
[email protected]7cbc6df12010-10-04 16:25:39675 LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
[email protected]4e91b5c2010-09-22 01:04:38676 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR/NSS error code.
[email protected]0ef0bcf2009-04-03 20:39:43677 }
678 // TODO(port): set more ssl options! Check errors!
679
680 int rv;
681
682 rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
[email protected]7cbc6df12010-10-04 16:25:39683 if (rv != SECSuccess) {
684 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
[email protected]4e91b5c2010-09-22 01:04:38685 return ERR_UNEXPECTED;
[email protected]7cbc6df12010-10-04 16:25:39686 }
[email protected]0ef0bcf2009-04-03 20:39:43687
688 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, ssl_config_.ssl2_enabled);
[email protected]7cbc6df12010-10-04 16:25:39689 if (rv != SECSuccess) {
690 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
[email protected]4e91b5c2010-09-22 01:04:38691 return ERR_UNEXPECTED;
[email protected]7cbc6df12010-10-04 16:25:39692 }
[email protected]0ef0bcf2009-04-03 20:39:43693
694 // SNI is enabled automatically if TLS is enabled -- as long as
695 // SSL_V2_COMPATIBLE_HELLO isn't.
696 // So don't do V2 compatible hellos unless we're really using SSL2,
697 // to avoid errors like
698 // "common name `mail.google.com' != requested host name `gmail.com'"
699 rv = SSL_OptionSet(nss_fd_, SSL_V2_COMPATIBLE_HELLO,
700 ssl_config_.ssl2_enabled);
[email protected]7cbc6df12010-10-04 16:25:39701 if (rv != SECSuccess) {
702 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_V2_COMPATIBLE_HELLO");
703 return ERR_UNEXPECTED;
704 }
[email protected]0ef0bcf2009-04-03 20:39:43705
706 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL3, ssl_config_.ssl3_enabled);
[email protected]7cbc6df12010-10-04 16:25:39707 if (rv != SECSuccess) {
708 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL3");
709 return ERR_UNEXPECTED;
710 }
[email protected]0ef0bcf2009-04-03 20:39:43711
712 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_TLS, ssl_config_.tls1_enabled);
[email protected]7cbc6df12010-10-04 16:25:39713 if (rv != SECSuccess) {
714 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_TLS");
715 return ERR_UNEXPECTED;
716 }
[email protected]0ef0bcf2009-04-03 20:39:43717
[email protected]47f7d742010-11-11 04:12:53718 for (std::vector<uint16>::const_iterator it =
719 ssl_config_.disabled_cipher_suites.begin();
720 it != ssl_config_.disabled_cipher_suites.end(); ++it) {
721 // This will fail if the specified cipher is not implemented by NSS, but
722 // the failure is harmless.
723 SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
724 }
725
[email protected]0ef0bcf2009-04-03 20:39:43726#ifdef SSL_ENABLE_SESSION_TICKETS
727 // Support RFC 5077
728 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
[email protected]7cbc6df12010-10-04 16:25:39729 if (rv != SECSuccess) {
730 LogFailedNSSFunction(
731 net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
732 }
[email protected]0ef0bcf2009-04-03 20:39:43733#else
734 #error "You need to install NSS-3.12 or later to build chromium"
735#endif
736
[email protected]7e52ed72009-11-17 00:40:12737#ifdef SSL_ENABLE_DEFLATE
[email protected]074c1582010-01-08 21:38:28738 // Some web servers have been found to break if TLS is used *or* if DEFLATE
739 // is advertised. Thus, if TLS is disabled (probably because we are doing
740 // SSLv3 fallback), we disable DEFLATE also.
741 // See http://crbug.com/31628
742 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_DEFLATE, ssl_config_.tls1_enabled);
[email protected]7e52ed72009-11-17 00:40:12743 if (rv != SECSuccess)
[email protected]7cbc6df12010-10-04 16:25:39744 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_DEFLATE");
[email protected]7e52ed72009-11-17 00:40:12745#endif
746
[email protected]c2def1c2010-03-02 21:40:34747#ifdef SSL_ENABLE_FALSE_START
[email protected]a0deaecf2010-08-18 23:39:52748 rv = SSL_OptionSet(
749 nss_fd_, SSL_ENABLE_FALSE_START,
750 ssl_config_.false_start_enabled &&
[email protected]4f4de7e62010-11-12 19:55:27751 !SSLConfigService::IsKnownFalseStartIncompatibleServer(
752 host_and_port_.host()));
[email protected]c2def1c2010-03-02 21:40:34753 if (rv != SECSuccess)
[email protected]7cbc6df12010-10-04 16:25:39754 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_FALSE_START");
[email protected]c2def1c2010-03-02 21:40:34755#endif
756
[email protected]7a8de3072010-10-01 16:25:54757#ifdef SSL_ENABLE_SNAP_START
758 // TODO(agl): check that SSL_ENABLE_SNAP_START actually does something in the
759 // current NSS code.
[email protected]4d52f192010-10-11 17:00:30760 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SNAP_START,
[email protected]09125792010-11-03 23:23:22761 ssl_config_.snap_start_enabled);
[email protected]7a8de3072010-10-01 16:25:54762 if (rv != SECSuccess)
[email protected]b30a3f52010-10-16 01:05:46763 VLOG(1) << "SSL_ENABLE_SNAP_START failed. Old system nss?";
[email protected]7a8de3072010-10-01 16:25:54764#endif
765
[email protected]33b3eb92010-01-06 01:35:04766#ifdef SSL_ENABLE_RENEGOTIATION
[email protected]304b0e352010-09-13 18:10:08767 // Deliberately disable this check for now: http://crbug.com/55410
768 if (false &&
[email protected]4f4de7e62010-11-12 19:55:27769 SSLConfigService::IsKnownStrictTLSServer(host_and_port_.host()) &&
[email protected]944a0a12010-08-19 20:02:28770 !ssl_config_.mitm_proxies_allowed) {
[email protected]d102f542010-06-30 14:51:05771 rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_SAFE_NEGOTIATION, PR_TRUE);
[email protected]7cbc6df12010-10-04 16:25:39772 if (rv != SECSuccess) {
773 LogFailedNSSFunction(
774 net_log_, "SSL_OptionSet", "SSL_REQUIRE_SAFE_NEGOTIATION");
775 }
[email protected]d102f542010-06-30 14:51:05776 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_RENEGOTIATION,
777 SSL_RENEGOTIATE_REQUIRES_XTN);
778 } else {
779 // We allow servers to request renegotiation. Since we're a client,
780 // prohibiting this is rather a waste of time. Only servers are in a
781 // position to prevent renegotiation attacks.
782 // http://extendedsubset.com/?p=8
783
784 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_RENEGOTIATION,
[email protected]e7bad86e2010-08-17 00:56:40785 SSL_RENEGOTIATE_TRANSITIONAL);
[email protected]d102f542010-06-30 14:51:05786 }
[email protected]7cbc6df12010-10-04 16:25:39787 if (rv != SECSuccess) {
788 LogFailedNSSFunction(
789 net_log_, "SSL_OptionSet", "SSL_ENABLE_RENEGOTIATION");
790 }
[email protected]d102f542010-06-30 14:51:05791#endif // SSL_ENABLE_RENEGOTIATION
[email protected]33b3eb92010-01-06 01:35:04792
[email protected]644bdca2009-11-30 20:40:53793#ifdef SSL_NEXT_PROTO_NEGOTIATED
794 if (!ssl_config_.next_protos.empty()) {
795 rv = SSL_SetNextProtoNego(
796 nss_fd_,
797 reinterpret_cast<const unsigned char *>(ssl_config_.next_protos.data()),
798 ssl_config_.next_protos.size());
799 if (rv != SECSuccess)
[email protected]7cbc6df12010-10-04 16:25:39800 LogFailedNSSFunction(net_log_, "SSL_SetNextProtoNego", "");
[email protected]644bdca2009-11-30 20:40:53801 }
802#endif
803
[email protected]0ef0bcf2009-04-03 20:39:43804 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
[email protected]7cbc6df12010-10-04 16:25:39805 if (rv != SECSuccess) {
806 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
807 return ERR_UNEXPECTED;
808 }
[email protected]0ef0bcf2009-04-03 20:39:43809
810 rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
[email protected]7cbc6df12010-10-04 16:25:39811 if (rv != SECSuccess) {
812 LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
813 return ERR_UNEXPECTED;
814 }
[email protected]0ef0bcf2009-04-03 20:39:43815
[email protected]4a842342010-11-04 16:21:33816#if defined(NSS_PLATFORM_CLIENT_AUTH)
817 rv = SSL_GetPlatformClientAuthDataHook(nss_fd_, PlatformClientAuthHandler,
818 this);
819#else
[email protected]d84b3722009-10-15 21:23:37820 rv = SSL_GetClientAuthDataHook(nss_fd_, ClientAuthHandler, this);
[email protected]4a842342010-11-04 16:21:33821#endif
[email protected]7cbc6df12010-10-04 16:25:39822 if (rv != SECSuccess) {
823 LogFailedNSSFunction(net_log_, "SSL_GetClientAuthDataHook", "");
824 return ERR_UNEXPECTED;
825 }
[email protected]d84b3722009-10-15 21:23:37826
[email protected]2345cc52009-06-04 09:18:47827 rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
[email protected]7cbc6df12010-10-04 16:25:39828 if (rv != SECSuccess) {
829 LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", "");
[email protected]2345cc52009-06-04 09:18:47830 return ERR_UNEXPECTED;
[email protected]7cbc6df12010-10-04 16:25:39831 }
[email protected]0ef0bcf2009-04-03 20:39:43832
833 // Tell SSL the hostname we're trying to connect to.
[email protected]4f4de7e62010-11-12 19:55:27834 SSL_SetURL(nss_fd_, host_and_port_.host().c_str());
[email protected]0ef0bcf2009-04-03 20:39:43835
[email protected]7f7e92392010-10-26 18:29:29836 // Tell SSL we're a client; needed if not letting NSPR do socket I/O
837 SSL_ResetHandshake(nss_fd_, 0);
838
839 return OK;
840}
841
842int SSLClientSocketNSS::InitializeSSLPeerName() {
843 // Tell NSS who we're connected to
844 AddressList peer_address;
845 int err = transport_->socket()->GetPeerAddress(&peer_address);
846 if (err != OK)
847 return err;
848
849 const struct addrinfo* ai = peer_address.head();
850
851 PRNetAddr peername;
852 memset(&peername, 0, sizeof(peername));
853 DCHECK_LE(ai->ai_addrlen, sizeof(peername));
854 size_t len = std::min(static_cast<size_t>(ai->ai_addrlen),
855 sizeof(peername));
856 memcpy(&peername, ai->ai_addr, len);
857
858 // Adjust the address family field for BSD, whose sockaddr
859 // structure has a one-byte length and one-byte address family
860 // field at the beginning. PRNetAddr has a two-byte address
861 // family field at the beginning.
862 peername.raw.family = ai->ai_addr->sa_family;
863
864 memio_SetPeerName(nss_fd_, &peername);
865
[email protected]52c27fb2009-11-30 22:40:23866 // Set the peer ID for session reuse. This is necessary when we create an
867 // SSL tunnel through a proxy -- GetPeerName returns the proxy's address
868 // rather than the destination server's address in that case.
[email protected]4f4de7e62010-11-12 19:55:27869 std::string peer_id = host_and_port_.ToString();
[email protected]7f7e92392010-10-26 18:29:29870 SECStatus rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str()));
[email protected]52c27fb2009-11-30 22:40:23871 if (rv != SECSuccess)
[email protected]7cbc6df12010-10-04 16:25:39872 LogFailedNSSFunction(net_log_, "SSL_SetSockPeerID", peer_id.c_str());
[email protected]52c27fb2009-11-30 22:40:23873
[email protected]7f7e92392010-10-26 18:29:29874 peername_initialized_ = true;
[email protected]5a05c47a2009-11-02 23:25:19875 return OK;
[email protected]b43c97c2008-10-22 19:50:58876}
877
[email protected]b43c97c2008-10-22 19:50:58878void SSLClientSocketNSS::Disconnect() {
[email protected]e17b4c12008-11-05 22:04:08879 EnterFunction("");
[email protected]bacff652009-03-31 17:50:33880
[email protected]b43c97c2008-10-22 19:50:58881 // TODO(wtc): Send SSL close_notify alert.
882 if (nss_fd_ != NULL) {
[email protected]b43c97c2008-10-22 19:50:58883 PR_Close(nss_fd_);
884 nss_fd_ = NULL;
885 }
[email protected]bacff652009-03-31 17:50:33886
[email protected]92d9cad2009-06-25 23:40:24887 // Shut down anything that may call us back (through buffer_send_callback_,
[email protected]a3ff5e92009-10-13 04:48:06888 // buffer_recv_callback, or handshake_io_callback_).
[email protected]92d9cad2009-06-25 23:40:24889 verifier_.reset();
[email protected]e60e47a2010-07-14 03:37:18890 transport_->socket()->Disconnect();
[email protected]bf0136d2009-05-29 05:55:04891
892 // Reset object state
[email protected]a6eb576292009-06-30 16:19:00893 transport_send_busy_ = false;
894 transport_recv_busy_ = false;
895 user_connect_callback_ = NULL;
[email protected]a3ff5e92009-10-13 04:48:06896 user_read_callback_ = NULL;
897 user_write_callback_ = NULL;
898 user_read_buf_ = NULL;
899 user_read_buf_len_ = 0;
900 user_write_buf_ = NULL;
901 user_write_buf_len_ = 0;
[email protected]a6eb576292009-06-30 16:19:00902 server_cert_ = NULL;
[email protected]f505a9b2010-01-28 19:44:02903 if (server_cert_nss_) {
904 CERT_DestroyCertificate(server_cert_nss_);
905 server_cert_nss_ = NULL;
906 }
[email protected]3b1d3db2010-10-28 16:39:40907 local_server_cert_verify_result_.Reset();
908 server_cert_verify_result_ = NULL;
[email protected]757f2e2b2010-10-27 23:28:35909 ssl_connection_status_ = 0;
[email protected]a6eb576292009-06-30 16:19:00910 completed_handshake_ = false;
[email protected]7a8de3072010-10-01 16:25:54911 pseudo_connected_ = false;
[email protected]563cbcc62010-10-11 23:07:52912 eset_mitm_detected_ = false;
[email protected]3b1d3db2010-10-28 16:39:40913 predicted_cert_chain_correct_ = false;
[email protected]7f7e92392010-10-26 18:29:29914 peername_initialized_ = false;
[email protected]a6eb576292009-06-30 16:19:00915 nss_bufs_ = NULL;
[email protected]b8fee152009-10-24 03:39:31916 client_certs_.clear();
[email protected]d84b3722009-10-15 21:23:37917 client_auth_cert_needed_ = false;
[email protected]bf0136d2009-05-29 05:55:04918
[email protected]e17b4c12008-11-05 22:04:08919 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:58920}
921
922bool SSLClientSocketNSS::IsConnected() const {
[email protected]b2197852009-02-19 23:27:33923 // Ideally, we should also check if we have received the close_notify alert
924 // message from the server, and return false in that case. We're not doing
925 // that, so this function may return a false positive. Since the upper
926 // layer (HttpNetworkTransaction) needs to handle a persistent connection
927 // closed by the server when we send a request anyway, a false positive in
928 // exchange for simpler code is a good trade-off.
[email protected]e17b4c12008-11-05 22:04:08929 EnterFunction("");
[email protected]7a8de3072010-10-01 16:25:54930 bool ret = (pseudo_connected_ || completed_handshake_) &&
931 transport_->socket()->IsConnected();
[email protected]e17b4c12008-11-05 22:04:08932 LeaveFunction("");
933 return ret;
[email protected]b43c97c2008-10-22 19:50:58934}
935
[email protected]b2197852009-02-19 23:27:33936bool SSLClientSocketNSS::IsConnectedAndIdle() const {
937 // Unlike IsConnected, this method doesn't return a false positive.
938 //
939 // Strictly speaking, we should check if we have received the close_notify
940 // alert message from the server, and return false in that case. Although
941 // the close_notify alert message means EOF in the SSL layer, it is just
[email protected]e60e47a2010-07-14 03:37:18942 // bytes to the transport layer below, so
943 // transport_->socket()->IsConnectedAndIdle() returns the desired false
944 // when we receive close_notify.
[email protected]b2197852009-02-19 23:27:33945 EnterFunction("");
[email protected]7a8de3072010-10-01 16:25:54946 bool ret = (pseudo_connected_ || completed_handshake_) &&
947 transport_->socket()->IsConnectedAndIdle();
[email protected]b2197852009-02-19 23:27:33948 LeaveFunction("");
949 return ret;
950}
951
[email protected]ac9eec62010-02-20 18:50:38952int SSLClientSocketNSS::GetPeerAddress(AddressList* address) const {
[email protected]e60e47a2010-07-14 03:37:18953 return transport_->socket()->GetPeerAddress(address);
[email protected]9f864b32010-01-20 15:01:16954}
955
[email protected]9b5614a2010-08-25 20:29:45956void SSLClientSocketNSS::SetSubresourceSpeculation() {
957 if (transport_.get() && transport_->socket()) {
958 transport_->socket()->SetSubresourceSpeculation();
959 } else {
960 NOTREACHED();
961 }
962}
963
964void SSLClientSocketNSS::SetOmniboxSpeculation() {
965 if (transport_.get() && transport_->socket()) {
966 transport_->socket()->SetOmniboxSpeculation();
967 } else {
968 NOTREACHED();
969 }
970}
971
[email protected]0f873e82010-09-02 16:09:01972bool SSLClientSocketNSS::WasEverUsed() const {
973 if (transport_.get() && transport_->socket()) {
974 return transport_->socket()->WasEverUsed();
975 }
976 NOTREACHED();
977 return false;
978}
979
[email protected]7f7e92392010-10-26 18:29:29980bool SSLClientSocketNSS::UsingTCPFastOpen() const {
981 if (transport_.get() && transport_->socket()) {
982 return transport_->socket()->UsingTCPFastOpen();
983 }
984 NOTREACHED();
985 return false;
986}
987
[email protected]ffeb0882009-04-30 21:51:25988int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len,
[email protected]ea224582008-12-07 20:25:46989 CompletionCallback* callback) {
[email protected]e17b4c12008-11-05 22:04:08990 EnterFunction(buf_len);
[email protected]a3ff5e92009-10-13 04:48:06991 DCHECK(!user_read_callback_);
[email protected]a6eb576292009-06-30 16:19:00992 DCHECK(!user_connect_callback_);
[email protected]a3ff5e92009-10-13 04:48:06993 DCHECK(!user_read_buf_);
994 DCHECK(nss_bufs_);
[email protected]b43c97c2008-10-22 19:50:58995
[email protected]a3ff5e92009-10-13 04:48:06996 user_read_buf_ = buf;
997 user_read_buf_len_ = buf_len;
[email protected]b43c97c2008-10-22 19:50:58998
[email protected]7a8de3072010-10-01 16:25:54999 if (!completed_handshake_) {
1000 // In this case we have lied about being connected in order to merge the
1001 // first Write into a Snap Start handshake. We'll leave the read hanging
1002 // until the handshake has completed.
1003 DCHECK(pseudo_connected_);
1004
1005 user_read_callback_ = callback;
1006 LeaveFunction(ERR_IO_PENDING);
1007 return ERR_IO_PENDING;
1008 }
1009
[email protected]a3ff5e92009-10-13 04:48:061010 int rv = DoReadLoop(OK);
1011
[email protected]1d583612010-03-12 17:47:141012 if (rv == ERR_IO_PENDING) {
[email protected]a3ff5e92009-10-13 04:48:061013 user_read_callback_ = callback;
[email protected]1d583612010-03-12 17:47:141014 } else {
[email protected]a3ff5e92009-10-13 04:48:061015 user_read_buf_ = NULL;
1016 user_read_buf_len_ = 0;
1017 }
[email protected]ea224582008-12-07 20:25:461018 LeaveFunction(rv);
[email protected]b43c97c2008-10-22 19:50:581019 return rv;
1020}
1021
[email protected]ffeb0882009-04-30 21:51:251022int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len,
[email protected]a3ff5e92009-10-13 04:48:061023 CompletionCallback* callback) {
[email protected]e17b4c12008-11-05 22:04:081024 EnterFunction(buf_len);
[email protected]7a8de3072010-10-01 16:25:541025 if (!pseudo_connected_) {
1026 DCHECK(completed_handshake_);
1027 DCHECK(next_handshake_state_ == STATE_NONE);
1028 DCHECK(!user_connect_callback_);
1029 }
[email protected]a3ff5e92009-10-13 04:48:061030 DCHECK(!user_write_callback_);
[email protected]a3ff5e92009-10-13 04:48:061031 DCHECK(!user_write_buf_);
1032 DCHECK(nss_bufs_);
[email protected]b43c97c2008-10-22 19:50:581033
[email protected]a3ff5e92009-10-13 04:48:061034 user_write_buf_ = buf;
1035 user_write_buf_len_ = buf_len;
[email protected]b43c97c2008-10-22 19:50:581036
[email protected]7a8de3072010-10-01 16:25:541037 if (next_handshake_state_ == STATE_SNAP_START_WAIT_FOR_WRITE) {
1038 // We lied about being connected and we have been waiting for this write in
1039 // order to merge it into the Snap Start handshake. We'll leave the write
1040 // pending until the handshake completes.
1041 DCHECK(pseudo_connected_);
1042 int rv = DoHandshakeLoop(OK);
1043 if (rv == ERR_IO_PENDING) {
1044 user_write_callback_ = callback;
1045 } else {
1046 user_write_buf_ = NULL;
1047 user_write_buf_len_ = 0;
1048 }
1049 if (rv != OK)
1050 return rv;
1051 }
1052
[email protected]fa788512010-10-08 14:48:061053 if (corked_) {
1054 corked_ = false;
1055 uncork_timer_.Reset();
1056 }
[email protected]a3ff5e92009-10-13 04:48:061057 int rv = DoWriteLoop(OK);
1058
[email protected]1d583612010-03-12 17:47:141059 if (rv == ERR_IO_PENDING) {
[email protected]a3ff5e92009-10-13 04:48:061060 user_write_callback_ = callback;
[email protected]1d583612010-03-12 17:47:141061 } else {
[email protected]a3ff5e92009-10-13 04:48:061062 user_write_buf_ = NULL;
1063 user_write_buf_len_ = 0;
1064 }
[email protected]ea224582008-12-07 20:25:461065 LeaveFunction(rv);
[email protected]b43c97c2008-10-22 19:50:581066 return rv;
1067}
1068
[email protected]d3f66572009-09-09 22:38:041069bool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) {
[email protected]e60e47a2010-07-14 03:37:181070 return transport_->socket()->SetReceiveBufferSize(size);
[email protected]d3f66572009-09-09 22:38:041071}
1072
1073bool SSLClientSocketNSS::SetSendBufferSize(int32 size) {
[email protected]e60e47a2010-07-14 03:37:181074 return transport_->socket()->SetSendBufferSize(size);
[email protected]d3f66572009-09-09 22:38:041075}
1076
[email protected]2d6e77832010-11-10 22:13:461077// static
1078void SSLClientSocketNSS::ClearSessionCache() {
1079 SSL_ClearSessionCache();
1080}
1081
[email protected]757f2e2b2010-10-27 23:28:351082// Sets server_cert_ and server_cert_nss_ if not yet set.
1083// Returns server_cert_.
[email protected]bacff652009-03-31 17:50:331084X509Certificate *SSLClientSocketNSS::UpdateServerCert() {
[email protected]757f2e2b2010-10-27 23:28:351085 // We set the server_cert_ from HandshakeCallback().
[email protected]bacff652009-03-31 17:50:331086 if (server_cert_ == NULL) {
[email protected]f505a9b2010-01-28 19:44:021087 server_cert_nss_ = SSL_PeerCertificate(nss_fd_);
1088 if (server_cert_nss_) {
[email protected]4feca4b2010-10-28 16:50:321089 PeerCertificateChain certs(nss_fd_);
[email protected]d8fbf582010-11-04 21:51:121090 server_cert_ = X509Certificate::CreateFromDERCertChain(
1091 certs.AsStringPieceVector());
[email protected]bacff652009-03-31 17:50:331092 }
1093 }
1094 return server_cert_;
1095}
1096
[email protected]757f2e2b2010-10-27 23:28:351097// Sets ssl_connection_status_.
1098void SSLClientSocketNSS::UpdateConnectionStatus() {
1099 SSLChannelInfo channel_info;
1100 SECStatus ok = SSL_GetChannelInfo(nss_fd_,
1101 &channel_info, sizeof(channel_info));
1102 if (ok == SECSuccess &&
1103 channel_info.length == sizeof(channel_info) &&
1104 channel_info.cipherSuite) {
1105 ssl_connection_status_ |=
1106 (static_cast<int>(channel_info.cipherSuite) &
1107 SSL_CONNECTION_CIPHERSUITE_MASK) <<
1108 SSL_CONNECTION_CIPHERSUITE_SHIFT;
1109
1110 ssl_connection_status_ |=
1111 (static_cast<int>(channel_info.compressionMethod) &
1112 SSL_CONNECTION_COMPRESSION_MASK) <<
1113 SSL_CONNECTION_COMPRESSION_SHIFT;
1114
[email protected]b92a96e2010-11-02 21:03:051115 // NSS 3.12.x doesn't have version macros for TLS 1.1 and 1.2 (because NSS
1116 // doesn't support them yet), so we use 0x0302 and 0x0303 directly.
[email protected]757f2e2b2010-10-27 23:28:351117 int version = SSL_CONNECTION_VERSION_UNKNOWN;
1118 if (channel_info.protocolVersion < SSL_LIBRARY_VERSION_3_0) {
1119 // All versions less than SSL_LIBRARY_VERSION_3_0 are treated as SSL
1120 // version 2.
1121 version = SSL_CONNECTION_VERSION_SSL2;
1122 } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_0) {
1123 version = SSL_CONNECTION_VERSION_SSL3;
1124 } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_1_TLS) {
1125 version = SSL_CONNECTION_VERSION_TLS1;
[email protected]b92a96e2010-11-02 21:03:051126 } else if (channel_info.protocolVersion == 0x0302) {
1127 version = SSL_CONNECTION_VERSION_TLS1_1;
1128 } else if (channel_info.protocolVersion == 0x0303) {
1129 version = SSL_CONNECTION_VERSION_TLS1_2;
[email protected]757f2e2b2010-10-27 23:28:351130 }
1131 ssl_connection_status_ |=
1132 (version & SSL_CONNECTION_VERSION_MASK) <<
1133 SSL_CONNECTION_VERSION_SHIFT;
1134 }
1135
[email protected]1e7cd2c72010-02-27 01:31:191136 // SSL_HandshakeNegotiatedExtension was added in NSS 3.12.6.
1137 // Since SSL_MAX_EXTENSIONS was added at the same time, we can test
1138 // SSL_MAX_EXTENSIONS for the presence of SSL_HandshakeNegotiatedExtension.
1139#if defined(SSL_MAX_EXTENSIONS)
[email protected]757f2e2b2010-10-27 23:28:351140 PRBool peer_supports_renego_ext;
1141 ok = SSL_HandshakeNegotiatedExtension(nss_fd_, ssl_renegotiation_info_xtn,
1142 &peer_supports_renego_ext);
1143 if (ok == SECSuccess) {
1144 if (!peer_supports_renego_ext) {
1145 ssl_connection_status_ |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
1146 // Log an informational message if the server does not support secure
1147 // renegotiation (RFC 5746).
[email protected]4f4de7e62010-11-12 19:55:271148 VLOG(1) << "The server " << host_and_port_.ToString()
[email protected]757f2e2b2010-10-27 23:28:351149 << " does not support the TLS renegotiation_info extension.";
1150 }
1151 UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported",
1152 peer_supports_renego_ext, 2);
[email protected]1e7cd2c72010-02-27 01:31:191153 }
1154#endif
[email protected]757f2e2b2010-10-27 23:28:351155
1156 if (ssl_config_.ssl3_fallback)
1157 ssl_connection_status_ |= SSL_CONNECTION_SSL3_FALLBACK;
[email protected]1e7cd2c72010-02-27 01:31:191158}
1159
[email protected]b43c97c2008-10-22 19:50:581160void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
[email protected]e17b4c12008-11-05 22:04:081161 EnterFunction("");
[email protected]b43c97c2008-10-22 19:50:581162 ssl_info->Reset();
[email protected]7a8de3072010-10-01 16:25:541163
1164 if (!server_cert_) {
1165 LOG(DFATAL) << "!server_cert_";
[email protected]2345cc52009-06-04 09:18:471166 return;
[email protected]7a8de3072010-10-01 16:25:541167 }
[email protected]2345cc52009-06-04 09:18:471168
[email protected]3b1d3db2010-10-28 16:39:401169 ssl_info->cert_status = server_cert_verify_result_->cert_status;
[email protected]bacff652009-03-31 17:50:331170 DCHECK(server_cert_ != NULL);
1171 ssl_info->cert = server_cert_;
[email protected]757f2e2b2010-10-27 23:28:351172 ssl_info->connection_status = ssl_connection_status_;
[email protected]644bdca2009-11-30 20:40:531173
[email protected]757f2e2b2010-10-27 23:28:351174 PRUint16 cipher_suite =
1175 SSLConnectionStatusToCipherSuite(ssl_connection_status_);
1176 SSLCipherSuiteInfo cipher_info;
1177 SECStatus ok = SSL_GetCipherSuiteInfo(cipher_suite,
1178 &cipher_info, sizeof(cipher_info));
[email protected]fc7de492010-07-12 14:49:041179 if (ok == SECSuccess) {
[email protected]757f2e2b2010-10-27 23:28:351180 ssl_info->security_bits = cipher_info.effectiveKeyBits;
1181 } else {
1182 ssl_info->security_bits = -1;
1183 LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError()
1184 << " for cipherSuite " << cipher_suite;
[email protected]fc7de492010-07-12 14:49:041185 }
[email protected]e17b4c12008-11-05 22:04:081186 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581187}
1188
[email protected]0b45559b2009-06-12 21:45:111189void SSLClientSocketNSS::GetSSLCertRequestInfo(
1190 SSLCertRequestInfo* cert_request_info) {
[email protected]d84b3722009-10-15 21:23:371191 EnterFunction("");
[email protected]4f4de7e62010-11-12 19:55:271192 // TODO(rch): switch SSLCertRequestInfo.host_and_port to a HostPortPair
1193 cert_request_info->host_and_port = host_and_port_.ToString();
[email protected]b8fee152009-10-24 03:39:311194 cert_request_info->client_certs = client_certs_;
[email protected]d84b3722009-10-15 21:23:371195 LeaveFunction(cert_request_info->client_certs.size());
[email protected]0b45559b2009-06-12 21:45:111196}
1197
[email protected]b28f19d72009-12-10 21:52:271198SSLClientSocket::NextProtoStatus
[email protected]f49ea7d2009-12-11 20:03:501199SSLClientSocketNSS::GetNextProto(std::string* proto) {
1200#if defined(SSL_NEXT_PROTO_NEGOTIATED)
[email protected]7a8de3072010-10-01 16:25:541201 if (!handshake_callback_called_) {
1202 DCHECK(pseudo_connected_);
1203 predicted_npn_proto_used_ = true;
1204 *proto = predicted_npn_proto_;
1205 return predicted_npn_status_;
1206 }
1207
[email protected]f49ea7d2009-12-11 20:03:501208 unsigned char buf[255];
[email protected]b28f19d72009-12-10 21:52:271209 int state;
1210 unsigned len;
1211 SECStatus rv = SSL_GetNextProto(nss_fd_, &state, buf, &len, sizeof(buf));
1212 if (rv != SECSuccess) {
1213 NOTREACHED() << "Error return from SSL_GetNextProto: " << rv;
1214 proto->clear();
1215 return kNextProtoUnsupported;
1216 }
[email protected]f49ea7d2009-12-11 20:03:501217 // We don't check for truncation because sizeof(buf) is large enough to hold
1218 // the maximum protocol size.
[email protected]829296f2010-01-27 02:58:031219 switch (state) {
[email protected]f49ea7d2009-12-11 20:03:501220 case SSL_NEXT_PROTO_NO_SUPPORT:
1221 proto->clear();
1222 return kNextProtoUnsupported;
1223 case SSL_NEXT_PROTO_NEGOTIATED:
1224 *proto = std::string(reinterpret_cast<char*>(buf), len);
1225 return kNextProtoNegotiated;
1226 case SSL_NEXT_PROTO_NO_OVERLAP:
1227 *proto = std::string(reinterpret_cast<char*>(buf), len);
1228 return kNextProtoNoOverlap;
1229 default:
1230 NOTREACHED() << "Unknown status from SSL_GetNextProto: " << state;
1231 proto->clear();
1232 return kNextProtoUnsupported;
[email protected]b28f19d72009-12-10 21:52:271233 }
[email protected]f49ea7d2009-12-11 20:03:501234#else
1235 // No NPN support in the libssl that we are building with.
1236 proto->clear();
1237 return kNextProtoUnsupported;
[email protected]b28f19d72009-12-10 21:52:271238#endif
1239}
1240
[email protected]899c3e92010-08-28 15:53:501241void SSLClientSocketNSS::UseDNSSEC(DNSSECProvider* provider) {
1242 dnssec_provider_ = provider;
1243}
1244
[email protected]a3ff5e92009-10-13 04:48:061245void SSLClientSocketNSS::DoReadCallback(int rv) {
[email protected]e17b4c12008-11-05 22:04:081246 EnterFunction(rv);
[email protected]b43c97c2008-10-22 19:50:581247 DCHECK(rv != ERR_IO_PENDING);
[email protected]a3ff5e92009-10-13 04:48:061248 DCHECK(user_read_callback_);
[email protected]b43c97c2008-10-22 19:50:581249
[email protected]a3ff5e92009-10-13 04:48:061250 // Since Run may result in Read being called, clear |user_read_callback_|
1251 // up front.
1252 CompletionCallback* c = user_read_callback_;
1253 user_read_callback_ = NULL;
1254 user_read_buf_ = NULL;
1255 user_read_buf_len_ = 0;
1256 c->Run(rv);
1257 LeaveFunction("");
1258}
1259
1260void SSLClientSocketNSS::DoWriteCallback(int rv) {
1261 EnterFunction(rv);
1262 DCHECK(rv != ERR_IO_PENDING);
1263 DCHECK(user_write_callback_);
1264
1265 // Since Run may result in Write being called, clear |user_write_callback_|
1266 // up front.
1267 CompletionCallback* c = user_write_callback_;
1268 user_write_callback_ = NULL;
1269 user_write_buf_ = NULL;
1270 user_write_buf_len_ = 0;
[email protected]b43c97c2008-10-22 19:50:581271 c->Run(rv);
[email protected]e17b4c12008-11-05 22:04:081272 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581273}
1274
[email protected]a6eb576292009-06-30 16:19:001275// As part of Connect(), the SSLClientSocketNSS object performs an SSL
1276// handshake. This requires network IO, which in turn calls
1277// BufferRecvComplete() with a non-zero byte count. This byte count eventually
1278// winds its way through the state machine and ends up being passed to the
1279// callback. For Read() and Write(), that's what we want. But for Connect(),
1280// the caller expects OK (i.e. 0) for success.
1281//
1282void SSLClientSocketNSS::DoConnectCallback(int rv) {
1283 EnterFunction(rv);
1284 DCHECK_NE(rv, ERR_IO_PENDING);
[email protected]a6eb576292009-06-30 16:19:001285
[email protected]a6eb576292009-06-30 16:19:001286 CompletionCallback* c = user_connect_callback_;
1287 user_connect_callback_ = NULL;
1288 c->Run(rv > OK ? OK : rv);
1289 LeaveFunction("");
1290}
1291
[email protected]a3ff5e92009-10-13 04:48:061292void SSLClientSocketNSS::OnHandshakeIOComplete(int result) {
[email protected]e17b4c12008-11-05 22:04:081293 EnterFunction(result);
[email protected]a3ff5e92009-10-13 04:48:061294 int rv = DoHandshakeLoop(result);
[email protected]5a05c47a2009-11-02 23:25:191295 if (rv != ERR_IO_PENDING) {
[email protected]ec11be62010-04-28 19:28:091296 net_log_.EndEvent(net::NetLog::TYPE_SSL_CONNECT, NULL);
[email protected]7a8de3072010-10-01 16:25:541297 // If we pseudo connected for Snap Start, then we won't have a connect
1298 // callback.
1299 if (user_connect_callback_)
1300 DoConnectCallback(rv);
[email protected]5a05c47a2009-11-02 23:25:191301 }
[email protected]a3ff5e92009-10-13 04:48:061302 LeaveFunction("");
1303}
1304
1305void SSLClientSocketNSS::OnSendComplete(int result) {
1306 EnterFunction(result);
[email protected]45965de2010-02-25 23:23:311307 if (next_handshake_state_ == STATE_HANDSHAKE) {
[email protected]a3ff5e92009-10-13 04:48:061308 // In handshake phase.
1309 OnHandshakeIOComplete(result);
1310 LeaveFunction("");
1311 return;
[email protected]a6eb576292009-06-30 16:19:001312 }
[email protected]a3ff5e92009-10-13 04:48:061313
1314 // OnSendComplete may need to call DoPayloadRead while the renegotiation
1315 // handshake is in progress.
1316 int rv_read = ERR_IO_PENDING;
1317 int rv_write = ERR_IO_PENDING;
1318 bool network_moved;
1319 do {
1320 if (user_read_buf_)
1321 rv_read = DoPayloadRead();
1322 if (user_write_buf_)
1323 rv_write = DoPayloadWrite();
1324 network_moved = DoTransportIO();
1325 } while (rv_read == ERR_IO_PENDING &&
1326 rv_write == ERR_IO_PENDING &&
1327 network_moved);
1328
1329 if (user_read_buf_ && rv_read != ERR_IO_PENDING)
1330 DoReadCallback(rv_read);
1331 if (user_write_buf_ && rv_write != ERR_IO_PENDING)
1332 DoWriteCallback(rv_write);
1333
1334 LeaveFunction("");
1335}
1336
1337void SSLClientSocketNSS::OnRecvComplete(int result) {
1338 EnterFunction(result);
[email protected]45965de2010-02-25 23:23:311339 if (next_handshake_state_ == STATE_HANDSHAKE) {
[email protected]a3ff5e92009-10-13 04:48:061340 // In handshake phase.
1341 OnHandshakeIOComplete(result);
1342 LeaveFunction("");
1343 return;
1344 }
1345
1346 // Network layer received some data, check if client requested to read
[email protected]7a8de3072010-10-01 16:25:541347 // decrypted data or if we're waiting for the first write for Snap Start.
1348 if (!user_read_buf_ || !completed_handshake_) {
[email protected]a3ff5e92009-10-13 04:48:061349 LeaveFunction("");
1350 return;
1351 }
1352
1353 int rv = DoReadLoop(result);
1354 if (rv != ERR_IO_PENDING)
1355 DoReadCallback(rv);
[email protected]e17b4c12008-11-05 22:04:081356 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581357}
1358
[email protected]b0735462009-11-04 22:11:261359// Map a Chromium net error code to an NSS error code.
[email protected]b43c97c2008-10-22 19:50:581360// See _MD_unix_map_default_error in the NSS source
1361// tree for inspiration.
1362static PRErrorCode MapErrorToNSS(int result) {
1363 if (result >=0)
1364 return result;
[email protected]b0735462009-11-04 22:11:261365
1366 switch (result) {
1367 case ERR_IO_PENDING:
1368 return PR_WOULD_BLOCK_ERROR;
1369 case ERR_ACCESS_DENIED:
[email protected]e5925962010-11-02 14:37:141370 case ERR_NETWORK_ACCESS_DENIED:
[email protected]b0735462009-11-04 22:11:261371 // For connect, this could be mapped to PR_ADDRESS_NOT_SUPPORTED_ERROR.
1372 return PR_NO_ACCESS_RIGHTS_ERROR;
[email protected]4a842342010-11-04 16:21:331373 case ERR_NOT_IMPLEMENTED:
1374 return PR_NOT_IMPLEMENTED_ERROR;
[email protected]b0735462009-11-04 22:11:261375 case ERR_INTERNET_DISCONNECTED: // Equivalent to ENETDOWN.
1376 return PR_NETWORK_UNREACHABLE_ERROR; // Best approximation.
1377 case ERR_CONNECTION_TIMED_OUT:
1378 case ERR_TIMED_OUT:
1379 return PR_IO_TIMEOUT_ERROR;
1380 case ERR_CONNECTION_RESET:
1381 return PR_CONNECT_RESET_ERROR;
1382 case ERR_CONNECTION_ABORTED:
1383 return PR_CONNECT_ABORTED_ERROR;
1384 case ERR_CONNECTION_REFUSED:
1385 return PR_CONNECT_REFUSED_ERROR;
1386 case ERR_ADDRESS_UNREACHABLE:
1387 return PR_HOST_UNREACHABLE_ERROR; // Also PR_NETWORK_UNREACHABLE_ERROR.
1388 case ERR_ADDRESS_INVALID:
1389 return PR_ADDRESS_NOT_AVAILABLE_ERROR;
[email protected]4d3040f42010-04-14 02:40:201390 case ERR_NAME_NOT_RESOLVED:
1391 return PR_DIRECTORY_LOOKUP_ERROR;
[email protected]b0735462009-11-04 22:11:261392 default:
1393 LOG(WARNING) << "MapErrorToNSS " << result
1394 << " mapped to PR_UNKNOWN_ERROR";
1395 return PR_UNKNOWN_ERROR;
1396 }
[email protected]b43c97c2008-10-22 19:50:581397}
1398
[email protected]ffeb0882009-04-30 21:51:251399// Do network I/O between the given buffer and the given socket.
[email protected]a3ff5e92009-10-13 04:48:061400// Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING)
1401bool SSLClientSocketNSS::DoTransportIO() {
1402 EnterFunction("");
1403 bool network_moved = false;
1404 if (nss_bufs_ != NULL) {
1405 int nsent = BufferSend();
1406 int nreceived = BufferRecv();
1407 network_moved = (nsent > 0 || nreceived >= 0);
1408 }
1409 LeaveFunction(network_moved);
1410 return network_moved;
1411}
1412
[email protected]ffeb0882009-04-30 21:51:251413// Return 0 for EOF,
1414// > 0 for bytes transferred immediately,
1415// < 0 for error (or the non-error ERR_IO_PENDING).
[email protected]b43c97c2008-10-22 19:50:581416int SSLClientSocketNSS::BufferSend(void) {
[email protected]9ae2ee02010-09-08 16:41:141417 if (transport_send_busy_)
1418 return ERR_IO_PENDING;
[email protected]b43c97c2008-10-22 19:50:581419
[email protected]914286d62009-12-10 23:06:441420 EnterFunction("");
[email protected]9ae2ee02010-09-08 16:41:141421 const char* buf1;
1422 const char* buf2;
1423 unsigned int len1, len2;
1424 memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2);
1425 const unsigned int len = len1 + len2;
[email protected]b43c97c2008-10-22 19:50:581426
[email protected]9ae2ee02010-09-08 16:41:141427 if (corked_ && len < kRecvBufferSize / 2)
1428 return 0;
1429
1430 int rv = 0;
1431 if (len) {
[email protected]ad8e04a2010-11-01 04:16:271432 scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
[email protected]9ae2ee02010-09-08 16:41:141433 memcpy(send_buffer->data(), buf1, len1);
1434 memcpy(send_buffer->data() + len1, buf2, len2);
1435 rv = transport_->socket()->Write(send_buffer, len,
1436 &buffer_send_callback_);
[email protected]914286d62009-12-10 23:06:441437 if (rv == ERR_IO_PENDING) {
[email protected]b43c97c2008-10-22 19:50:581438 transport_send_busy_ = true;
[email protected]914286d62009-12-10 23:06:441439 } else {
[email protected]b43c97c2008-10-22 19:50:581440 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
[email protected]914286d62009-12-10 23:06:441441 }
[email protected]b43c97c2008-10-22 19:50:581442 }
1443
[email protected]9ae2ee02010-09-08 16:41:141444 LeaveFunction(rv);
1445 return rv;
[email protected]b43c97c2008-10-22 19:50:581446}
1447
1448void SSLClientSocketNSS::BufferSendComplete(int result) {
[email protected]e17b4c12008-11-05 22:04:081449 EnterFunction(result);
[email protected]7f7e92392010-10-26 18:29:291450
1451 // In the case of TCP FastOpen, connect is now finished.
1452 if (!peername_initialized_ && UsingTCPFastOpen())
1453 InitializeSSLPeerName();
1454
[email protected]b0735462009-11-04 22:11:261455 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
[email protected]b43c97c2008-10-22 19:50:581456 transport_send_busy_ = false;
[email protected]a3ff5e92009-10-13 04:48:061457 OnSendComplete(result);
[email protected]e17b4c12008-11-05 22:04:081458 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581459}
1460
1461
1462int SSLClientSocketNSS::BufferRecv(void) {
[email protected]b43c97c2008-10-22 19:50:581463 if (transport_recv_busy_) return ERR_IO_PENDING;
1464
1465 char *buf;
1466 int nb = memio_GetReadParams(nss_bufs_, &buf);
[email protected]e17b4c12008-11-05 22:04:081467 EnterFunction(nb);
[email protected]b43c97c2008-10-22 19:50:581468 int rv;
1469 if (!nb) {
1470 // buffer too full to read into, so no I/O possible at moment
1471 rv = ERR_IO_PENDING;
1472 } else {
[email protected]ffeb0882009-04-30 21:51:251473 recv_buffer_ = new IOBuffer(nb);
[email protected]e60e47a2010-07-14 03:37:181474 rv = transport_->socket()->Read(recv_buffer_, nb, &buffer_recv_callback_);
[email protected]ffeb0882009-04-30 21:51:251475 if (rv == ERR_IO_PENDING) {
[email protected]b43c97c2008-10-22 19:50:581476 transport_recv_busy_ = true;
[email protected]ffeb0882009-04-30 21:51:251477 } else {
1478 if (rv > 0)
1479 memcpy(buf, recv_buffer_->data(), rv);
[email protected]b43c97c2008-10-22 19:50:581480 memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
[email protected]ffeb0882009-04-30 21:51:251481 recv_buffer_ = NULL;
1482 }
[email protected]b43c97c2008-10-22 19:50:581483 }
[email protected]e17b4c12008-11-05 22:04:081484 LeaveFunction(rv);
[email protected]b43c97c2008-10-22 19:50:581485 return rv;
1486}
1487
1488void SSLClientSocketNSS::BufferRecvComplete(int result) {
[email protected]e17b4c12008-11-05 22:04:081489 EnterFunction(result);
[email protected]ffeb0882009-04-30 21:51:251490 if (result > 0) {
1491 char *buf;
1492 memio_GetReadParams(nss_bufs_, &buf);
1493 memcpy(buf, recv_buffer_->data(), result);
1494 }
1495 recv_buffer_ = NULL;
[email protected]b0735462009-11-04 22:11:261496 memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
[email protected]b43c97c2008-10-22 19:50:581497 transport_recv_busy_ = false;
[email protected]a3ff5e92009-10-13 04:48:061498 OnRecvComplete(result);
[email protected]e17b4c12008-11-05 22:04:081499 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581500}
1501
[email protected]a3ff5e92009-10-13 04:48:061502int SSLClientSocketNSS::DoHandshakeLoop(int last_io_result) {
[email protected]e17b4c12008-11-05 22:04:081503 EnterFunction(last_io_result);
[email protected]b43c97c2008-10-22 19:50:581504 bool network_moved;
1505 int rv = last_io_result;
1506 do {
[email protected]e17b4c12008-11-05 22:04:081507 // Default to STATE_NONE for next state.
[email protected]ea224582008-12-07 20:25:461508 // (This is a quirk carried over from the windows
[email protected]e17b4c12008-11-05 22:04:081509 // implementation. It makes reading the logs a bit harder.)
[email protected]ea224582008-12-07 20:25:461510 // State handlers can and often do call GotoState just
[email protected]e17b4c12008-11-05 22:04:081511 // to stay in the current state.
[email protected]a3ff5e92009-10-13 04:48:061512 State state = next_handshake_state_;
[email protected]e17b4c12008-11-05 22:04:081513 GotoState(STATE_NONE);
[email protected]b43c97c2008-10-22 19:50:581514 switch (state) {
[email protected]e17b4c12008-11-05 22:04:081515 case STATE_NONE:
1516 // we're just pumping data between the buffer and the network
1517 break;
[email protected]7a8de3072010-10-01 16:25:541518 case STATE_SNAP_START_LOAD_INFO:
1519 rv = DoSnapStartLoadInfo();
1520 break;
1521 case STATE_SNAP_START_WAIT_FOR_WRITE:
1522 rv = DoSnapStartWaitForWrite();
1523 break;
[email protected]a3ff5e92009-10-13 04:48:061524 case STATE_HANDSHAKE:
1525 rv = DoHandshake();
[email protected]b43c97c2008-10-22 19:50:581526 break;
[email protected]899c3e92010-08-28 15:53:501527 case STATE_VERIFY_DNSSEC:
1528 rv = DoVerifyDNSSEC(rv);
1529 break;
1530 case STATE_VERIFY_DNSSEC_COMPLETE:
1531 rv = DoVerifyDNSSECComplete(rv);
1532 break;
[email protected]2345cc52009-06-04 09:18:471533 case STATE_VERIFY_CERT:
1534 DCHECK(rv == OK);
1535 rv = DoVerifyCert(rv);
1536 break;
1537 case STATE_VERIFY_CERT_COMPLETE:
1538 rv = DoVerifyCertComplete(rv);
1539 break;
[email protected]b43c97c2008-10-22 19:50:581540 default:
1541 rv = ERR_UNEXPECTED;
[email protected]4e91b5c2010-09-22 01:04:381542 LOG(DFATAL) << "unexpected state " << state;
[email protected]b43c97c2008-10-22 19:50:581543 break;
1544 }
1545
1546 // Do the actual network I/O
[email protected]a3ff5e92009-10-13 04:48:061547 network_moved = DoTransportIO();
[email protected]72d1e592009-03-10 17:39:461548 } while ((rv != ERR_IO_PENDING || network_moved) &&
[email protected]7a8de3072010-10-01 16:25:541549 next_handshake_state_ != STATE_NONE);
[email protected]a3ff5e92009-10-13 04:48:061550 LeaveFunction("");
1551 return rv;
1552}
1553
1554int SSLClientSocketNSS::DoReadLoop(int result) {
1555 EnterFunction("");
1556 DCHECK(completed_handshake_);
1557 DCHECK(next_handshake_state_ == STATE_NONE);
1558
1559 if (result < 0)
1560 return result;
1561
[email protected]4e91b5c2010-09-22 01:04:381562 if (!nss_bufs_) {
1563 LOG(DFATAL) << "!nss_bufs_";
[email protected]7cbc6df12010-10-04 16:25:391564 int rv = ERR_UNEXPECTED;
[email protected]00cd9c42010-11-02 20:15:571565 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
1566 make_scoped_refptr(new SSLErrorParams(rv, 0)));
[email protected]7cbc6df12010-10-04 16:25:391567 return rv;
[email protected]4e91b5c2010-09-22 01:04:381568 }
[email protected]a3ff5e92009-10-13 04:48:061569
1570 bool network_moved;
1571 int rv;
1572 do {
1573 rv = DoPayloadRead();
1574 network_moved = DoTransportIO();
1575 } while (rv == ERR_IO_PENDING && network_moved);
1576
1577 LeaveFunction("");
1578 return rv;
1579}
1580
1581int SSLClientSocketNSS::DoWriteLoop(int result) {
1582 EnterFunction("");
1583 DCHECK(completed_handshake_);
1584 DCHECK(next_handshake_state_ == STATE_NONE);
1585
1586 if (result < 0)
1587 return result;
1588
[email protected]4e91b5c2010-09-22 01:04:381589 if (!nss_bufs_) {
1590 LOG(DFATAL) << "!nss_bufs_";
[email protected]7cbc6df12010-10-04 16:25:391591 int rv = ERR_UNEXPECTED;
[email protected]00cd9c42010-11-02 20:15:571592 net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
1593 make_scoped_refptr(new SSLErrorParams(rv, 0)));
[email protected]7cbc6df12010-10-04 16:25:391594 return rv;
[email protected]4e91b5c2010-09-22 01:04:381595 }
[email protected]a3ff5e92009-10-13 04:48:061596
1597 bool network_moved;
1598 int rv;
1599 do {
1600 rv = DoPayloadWrite();
1601 network_moved = DoTransportIO();
1602 } while (rv == ERR_IO_PENDING && network_moved);
1603
[email protected]e17b4c12008-11-05 22:04:081604 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581605 return rv;
1606}
1607
[email protected]bacff652009-03-31 17:50:331608// static
1609// NSS calls this if an incoming certificate needs to be verified.
[email protected]2345cc52009-06-04 09:18:471610// Do nothing but return SECSuccess.
1611// This is called only in full handshake mode.
1612// Peer certificate is retrieved in HandshakeCallback() later, which is called
1613// in full handshake mode or in resumption handshake mode.
[email protected]bacff652009-03-31 17:50:331614SECStatus SSLClientSocketNSS::OwnAuthCertHandler(void* arg,
1615 PRFileDesc* socket,
1616 PRBool checksig,
1617 PRBool is_server) {
[email protected]9ae2ee02010-09-08 16:41:141618#ifdef SSL_ENABLE_FALSE_START
1619 // In the event that we are False Starting this connection, we wish to send
1620 // out the Finished message and first application data record in the same
1621 // packet. This prevents non-determinism when talking to False Start
1622 // intolerant servers which, otherwise, might see the two messages in
1623 // different reads or not, depending on network conditions.
1624 PRBool false_start = 0;
1625 SECStatus rv = SSL_OptionGet(socket, SSL_ENABLE_FALSE_START, &false_start);
[email protected]79ba2d82010-11-05 14:07:461626 DCHECK_EQ(SECSuccess, rv);
1627
[email protected]9ae2ee02010-09-08 16:41:141628 if (false_start) {
1629 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg);
[email protected]563cbcc62010-10-11 23:07:521630
1631 // ESET anti-virus is capable of intercepting HTTPS connections on Windows.
1632 // However, it is False Start intolerant and causes the connections to hang
1633 // forever. We detect ESET by the issuer of the leaf certificate and set a
1634 // flag to return a specific error, giving the user instructions for
1635 // reconfiguring ESET.
1636 CERTCertificate* cert = SSL_PeerCertificate(that->nss_fd_);
1637 if (cert) {
1638 char* common_name = CERT_GetCommonName(&cert->issuer);
1639 if (common_name) {
1640 if (strcmp(common_name, "ESET_RootSslCert") == 0)
1641 that->eset_mitm_detected_ = true;
[email protected]79ba2d82010-11-05 14:07:461642 if (strcmp(common_name, "ContentWatch Root Certificate Authority") == 0) {
1643 // This is NetNanny. NetNanny are updating their product so we
1644 // silently disable False Start for now.
1645 rv = SSL_OptionSet(socket, SSL_ENABLE_FALSE_START, PR_FALSE);
1646 DCHECK_EQ(SECSuccess, rv);
1647 false_start = 0;
1648 }
[email protected]563cbcc62010-10-11 23:07:521649 PORT_Free(common_name);
1650 }
1651 CERT_DestroyCertificate(cert);
1652 }
[email protected]79ba2d82010-11-05 14:07:461653
1654 if (false_start && !that->handshake_callback_called_) {
1655 that->corked_ = true;
1656 that->uncork_timer_.Start(
1657 base::TimeDelta::FromMilliseconds(kCorkTimeoutMs),
1658 that, &SSLClientSocketNSS::UncorkAfterTimeout);
1659 }
[email protected]9ae2ee02010-09-08 16:41:141660 }
1661#endif
1662
[email protected]2345cc52009-06-04 09:18:471663 // Tell NSS to not verify the certificate.
1664 return SECSuccess;
1665}
1666
[email protected]4a842342010-11-04 16:21:331667#if defined(NSS_PLATFORM_CLIENT_AUTH)
[email protected]2345cc52009-06-04 09:18:471668// static
[email protected]d84b3722009-10-15 21:23:371669// NSS calls this if a client certificate is needed.
[email protected]4a842342010-11-04 16:21:331670SECStatus SSLClientSocketNSS::PlatformClientAuthHandler(
[email protected]d84b3722009-10-15 21:23:371671 void* arg,
1672 PRFileDesc* socket,
1673 CERTDistNames* ca_names,
[email protected]4a842342010-11-04 16:21:331674 CERTCertList** result_certs,
1675 void** result_private_key) {
[email protected]d84b3722009-10-15 21:23:371676 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg);
1677
1678 that->client_auth_cert_needed_ = !that->ssl_config_.send_client_cert;
[email protected]1d583612010-03-12 17:47:141679#if defined(OS_WIN)
1680 if (that->ssl_config_.send_client_cert) {
[email protected]4a842342010-11-04 16:21:331681 if (that->ssl_config_.client_cert) {
1682 PCCERT_CONTEXT cert_context =
1683 that->ssl_config_.client_cert->os_cert_handle();
[email protected]b493c0b92010-11-11 05:12:421684 if (VLOG_IS_ON(1)) {
1685 do {
1686 DWORD size_needed = 0;
1687 BOOL got_info = CertGetCertificateContextProperty(
1688 cert_context, CERT_KEY_PROV_INFO_PROP_ID, NULL, &size_needed);
1689 if (!got_info) {
1690 VLOG(1) << "Failed to get key prov info size " << GetLastError();
1691 break;
1692 }
1693 std::vector<BYTE> raw_info(size_needed);
1694 got_info = CertGetCertificateContextProperty(
1695 cert_context, CERT_KEY_PROV_INFO_PROP_ID, &raw_info[0],
1696 &size_needed);
1697 if (!got_info) {
1698 VLOG(1) << "Failed to get key prov info " << GetLastError();
1699 break;
1700 }
1701 PCRYPT_KEY_PROV_INFO info =
1702 reinterpret_cast<PCRYPT_KEY_PROV_INFO>(&raw_info[0]);
1703 VLOG(1) << "Container Name: " << info->pwszContainerName
1704 << "\nProvider Name: " << info->pwszProvName
1705 << "\nProvider Type: " << info->dwProvType
1706 << "\nFlags: " << info->dwFlags
1707 << "\nProvider Param Count: " << info->cProvParam
1708 << "\nKey Specifier: " << info->dwKeySpec;
1709 } while (false);
1710
1711 do {
1712 DWORD size_needed = 0;
1713 BOOL got_identifier = CertGetCertificateContextProperty(
1714 cert_context, CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size_needed);
1715 if (!got_identifier) {
1716 VLOG(1) << "Failed to get key identifier size "
1717 << GetLastError();
1718 break;
1719 }
1720 std::vector<BYTE> raw_id(size_needed);
1721 got_identifier = CertGetCertificateContextProperty(
1722 cert_context, CERT_KEY_IDENTIFIER_PROP_ID, &raw_id[0],
1723 &size_needed);
1724 if (!got_identifier) {
1725 VLOG(1) << "Failed to get key identifier " << GetLastError();
1726 break;
1727 }
1728 VLOG(1) << "Key Identifier: " << base::HexEncode(&raw_id[0],
1729 size_needed);
1730 } while (false);
1731 }
[email protected]4a842342010-11-04 16:21:331732 HCRYPTPROV provider = NULL;
1733 DWORD key_spec = AT_KEYEXCHANGE;
1734 BOOL must_free = FALSE;
1735 BOOL acquired_key = CryptAcquireCertificatePrivateKey(
1736 cert_context,
1737 CRYPT_ACQUIRE_CACHE_FLAG | CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
1738 NULL, &provider, &key_spec, &must_free);
1739 if (acquired_key && provider) {
1740 DCHECK_NE(key_spec, CERT_NCRYPT_KEY_SPEC);
1741
1742 // The certificate cache may have been updated/used, in which case,
1743 // duplicate the existing handle, since NSS will free it when no
1744 // longer in use.
1745 if (!must_free)
1746 CryptContextAddRef(provider, NULL, 0);
1747
1748 SECItem der_cert;
1749 der_cert.type = siDERCertBuffer;
1750 der_cert.data = cert_context->pbCertEncoded;
1751 der_cert.len = cert_context->cbCertEncoded;
1752
1753 // TODO(rsleevi): Error checking for NSS allocation errors.
1754 *result_certs = CERT_NewCertList();
1755 CERTCertDBHandle* db_handle = CERT_GetDefaultCertDB();
1756 CERTCertificate* user_cert = CERT_NewTempCertificate(
1757 db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE);
1758 CERT_AddCertToListTail(*result_certs, user_cert);
1759
1760 // Add the intermediates.
1761 X509Certificate::OSCertHandles intermediates =
1762 that->ssl_config_.client_cert->GetIntermediateCertificates();
1763 for (X509Certificate::OSCertHandles::const_iterator it =
1764 intermediates.begin(); it != intermediates.end(); ++it) {
1765 der_cert.data = (*it)->pbCertEncoded;
1766 der_cert.len = (*it)->cbCertEncoded;
1767
1768 CERTCertificate* intermediate = CERT_NewTempCertificate(
1769 db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE);
1770 CERT_AddCertToListTail(*result_certs, intermediate);
1771 }
1772 // TODO(wtc): |key_spec| should be passed along with |provider|.
1773 *result_private_key = reinterpret_cast<void*>(provider);
1774 return SECSuccess;
1775 }
1776 LOG(WARNING) << "Client cert found without private key";
1777 }
[email protected]1d583612010-03-12 17:47:141778 // Send no client certificate.
1779 return SECFailure;
1780 }
1781
1782 that->client_certs_.clear();
1783
1784 std::vector<CERT_NAME_BLOB> issuer_list(ca_names->nnames);
1785 for (int i = 0; i < ca_names->nnames; ++i) {
1786 issuer_list[i].cbData = ca_names->names[i].len;
1787 issuer_list[i].pbData = ca_names->names[i].data;
1788 }
1789
1790 // Client certificates of the user are in the "MY" system certificate store.
1791 HCERTSTORE my_cert_store = CertOpenSystemStore(NULL, L"MY");
1792 if (!my_cert_store) {
1793 LOG(ERROR) << "Could not open the \"MY\" system certificate store: "
1794 << GetLastError();
1795 return SECFailure;
1796 }
1797
1798 // Enumerate the client certificates.
1799 CERT_CHAIN_FIND_BY_ISSUER_PARA find_by_issuer_para;
1800 memset(&find_by_issuer_para, 0, sizeof(find_by_issuer_para));
1801 find_by_issuer_para.cbSize = sizeof(find_by_issuer_para);
1802 find_by_issuer_para.pszUsageIdentifier = szOID_PKIX_KP_CLIENT_AUTH;
1803 find_by_issuer_para.cIssuer = ca_names->nnames;
1804 find_by_issuer_para.rgIssuer = ca_names->nnames ? &issuer_list[0] : NULL;
[email protected]01640f62010-08-10 19:42:121805 find_by_issuer_para.pfnFindCallback = ClientCertFindCallback;
[email protected]1d583612010-03-12 17:47:141806
1807 PCCERT_CHAIN_CONTEXT chain_context = NULL;
1808
1809 for (;;) {
1810 // Find a certificate chain.
1811 chain_context = CertFindChainInStore(my_cert_store,
1812 X509_ASN_ENCODING,
1813 0,
1814 CERT_CHAIN_FIND_BY_ISSUER,
1815 &find_by_issuer_para,
1816 chain_context);
1817 if (!chain_context) {
1818 DWORD err = GetLastError();
1819 if (err != CRYPT_E_NOT_FOUND)
1820 DLOG(ERROR) << "CertFindChainInStore failed: " << err;
1821 break;
1822 }
1823
1824 // Get the leaf certificate.
1825 PCCERT_CONTEXT cert_context =
1826 chain_context->rgpChain[0]->rgpElement[0]->pCertContext;
1827 // Copy it to our own certificate store, so that we can close the "MY"
1828 // certificate store before returning from this function.
1829 PCCERT_CONTEXT cert_context2;
[email protected]670dca92010-10-26 13:27:091830 BOOL ok = CertAddCertificateContextToStore(X509Certificate::cert_store(),
1831 cert_context,
[email protected]1d583612010-03-12 17:47:141832 CERT_STORE_ADD_USE_EXISTING,
1833 &cert_context2);
1834 if (!ok) {
1835 NOTREACHED();
1836 continue;
1837 }
[email protected]4a842342010-11-04 16:21:331838
1839 // Copy the rest of the chain to our own store as well. Copying the chain
1840 // stops gracefully if an error is encountered, with the partial chain
1841 // being used as the intermediates, rather than failing to consider the
1842 // client certificate.
1843 net::X509Certificate::OSCertHandles intermediates;
1844 for (DWORD i = 1; i < chain_context->rgpChain[0]->cElement; i++) {
1845 PCCERT_CONTEXT intermediate_copy;
1846 ok = CertAddCertificateContextToStore(X509Certificate::cert_store(),
1847 chain_context->rgpChain[0]->rgpElement[i]->pCertContext,
1848 CERT_STORE_ADD_USE_EXISTING, &intermediate_copy);
1849 if (!ok) {
1850 NOTREACHED();
1851 break;
1852 }
1853 intermediates.push_back(intermediate_copy);
1854 }
1855
[email protected]1d583612010-03-12 17:47:141856 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle(
1857 cert_context2, X509Certificate::SOURCE_LONE_CERT_IMPORT,
[email protected]4a842342010-11-04 16:21:331858 intermediates);
[email protected]1d583612010-03-12 17:47:141859 that->client_certs_.push_back(cert);
[email protected]4a842342010-11-04 16:21:331860
1861 X509Certificate::FreeOSCertHandle(cert_context2);
1862 for (net::X509Certificate::OSCertHandles::iterator it =
1863 intermediates.begin(); it != intermediates.end(); ++it) {
1864 net::X509Certificate::FreeOSCertHandle(*it);
1865 }
[email protected]1d583612010-03-12 17:47:141866 }
1867
1868 BOOL ok = CertCloseStore(my_cert_store, CERT_CLOSE_STORE_CHECK_FLAG);
1869 DCHECK(ok);
1870
1871 // Tell NSS to suspend the client authentication. We will then abort the
1872 // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
1873 return SECWouldBlock;
[email protected]3dd6f5e2010-06-01 20:28:031874#elif defined(OS_MACOSX)
[email protected]fd4f139f2010-06-11 17:02:201875 if (that->ssl_config_.send_client_cert) {
[email protected]4a842342010-11-04 16:21:331876 if (that->ssl_config_.client_cert) {
1877 OSStatus os_error = noErr;
1878 SecIdentityRef identity = NULL;
1879 SecKeyRef private_key = NULL;
1880 CFArrayRef chain =
1881 that->ssl_config_.client_cert->CreateClientCertificateChain();
1882 if (chain) {
1883 identity = reinterpret_cast<SecIdentityRef>(
1884 const_cast<void*>(CFArrayGetValueAtIndex(chain, 0)));
1885 }
1886 if (identity)
1887 os_error = SecIdentityCopyPrivateKey(identity, &private_key);
1888
1889 if (chain && identity && os_error == noErr) {
1890 // TODO(rsleevi): Error checking for NSS allocation errors.
1891 *result_certs = CERT_NewCertList();
1892 *result_private_key = reinterpret_cast<void*>(private_key);
1893
1894 for (CFIndex i = 0; i < CFArrayGetCount(chain); ++i) {
1895 CSSM_DATA cert_data;
1896 SecCertificateRef cert_ref;
1897 if (i == 0) {
1898 cert_ref = that->ssl_config_.client_cert->os_cert_handle();
1899 } else {
1900 cert_ref = reinterpret_cast<SecCertificateRef>(
1901 const_cast<void*>(CFArrayGetValueAtIndex(chain, i)));
1902 }
1903 os_error = SecCertificateGetData(cert_ref, &cert_data);
1904 if (os_error != noErr)
1905 break;
1906
1907 SECItem der_cert;
1908 der_cert.type = siDERCertBuffer;
1909 der_cert.data = cert_data.Data;
1910 der_cert.len = cert_data.Length;
1911 CERTCertificate* nss_cert = CERT_NewTempCertificate(
1912 CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
1913 CERT_AddCertToListTail(*result_certs, nss_cert);
1914 }
1915 }
1916 if (os_error == noErr) {
1917 CFRelease(chain);
1918 return SECSuccess;
1919 }
1920 LOG(WARNING) << "Client cert found, but could not be used: "
1921 << os_error;
1922 if (*result_certs) {
1923 CERT_DestroyCertList(*result_certs);
1924 *result_certs = NULL;
1925 }
1926 if (*result_private_key)
1927 *result_private_key = NULL;
1928 if (private_key)
1929 CFRelease(private_key);
1930 if (chain)
1931 CFRelease(chain);
1932 }
[email protected]fd4f139f2010-06-11 17:02:201933 // Send no client certificate.
1934 return SECFailure;
1935 }
1936
1937 that->client_certs_.clear();
1938
1939 // First, get the cert issuer names allowed by the server.
1940 std::vector<CertPrincipal> valid_issuers;
1941 int n = ca_names->nnames;
1942 for (int i = 0; i < n; i++) {
1943 // Parse each name into a CertPrincipal object.
1944 CertPrincipal p;
1945 if (p.ParseDistinguishedName(ca_names->names[i].data,
1946 ca_names->names[i].len)) {
1947 valid_issuers.push_back(p);
1948 }
1949 }
1950
1951 // Now get the available client certs whose issuers are allowed by the server.
[email protected]4f4de7e62010-11-12 19:55:271952 X509Certificate::GetSSLClientCertificates(that->host_and_port_.host(),
[email protected]fd4f139f2010-06-11 17:02:201953 valid_issuers,
1954 &that->client_certs_);
1955
1956 // Tell NSS to suspend the client authentication. We will then abort the
1957 // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
1958 return SECWouldBlock;
[email protected]1d583612010-03-12 17:47:141959#else
[email protected]4a842342010-11-04 16:21:331960 return SECFailure;
1961#endif
1962}
1963
1964#else // NSS_PLATFORM_CLIENT_AUTH
1965
1966// static
1967// NSS calls this if a client certificate is needed.
1968// Based on Mozilla's NSS_GetClientAuthData.
1969SECStatus SSLClientSocketNSS::ClientAuthHandler(
1970 void* arg,
1971 PRFileDesc* socket,
1972 CERTDistNames* ca_names,
1973 CERTCertificate** result_certificate,
1974 SECKEYPrivateKey** result_private_key) {
1975 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg);
1976
1977 that->client_auth_cert_needed_ = !that->ssl_config_.send_client_cert;
[email protected]b8fee152009-10-24 03:39:311978 void* wincx = SSL_RevealPinArg(socket);
1979
[email protected]d84b3722009-10-15 21:23:371980 // Second pass: a client certificate should have been selected.
1981 if (that->ssl_config_.send_client_cert) {
1982 if (that->ssl_config_.client_cert) {
[email protected]701e8692010-08-17 20:00:431983 CERTCertificate* cert = CERT_DupCertificate(
[email protected]d84b3722009-10-15 21:23:371984 that->ssl_config_.client_cert->os_cert_handle());
[email protected]701e8692010-08-17 20:00:431985 SECKEYPrivateKey* privkey = PK11_FindKeyByAnyCert(cert, wincx);
[email protected]d84b3722009-10-15 21:23:371986 if (privkey) {
1987 // TODO(jsorianopastor): We should wait for server certificate
1988 // verification before sending our credentials. See
1989 // http://crbug.com/13934.
1990 *result_certificate = cert;
1991 *result_private_key = privkey;
1992 return SECSuccess;
1993 }
1994 LOG(WARNING) << "Client cert found without private key";
1995 }
1996 // Send no client certificate.
1997 return SECFailure;
1998 }
1999
[email protected]701e8692010-08-17 20:00:432000 // Iterate over all client certificates.
2001 CERTCertList* client_certs = CERT_FindUserCertsByUsage(
2002 CERT_GetDefaultCertDB(), certUsageSSLClient,
2003 PR_FALSE, PR_FALSE, wincx);
2004 if (client_certs) {
2005 for (CERTCertListNode* node = CERT_LIST_HEAD(client_certs);
2006 !CERT_LIST_END(node, client_certs);
2007 node = CERT_LIST_NEXT(node)) {
2008 // Only offer unexpired certificates.
2009 if (CERT_CheckCertValidTimes(node->cert, PR_Now(), PR_TRUE) !=
2010 secCertTimeValid)
[email protected]b8fee152009-10-24 03:39:312011 continue;
[email protected]701e8692010-08-17 20:00:432012 // Filter by issuer.
2013 //
2014 // TODO(davidben): This does a binary comparison of the DER-encoded
2015 // issuers. We should match according to RFC 5280 sec. 7.1. We should find
2016 // an appropriate NSS function or add one if needbe.
2017 if (ca_names->nnames &&
2018 NSS_CmpCertChainWCANames(node->cert, ca_names) != SECSuccess)
2019 continue;
2020 X509Certificate* x509_cert = X509Certificate::CreateFromHandle(
2021 node->cert, X509Certificate::SOURCE_LONE_CERT_IMPORT,
2022 net::X509Certificate::OSCertHandles());
2023 that->client_certs_.push_back(x509_cert);
[email protected]b8fee152009-10-24 03:39:312024 }
[email protected]701e8692010-08-17 20:00:432025 CERT_DestroyCertList(client_certs);
[email protected]b8fee152009-10-24 03:39:312026 }
[email protected]d84b3722009-10-15 21:23:372027
[email protected]f6ee0a012010-03-05 22:00:242028 // Tell NSS to suspend the client authentication. We will then abort the
2029 // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
2030 return SECWouldBlock;
[email protected]d84b3722009-10-15 21:23:372031}
[email protected]4a842342010-11-04 16:21:332032#endif // NSS_PLATFORM_CLIENT_AUTH
[email protected]d84b3722009-10-15 21:23:372033
2034// static
[email protected]2345cc52009-06-04 09:18:472035// NSS calls this when handshake is completed.
2036// After the SSL handshake is finished, use CertVerifier to verify
2037// the saved server certificate.
2038void SSLClientSocketNSS::HandshakeCallback(PRFileDesc* socket,
2039 void* arg) {
[email protected]bacff652009-03-31 17:50:332040 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg);
2041
[email protected]7a8de3072010-10-01 16:25:542042 that->handshake_callback_called_ = true;
[email protected]39afe642010-04-29 14:55:182043
[email protected]2345cc52009-06-04 09:18:472044 that->UpdateServerCert();
[email protected]757f2e2b2010-10-27 23:28:352045 that->UpdateConnectionStatus();
[email protected]2345cc52009-06-04 09:18:472046}
[email protected]bacff652009-03-31 17:50:332047
[email protected]7a8de3072010-10-01 16:25:542048int SSLClientSocketNSS::DoSnapStartLoadInfo() {
2049 EnterFunction("");
[email protected]7ab5bbd12010-10-19 13:33:212050 int rv = ssl_host_info_->WaitForDataReady(&handshake_io_callback_);
[email protected]09125792010-11-03 23:23:222051 GotoState(STATE_HANDSHAKE);
[email protected]7a8de3072010-10-01 16:25:542052
2053 if (rv == OK) {
[email protected]09125792010-11-03 23:23:222054 if (ssl_host_info_->WaitForCertVerification(NULL) == OK) {
2055 if (LoadSnapStartInfo()) {
2056 pseudo_connected_ = true;
2057 GotoState(STATE_SNAP_START_WAIT_FOR_WRITE);
2058 if (user_connect_callback_)
2059 DoConnectCallback(OK);
2060 }
2061 } else if (!ssl_host_info_->state().server_hello.empty()) {
2062 // A non-empty ServerHello suggests that we would have tried a Snap Start
2063 // connection.
2064 base::TimeTicks now = base::TimeTicks::Now();
2065 const base::TimeDelta duration =
2066 now - ssl_host_info_->verification_start_time();
2067 UMA_HISTOGRAM_TIMES("Net.SSLSnapStartNeededVerificationInMs", duration);
2068 VLOG(1) << "Cannot snap start because verification isn't ready. "
2069 << "Wanted verification after "
2070 << duration.InMilliseconds() << "ms";
[email protected]7a8de3072010-10-01 16:25:542071 }
2072 } else {
2073 DCHECK_EQ(ERR_IO_PENDING, rv);
2074 GotoState(STATE_SNAP_START_LOAD_INFO);
2075 }
2076
2077 LeaveFunction("");
2078 return rv;
2079}
2080
2081int SSLClientSocketNSS::DoSnapStartWaitForWrite() {
2082 EnterFunction("");
2083 // In this state, we're waiting for the first Write call so that we can merge
2084 // it into the Snap Start handshake.
2085 if (!user_write_buf_) {
2086 // We'll lie and say that we're connected in order that someone will call
2087 // Write.
2088 GotoState(STATE_SNAP_START_WAIT_FOR_WRITE);
2089 DCHECK(!user_connect_callback_);
2090 LeaveFunction("");
2091 return ERR_IO_PENDING;
2092 }
2093
2094 // This is the largest Snap Start application data payload that we'll try to
2095 // use. A TCP client can only send three frames of data without an ACK and,
2096 // at 2048 bytes, this leaves some space for the rest of the ClientHello
2097 // (including possible session ticket).
2098 static const int kMaxSnapStartPayloadSize = 2048;
2099
2100 if (user_write_buf_len_ > kMaxSnapStartPayloadSize) {
2101 user_write_buf_len_ = kMaxSnapStartPayloadSize;
2102 // When we complete the handshake and call user_write_callback_ we'll say
2103 // that we only wrote |kMaxSnapStartPayloadSize| bytes. That way the rest
2104 // of the payload will be presented to |Write| again and transmitted as
2105 // normal application data.
2106 }
2107
2108 SECStatus rv = SSL_SetSnapStartApplicationData(
2109 nss_fd_, reinterpret_cast<const unsigned char*>(user_write_buf_->data()),
2110 user_write_buf_len_);
2111 DCHECK_EQ(SECSuccess, rv);
[email protected]7a8de3072010-10-01 16:25:542112
2113 GotoState(STATE_HANDSHAKE);
2114 LeaveFunction("");
2115 return OK;
2116}
2117
[email protected]a3ff5e92009-10-13 04:48:062118int SSLClientSocketNSS::DoHandshake() {
[email protected]2345cc52009-06-04 09:18:472119 EnterFunction("");
2120 int net_error = net::OK;
[email protected]d84b3722009-10-15 21:23:372121 SECStatus rv = SSL_ForceHandshake(nss_fd_);
[email protected]2345cc52009-06-04 09:18:472122
[email protected]d84b3722009-10-15 21:23:372123 if (client_auth_cert_needed_) {
2124 net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
[email protected]7cbc6df12010-10-04 16:25:392125 net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
[email protected]00cd9c42010-11-02 20:15:572126 make_scoped_refptr(new SSLErrorParams(net_error, 0)));
[email protected]d84b3722009-10-15 21:23:372127 // If the handshake already succeeded (because the server requests but
2128 // doesn't require a client cert), we need to invalidate the SSL session
2129 // so that we won't try to resume the non-client-authenticated session in
2130 // the next handshake. This will cause the server to ask for a client
2131 // cert again.
2132 if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess) {
2133 LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError();
2134 }
2135 } else if (rv == SECSuccess) {
[email protected]39afe642010-04-29 14:55:182136 if (handshake_callback_called_) {
[email protected]563cbcc62010-10-11 23:07:522137 if (eset_mitm_detected_) {
2138 net_error = ERR_ESET_ANTI_VIRUS_SSL_INTERCEPTION;
[email protected]7a8de3072010-10-01 16:25:542139 } else {
[email protected]3b1d3db2010-10-28 16:39:402140 // We need to see if the predicted certificate chain (in
2141 // |ssl_host_info_->state().certs) matches the actual certificate chain
2142 // before we call SaveSnapStartInfo, as that will update
2143 // |ssl_host_info_|.
2144 if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty()) {
2145 PeerCertificateChain certs(nss_fd_);
2146 const SSLHostInfo::State& state = ssl_host_info_->state();
2147 predicted_cert_chain_correct_ = certs.size() == state.certs.size();
2148 if (predicted_cert_chain_correct_) {
2149 for (unsigned i = 0; i < certs.size(); i++) {
2150 if (certs[i]->derCert.len != state.certs[i].size() ||
2151 memcmp(certs[i]->derCert.data, state.certs[i].data(),
2152 certs[i]->derCert.len) != 0) {
2153 predicted_cert_chain_correct_ = false;
2154 break;
2155 }
2156 }
2157 }
2158 }
2159
[email protected]563cbcc62010-10-11 23:07:522160 SaveSnapStartInfo();
[email protected]b30a3f52010-10-16 01:05:462161 // SSL handshake is completed. It's possible that we mispredicted the
2162 // NPN agreed protocol. In this case, we've just sent a request in the
2163 // wrong protocol! The higher levels of this network stack aren't
2164 // prepared for switching the protocol like that so we make up an error
2165 // and rely on the fact that the request will be retried.
[email protected]563cbcc62010-10-11 23:07:522166 if (IsNPNProtocolMispredicted()) {
[email protected]4f4de7e62010-11-12 19:55:272167 LOG(WARNING) << "Mispredicted NPN protocol for "
2168 << host_and_port_.ToString();
[email protected]563cbcc62010-10-11 23:07:522169 net_error = ERR_SSL_SNAP_START_NPN_MISPREDICTION;
2170 } else {
2171 // Let's verify the certificate.
2172 GotoState(STATE_VERIFY_DNSSEC);
2173 }
[email protected]7a8de3072010-10-01 16:25:542174 }
[email protected]39afe642010-04-29 14:55:182175 // Done!
2176 } else {
[email protected]e3ad1a8f12010-10-06 18:21:172177 // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=562434 -
[email protected]39afe642010-04-29 14:55:182178 // SSL_ForceHandshake returned SECSuccess prematurely.
2179 rv = SECFailure;
2180 net_error = ERR_SSL_PROTOCOL_ERROR;
[email protected]7cbc6df12010-10-04 16:25:392181 net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
[email protected]00cd9c42010-11-02 20:15:572182 make_scoped_refptr(new SSLErrorParams(net_error, 0)));
[email protected]39afe642010-04-29 14:55:182183 }
[email protected]2345cc52009-06-04 09:18:472184 } else {
2185 PRErrorCode prerr = PR_GetError();
[email protected]2e9a5b6982010-01-15 22:29:032186 net_error = MapHandshakeError(prerr);
[email protected]2345cc52009-06-04 09:18:472187
2188 // If not done, stay in this state
2189 if (net_error == ERR_IO_PENDING) {
[email protected]a3ff5e92009-10-13 04:48:062190 GotoState(STATE_HANDSHAKE);
[email protected]2345cc52009-06-04 09:18:472191 } else {
2192 LOG(ERROR) << "handshake failed; NSS error code " << prerr
2193 << ", net_error " << net_error;
[email protected]00cd9c42010-11-02 20:15:572194 net_log_.AddEvent(
2195 NetLog::TYPE_SSL_HANDSHAKE_ERROR,
2196 make_scoped_refptr(new SSLErrorParams(net_error, prerr)));
[email protected]2345cc52009-06-04 09:18:472197 }
2198 }
2199
2200 LeaveFunction("");
2201 return net_error;
2202}
2203
[email protected]899c3e92010-08-28 15:53:502204// DNSValidationResult enumerates the possible outcomes from processing a
2205// set of DNS records.
2206enum DNSValidationResult {
[email protected]4e91b5c2010-09-22 01:04:382207 DNSVR_SUCCESS, // the cert is immediately acceptable.
2208 DNSVR_FAILURE, // the cert is unconditionally rejected.
2209 DNSVR_CONTINUE, // perform CA validation as usual.
[email protected]899c3e92010-08-28 15:53:502210};
2211
2212// VerifyTXTRecords processes the RRDATA for a number of DNS TXT records and
2213// checks them against the given certificate.
2214// dnssec: if true then the TXT records are DNSSEC validated. In this case,
2215// DNSVR_SUCCESS may be returned.
2216// server_cert_nss: the certificate to validate
2217// rrdatas: the TXT records for the current domain.
2218static DNSValidationResult VerifyTXTRecords(
2219 bool dnssec,
2220 CERTCertificate* server_cert_nss,
2221 const std::vector<base::StringPiece>& rrdatas) {
2222 bool found_well_formed_record = false;
2223 bool matched_record = false;
2224
2225 for (std::vector<base::StringPiece>::const_iterator
2226 i = rrdatas.begin(); i != rrdatas.end(); ++i) {
2227 std::map<std::string, std::string> m(
2228 DNSSECChainVerifier::ParseTLSTXTRecord(*i));
2229 if (m.empty())
2230 continue;
2231
2232 std::map<std::string, std::string>::const_iterator j;
2233 j = m.find("v");
2234 if (j == m.end() || j->second != "tls1")
2235 continue;
2236
2237 j = m.find("ha");
2238
2239 HASH_HashType hash_algorithm;
2240 unsigned hash_length;
2241 if (j == m.end() || j->second == "sha1") {
2242 hash_algorithm = HASH_AlgSHA1;
2243 hash_length = SHA1_LENGTH;
2244 } else if (j->second == "sha256") {
2245 hash_algorithm = HASH_AlgSHA256;
2246 hash_length = SHA256_LENGTH;
2247 } else {
2248 continue;
2249 }
2250
2251 j = m.find("h");
2252 if (j == m.end())
2253 continue;
2254
2255 std::vector<uint8> given_hash;
2256 if (!base::HexStringToBytes(j->second, &given_hash))
2257 continue;
2258
2259 if (given_hash.size() != hash_length)
2260 continue;
2261
2262 uint8 calculated_hash[SHA256_LENGTH]; // SHA256 is the largest.
2263 SECStatus rv;
2264
2265 j = m.find("hr");
[email protected]b40f05a2010-09-09 20:13:232266 if (j == m.end() || j->second == "pubkey") {
[email protected]899c3e92010-08-28 15:53:502267 rv = HASH_HashBuf(hash_algorithm, calculated_hash,
2268 server_cert_nss->derPublicKey.data,
2269 server_cert_nss->derPublicKey.len);
[email protected]b40f05a2010-09-09 20:13:232270 } else if (j->second == "cert") {
2271 rv = HASH_HashBuf(hash_algorithm, calculated_hash,
2272 server_cert_nss->derCert.data,
2273 server_cert_nss->derCert.len);
[email protected]899c3e92010-08-28 15:53:502274 } else {
2275 continue;
2276 }
2277
2278 if (rv != SECSuccess)
2279 NOTREACHED();
2280
2281 found_well_formed_record = true;
2282
2283 if (memcmp(calculated_hash, &given_hash[0], hash_length) == 0) {
2284 matched_record = true;
2285 if (dnssec)
2286 return DNSVR_SUCCESS;
2287 }
2288 }
2289
2290 if (found_well_formed_record && !matched_record)
2291 return DNSVR_FAILURE;
2292
2293 return DNSVR_CONTINUE;
2294}
2295
2296
[email protected]b24713592010-08-11 19:50:022297// CheckDNSSECChain tries to validate a DNSSEC chain embedded in
2298// |server_cert_nss_|. It returns true iff a chain is found that proves the
[email protected]899c3e92010-08-28 15:53:502299// value of a TXT record that contains a valid public key fingerprint.
2300static DNSValidationResult CheckDNSSECChain(
2301 const std::string& hostname,
2302 CERTCertificate* server_cert_nss) {
2303 if (!server_cert_nss)
2304 return DNSVR_CONTINUE;
[email protected]b24713592010-08-11 19:50:022305
[email protected]b24713592010-08-11 19:50:022306 // CERT_FindCertExtensionByOID isn't exported so we have to install an OID,
2307 // get a tag for it and find the extension by using that tag.
2308 static SECOidTag dnssec_chain_tag;
2309 static bool dnssec_chain_tag_valid;
2310 if (!dnssec_chain_tag_valid) {
2311 // It's harmless if multiple threads enter this block concurrently.
2312 static const uint8 kDNSSECChainOID[] =
[email protected]b736e502010-10-14 18:23:542313 // 1.3.6.1.4.1.11129.2.1.4
2314 // (iso.org.dod.internet.private.enterprises.google.googleSecurity.
2315 // certificateExtensions.dnssecEmbeddedChain)
2316 {0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x04};
[email protected]b24713592010-08-11 19:50:022317 SECOidData oid_data;
2318 memset(&oid_data, 0, sizeof(oid_data));
2319 oid_data.oid.data = const_cast<uint8*>(kDNSSECChainOID);
2320 oid_data.oid.len = sizeof(kDNSSECChainOID);
2321 oid_data.desc = "DNSSEC chain";
2322 oid_data.supportedExtension = SUPPORTED_CERT_EXTENSION;
2323 dnssec_chain_tag = SECOID_AddEntry(&oid_data);
2324 DCHECK_NE(SEC_OID_UNKNOWN, dnssec_chain_tag);
2325 dnssec_chain_tag_valid = true;
2326 }
2327
2328 SECItem dnssec_embedded_chain;
[email protected]899c3e92010-08-28 15:53:502329 SECStatus rv = CERT_FindCertExtension(server_cert_nss,
[email protected]b24713592010-08-11 19:50:022330 dnssec_chain_tag, &dnssec_embedded_chain);
2331 if (rv != SECSuccess)
[email protected]899c3e92010-08-28 15:53:502332 return DNSVR_CONTINUE;
[email protected]b24713592010-08-11 19:50:022333
2334 base::StringPiece chain(
2335 reinterpret_cast<char*>(dnssec_embedded_chain.data),
2336 dnssec_embedded_chain.len);
2337 std::string dns_hostname;
[email protected]899c3e92010-08-28 15:53:502338 if (!DNSDomainFromDot(hostname, &dns_hostname))
2339 return DNSVR_CONTINUE;
[email protected]b24713592010-08-11 19:50:022340 DNSSECChainVerifier verifier(dns_hostname, chain);
2341 DNSSECChainVerifier::Error err = verifier.Verify();
2342 if (err != DNSSECChainVerifier::OK) {
2343 LOG(ERROR) << "DNSSEC chain verification failed: " << err;
[email protected]899c3e92010-08-28 15:53:502344 return DNSVR_CONTINUE;
[email protected]b24713592010-08-11 19:50:022345 }
2346
[email protected]899c3e92010-08-28 15:53:502347 if (verifier.rrtype() != kDNS_TXT)
2348 return DNSVR_CONTINUE;
[email protected]b24713592010-08-11 19:50:022349
[email protected]899c3e92010-08-28 15:53:502350 DNSValidationResult r = VerifyTXTRecords(
2351 true /* DNSSEC verified */, server_cert_nss, verifier.rrdatas());
2352 SECITEM_FreeItem(&dnssec_embedded_chain, PR_FALSE);
2353 return r;
2354}
[email protected]b24713592010-08-11 19:50:022355
[email protected]899c3e92010-08-28 15:53:502356int SSLClientSocketNSS::DoVerifyDNSSEC(int result) {
[email protected]345c613b2010-11-22 19:33:182357 if (ssl_config_.dns_cert_provenance_checking_enabled &&
2358 dns_cert_checker_) {
2359 PeerCertificateChain certs(nss_fd_);
2360 dns_cert_checker_->DoAsyncVerification(
2361 host_and_port_.host(), certs.AsStringPieceVector());
2362 }
2363
[email protected]899c3e92010-08-28 15:53:502364 if (ssl_config_.dnssec_enabled) {
[email protected]4f4de7e62010-11-12 19:55:272365 DNSValidationResult r = CheckDNSSECChain(host_and_port_.host(),
2366 server_cert_nss_);
[email protected]899c3e92010-08-28 15:53:502367 if (r == DNSVR_SUCCESS) {
[email protected]3b1d3db2010-10-28 16:39:402368 local_server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC;
2369 server_cert_verify_result_ = &local_server_cert_verify_result_;
[email protected]899c3e92010-08-28 15:53:502370 GotoState(STATE_VERIFY_CERT_COMPLETE);
2371 return OK;
[email protected]b24713592010-08-11 19:50:022372 }
2373 }
2374
[email protected]899c3e92010-08-28 15:53:502375 if (dnssec_provider_ == NULL) {
2376 GotoState(STATE_VERIFY_CERT);
2377 return OK;
2378 }
2379
2380 GotoState(STATE_VERIFY_DNSSEC_COMPLETE);
2381 RRResponse* response;
2382 dnssec_wait_start_time_ = base::Time::Now();
2383 return dnssec_provider_->GetDNSSECRecords(&response, &handshake_io_callback_);
2384}
2385
2386int SSLClientSocketNSS::DoVerifyDNSSECComplete(int result) {
2387 RRResponse* response;
2388 int err = dnssec_provider_->GetDNSSECRecords(&response, NULL);
2389 DCHECK_EQ(err, OK);
2390
2391 const base::TimeDelta elapsed = base::Time::Now() - dnssec_wait_start_time_;
2392 HISTOGRAM_TIMES("Net.DNSSECWaitTime", elapsed);
2393
2394 GotoState(STATE_VERIFY_CERT);
2395 if (!response || response->rrdatas.empty())
2396 return OK;
2397
2398 std::vector<base::StringPiece> records;
2399 records.resize(response->rrdatas.size());
2400 for (unsigned i = 0; i < response->rrdatas.size(); i++)
2401 records[i] = base::StringPiece(response->rrdatas[i]);
2402 DNSValidationResult r =
2403 VerifyTXTRecords(response->dnssec, server_cert_nss_, records);
2404
2405 if (!ssl_config_.dnssec_enabled) {
2406 // If DNSSEC is not enabled we don't take any action based on the result,
2407 // except to record the latency, above.
[email protected]899c3e92010-08-28 15:53:502408 return OK;
2409 }
2410
2411 switch (r) {
2412 case DNSVR_FAILURE:
2413 GotoState(STATE_VERIFY_CERT_COMPLETE);
[email protected]3b1d3db2010-10-28 16:39:402414 local_server_cert_verify_result_.cert_status |= CERT_STATUS_NOT_IN_DNS;
2415 server_cert_verify_result_ = &local_server_cert_verify_result_;
[email protected]899c3e92010-08-28 15:53:502416 return ERR_CERT_NOT_IN_DNS;
2417 case DNSVR_CONTINUE:
2418 GotoState(STATE_VERIFY_CERT);
2419 break;
2420 case DNSVR_SUCCESS:
[email protected]3b1d3db2010-10-28 16:39:402421 local_server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC;
2422 server_cert_verify_result_ = &local_server_cert_verify_result_;
[email protected]899c3e92010-08-28 15:53:502423 GotoState(STATE_VERIFY_CERT_COMPLETE);
2424 break;
2425 default:
2426 NOTREACHED();
2427 GotoState(STATE_VERIFY_CERT);
2428 }
2429
2430 return OK;
[email protected]b24713592010-08-11 19:50:022431}
2432
[email protected]2345cc52009-06-04 09:18:472433int SSLClientSocketNSS::DoVerifyCert(int result) {
2434 DCHECK(server_cert_);
[email protected]a89eda42010-02-18 01:45:392435
[email protected]3b1d3db2010-10-28 16:39:402436 GotoState(STATE_VERIFY_CERT_COMPLETE);
2437
2438 if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty() &&
2439 predicted_cert_chain_correct_) {
2440 // If the SSLHostInfo had a prediction for the certificate chain of this
2441 // server then it will have optimistically started a verification of that
2442 // chain. So, if the prediction was correct, we should wait for that
2443 // verification to finish rather than start our own.
[email protected]09125792010-11-03 23:23:222444 net_log_.AddEvent(NetLog::TYPE_SSL_VERIFICATION_MERGED, NULL);
2445 UMA_HISTOGRAM_ENUMERATION("Net.SSLVerificationMerged", 1 /* true */, 2);
2446 base::TimeTicks now = base::TimeTicks::Now();
2447 UMA_HISTOGRAM_TIMES("Net.SSLVerificationMergedMsSaved",
2448 now - ssl_host_info_->verification_start_time());
[email protected]3b1d3db2010-10-28 16:39:402449 server_cert_verify_result_ = &ssl_host_info_->cert_verify_result();
2450 return ssl_host_info_->WaitForCertVerification(&handshake_io_callback_);
[email protected]09125792010-11-03 23:23:222451 } else {
2452 UMA_HISTOGRAM_ENUMERATION("Net.SSLVerificationMerged", 0 /* false */, 2);
[email protected]3b1d3db2010-10-28 16:39:402453 }
2454
2455 int flags = 0;
[email protected]dd681aa2010-07-26 20:35:182456 if (ssl_config_.rev_checking_enabled)
[email protected]f6555ad2009-06-23 06:35:052457 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
2458 if (ssl_config_.verify_ev_cert)
2459 flags |= X509Certificate::VERIFY_EV_CERT;
[email protected]92d9cad2009-06-25 23:40:242460 verifier_.reset(new CertVerifier);
[email protected]3b1d3db2010-10-28 16:39:402461 server_cert_verify_result_ = &local_server_cert_verify_result_;
[email protected]4f4de7e62010-11-12 19:55:272462 return verifier_->Verify(server_cert_, host_and_port_.host(), flags,
[email protected]3b1d3db2010-10-28 16:39:402463 &local_server_cert_verify_result_,
[email protected]a3ff5e92009-10-13 04:48:062464 &handshake_io_callback_);
[email protected]2345cc52009-06-04 09:18:472465}
2466
2467// Derived from AuthCertificateCallback() in
2468// mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp.
2469int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
[email protected]92d9cad2009-06-25 23:40:242470 verifier_.reset();
2471
[email protected]4feca4b2010-10-28 16:50:322472 // We used to remember the intermediate CA certs in the NSS database
2473 // persistently. However, NSS opens a connection to the SQLite database
2474 // during NSS initialization and doesn't close the connection until NSS
2475 // shuts down. If the file system where the database resides is gone,
2476 // the database connection goes bad. What's worse, the connection won't
2477 // recover when the file system comes back. Until this NSS or SQLite bug
2478 // is fixed, we need to avoid using the NSS database for non-essential
2479 // purposes. See https://bugzilla.mozilla.org/show_bug.cgi?id=508081 and
2480 // http://crbug.com/15630 for more info.
[email protected]bf0136d2009-05-29 05:55:042481
[email protected]2345cc52009-06-04 09:18:472482 // If we have been explicitly told to accept this certificate, override the
2483 // result of verifier_.Verify.
2484 // Eventually, we should cache the cert verification results so that we don't
2485 // need to call verifier_.Verify repeatedly. But for now we need to do this.
[email protected]127017872009-08-13 17:54:422486 // Alternatively, we could use the cert's status that we stored along with
2487 // the cert in the allowed_bad_certs vector.
[email protected]2345cc52009-06-04 09:18:472488 if (IsCertificateError(result) &&
[email protected]127017872009-08-13 17:54:422489 ssl_config_.IsAllowedBadCert(server_cert_)) {
[email protected]b30a3f52010-10-16 01:05:462490 VLOG(1) << "accepting bad SSL certificate, as user told us to";
[email protected]2345cc52009-06-04 09:18:472491 result = OK;
[email protected]b43c97c2008-10-22 19:50:582492 }
[email protected]ea224582008-12-07 20:25:462493
[email protected]757f2e2b2010-10-27 23:28:352494 if (result == OK)
2495 LogConnectionTypeMetrics();
2496
[email protected]2345cc52009-06-04 09:18:472497 completed_handshake_ = true;
[email protected]7a8de3072010-10-01 16:25:542498
[email protected]ff730e52010-11-03 19:46:242499 // If we merged a Write call into the handshake we need to make the
[email protected]7a8de3072010-10-01 16:25:542500 // callback now.
2501 if (user_write_callback_) {
2502 corked_ = false;
[email protected]ff730e52010-11-03 19:46:242503 if (result != OK) {
2504 DoWriteCallback(result);
2505 } else {
2506 SSLSnapStartResult snap_start_type;
2507 SECStatus rv = SSL_GetSnapStartResult(nss_fd_, &snap_start_type);
2508 DCHECK_EQ(rv, SECSuccess);
2509 DCHECK_NE(snap_start_type, SSL_SNAP_START_NONE);
2510 if (snap_start_type == SSL_SNAP_START_RECOVERY ||
2511 snap_start_type == SSL_SNAP_START_RESUME_RECOVERY) {
2512 // If we mispredicted the server's handshake then Snap Start will have
2513 // triggered a recovery mode. The misprediction could have been caused
2514 // by the server having a different certificate so the application data
2515 // wasn't resent. Now that we have verified the certificate, we need to
2516 // resend the application data.
2517 int bytes_written = DoPayloadWrite();
2518 if (bytes_written != ERR_IO_PENDING)
2519 DoWriteCallback(bytes_written);
2520 } else {
2521 DoWriteCallback(user_write_buf_len_);
2522 }
2523 }
[email protected]7a8de3072010-10-01 16:25:542524 }
2525
[email protected]09125792010-11-03 23:23:222526 if (user_read_callback_) {
2527 int rv = DoReadLoop(OK);
2528 if (rv != ERR_IO_PENDING)
2529 DoReadCallback(rv);
2530 }
2531
[email protected]a3ff5e92009-10-13 04:48:062532 // Exit DoHandshakeLoop and return the result to the caller to Connect.
2533 DCHECK(next_handshake_state_ == STATE_NONE);
[email protected]2345cc52009-06-04 09:18:472534 return result;
[email protected]b43c97c2008-10-22 19:50:582535}
[email protected]ea224582008-12-07 20:25:462536
[email protected]b43c97c2008-10-22 19:50:582537int SSLClientSocketNSS::DoPayloadRead() {
[email protected]a3ff5e92009-10-13 04:48:062538 EnterFunction(user_read_buf_len_);
2539 DCHECK(user_read_buf_);
[email protected]1d583612010-03-12 17:47:142540 DCHECK_GT(user_read_buf_len_, 0);
[email protected]a3ff5e92009-10-13 04:48:062541 int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_);
[email protected]d84b3722009-10-15 21:23:372542 if (client_auth_cert_needed_) {
2543 // We don't need to invalidate the non-client-authenticated SSL session
2544 // because the server will renegotiate anyway.
2545 LeaveFunction("");
[email protected]7cbc6df12010-10-04 16:25:392546 rv = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
2547 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
[email protected]00cd9c42010-11-02 20:15:572548 make_scoped_refptr(new SSLErrorParams(rv, 0)));
[email protected]7cbc6df12010-10-04 16:25:392549 return rv;
[email protected]d84b3722009-10-15 21:23:372550 }
[email protected]e17b4c12008-11-05 22:04:082551 if (rv >= 0) {
[email protected]a3ff5e92009-10-13 04:48:062552 LogData(user_read_buf_->data(), rv);
[email protected]e17b4c12008-11-05 22:04:082553 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:582554 return rv;
[email protected]e17b4c12008-11-05 22:04:082555 }
[email protected]b43c97c2008-10-22 19:50:582556 PRErrorCode prerr = PR_GetError();
2557 if (prerr == PR_WOULD_BLOCK_ERROR) {
[email protected]e17b4c12008-11-05 22:04:082558 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:582559 return ERR_IO_PENDING;
2560 }
[email protected]e17b4c12008-11-05 22:04:082561 LeaveFunction("");
[email protected]7cbc6df12010-10-04 16:25:392562 rv = MapNSPRError(prerr);
[email protected]00cd9c42010-11-02 20:15:572563 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
2564 make_scoped_refptr(new SSLErrorParams(rv, prerr)));
[email protected]7cbc6df12010-10-04 16:25:392565 return rv;
[email protected]b43c97c2008-10-22 19:50:582566}
2567
2568int SSLClientSocketNSS::DoPayloadWrite() {
[email protected]a3ff5e92009-10-13 04:48:062569 EnterFunction(user_write_buf_len_);
2570 DCHECK(user_write_buf_);
2571 int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
[email protected]e17b4c12008-11-05 22:04:082572 if (rv >= 0) {
[email protected]a3ff5e92009-10-13 04:48:062573 LogData(user_write_buf_->data(), rv);
[email protected]e17b4c12008-11-05 22:04:082574 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:582575 return rv;
[email protected]e17b4c12008-11-05 22:04:082576 }
[email protected]b43c97c2008-10-22 19:50:582577 PRErrorCode prerr = PR_GetError();
2578 if (prerr == PR_WOULD_BLOCK_ERROR) {
[email protected]4d3040f42010-04-14 02:40:202579 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:582580 return ERR_IO_PENDING;
2581 }
[email protected]e17b4c12008-11-05 22:04:082582 LeaveFunction("");
[email protected]7cbc6df12010-10-04 16:25:392583 rv = MapNSPRError(prerr);
2584 net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
[email protected]00cd9c42010-11-02 20:15:572585 make_scoped_refptr(new SSLErrorParams(rv, prerr)));
[email protected]7cbc6df12010-10-04 16:25:392586 return rv;
[email protected]b43c97c2008-10-22 19:50:582587}
2588
[email protected]757f2e2b2010-10-27 23:28:352589void SSLClientSocketNSS::LogConnectionTypeMetrics() const {
2590 UpdateConnectionTypeHistograms(CONNECTION_SSL);
[email protected]3b1d3db2010-10-28 16:39:402591 if (server_cert_verify_result_->has_md5)
[email protected]757f2e2b2010-10-27 23:28:352592 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5);
[email protected]3b1d3db2010-10-28 16:39:402593 if (server_cert_verify_result_->has_md2)
[email protected]757f2e2b2010-10-27 23:28:352594 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2);
[email protected]3b1d3db2010-10-28 16:39:402595 if (server_cert_verify_result_->has_md4)
[email protected]757f2e2b2010-10-27 23:28:352596 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD4);
[email protected]3b1d3db2010-10-28 16:39:402597 if (server_cert_verify_result_->has_md5_ca)
[email protected]757f2e2b2010-10-27 23:28:352598 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5_CA);
[email protected]3b1d3db2010-10-28 16:39:402599 if (server_cert_verify_result_->has_md2_ca)
[email protected]757f2e2b2010-10-27 23:28:352600 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA);
2601 int ssl_version = SSLConnectionStatusToVersion(ssl_connection_status_);
2602 switch (ssl_version) {
2603 case SSL_CONNECTION_VERSION_SSL2:
2604 UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL2);
2605 break;
2606 case SSL_CONNECTION_VERSION_SSL3:
2607 UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL3);
2608 break;
2609 case SSL_CONNECTION_VERSION_TLS1:
2610 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1);
2611 break;
2612 case SSL_CONNECTION_VERSION_TLS1_1:
2613 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_1);
2614 break;
2615 case SSL_CONNECTION_VERSION_TLS1_2:
2616 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_2);
2617 break;
2618 };
2619}
2620
[email protected]b43c97c2008-10-22 19:50:582621} // namespace net