blob: 0a28439b3971d77d1933f6230372d3b929226667 [file] [log] [blame]
[email protected]35a43f92011-02-09 04:39:481// Copyright (c) 2011 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]71d6ccaa2011-01-06 17:43:2155#include <ocsp.h>
[email protected]d8eb84242010-09-25 02:25:0656#include <pk11pub.h>
[email protected]ea224582008-12-07 20:25:4657#include <secerr.h>
[email protected]b24713592010-08-11 19:50:0258#include <sechash.h>
[email protected]b43c97c2008-10-22 19:50:5859#include <ssl.h>
[email protected]ea224582008-12-07 20:25:4660#include <sslerr.h>
[email protected]757f2e2b2010-10-27 23:28:3561#include <sslproto.h>
[email protected]b43c97c2008-10-22 19:50:5862
[email protected]35a43f92011-02-09 04:39:4863#include <algorithm>
[email protected]7a8de3072010-10-01 16:25:5464#include <limits>
[email protected]35a43f92011-02-09 04:39:4865#include <map>
[email protected]7a8de3072010-10-01 16:25:5466
[email protected]bacff652009-03-31 17:50:3367#include "base/compiler_specific.h"
[email protected]b43c97c2008-10-22 19:50:5868#include "base/logging.h"
[email protected]3b63f8f42011-03-28 01:54:1569#include "base/memory/singleton.h"
[email protected]b92ead12011-01-19 15:29:0970#include "base/metrics/histogram.h"
[email protected]899c3e92010-08-28 15:53:5071#include "base/string_number_conversions.h"
[email protected]b43c97c2008-10-22 19:50:5872#include "base/string_util.h"
[email protected]d8eb84242010-09-25 02:25:0673#include "base/stringprintf.h"
[email protected]34b99632011-01-01 01:01:0674#include "base/threading/thread_restrictions.h"
[email protected]7cbc6df12010-10-04 16:25:3975#include "base/values.h"
[email protected]ac9eec62010-02-20 18:50:3876#include "net/base/address_list.h"
[email protected]43025b7a2010-09-16 19:24:4577#include "net/base/cert_status_flags.h"
[email protected]92d9cad2009-06-25 23:40:2478#include "net/base/cert_verifier.h"
[email protected]757f2e2b2010-10-27 23:28:3579#include "net/base/connection_type_histograms.h"
[email protected]d8eb84242010-09-25 02:25:0680#include "net/base/dns_util.h"
[email protected]899c3e92010-08-28 15:53:5081#include "net/base/dnsrr_resolver.h"
[email protected]b24713592010-08-11 19:50:0282#include "net/base/dnssec_chain_verifier.h"
[email protected]597cf6e2009-05-29 09:43:2683#include "net/base/io_buffer.h"
[email protected]b43c97c2008-10-22 19:50:5884#include "net/base/net_errors.h"
[email protected]899c3e92010-08-28 15:53:5085#include "net/base/net_log.h"
[email protected]d84b3722009-10-15 21:23:3786#include "net/base/ssl_cert_request_info.h"
[email protected]fc7de492010-07-12 14:49:0487#include "net/base/ssl_connection_status_flags.h"
[email protected]b43c97c2008-10-22 19:50:5888#include "net/base/ssl_info.h"
[email protected]ac9eec62010-02-20 18:50:3889#include "net/base/sys_addrinfo.h"
[email protected]2a0c0a52009-07-31 07:51:3290#include "net/ocsp/nss_ocsp.h"
[email protected]e60e47a2010-07-14 03:37:1891#include "net/socket/client_socket_handle.h"
[email protected]345c613b2010-11-22 19:33:1892#include "net/socket/dns_cert_provenance_checker.h"
[email protected]f61c3972010-12-23 09:54:1593#include "net/socket/nss_ssl_util.h"
[email protected]47f7d742010-11-11 04:12:5394#include "net/socket/ssl_error_params.h"
[email protected]d0672be2010-10-20 16:30:1995#include "net/socket/ssl_host_info.h"
[email protected]b43c97c2008-10-22 19:50:5896
[email protected]11f40342010-11-22 13:35:4997#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>
[email protected]35a43f92011-02-09 04:39:48104#elif defined(USE_NSS)
105#include <dlfcn.h>
[email protected]11f40342010-11-22 13:35:49106#endif
107
[email protected]b43c97c2008-10-22 19:50:58108static const int kRecvBufferSize = 4096;
109
[email protected]fa788512010-10-08 14:48:06110// kCorkTimeoutMs is the number of milliseconds for which we'll wait for a
111// Write to an SSL socket which we're False Starting. Since corking stops the
112// Finished message from being sent, the server sees an incomplete handshake
113// and some will time out such sockets quite aggressively.
114static const int kCorkTimeoutMs = 200;
115
[email protected]35a43f92011-02-09 04:39:48116#if defined(OS_WIN)
117// CERT_OCSP_RESPONSE_PROP_ID is only implemented on Vista+, but it can be
118// set on Windows XP without error. There is some overhead from the server
119// sending the OCSP response if it supports the extension, for the subset of
120// XP clients who will request it but be unable to use it, but this is an
121// acceptable trade-off for simplicity of implementation.
122static bool IsOCSPStaplingSupported() {
123 return true;
124}
125#elif defined(USE_NSS)
[email protected]b92ead12011-01-19 15:29:09126typedef SECStatus
127(*CacheOCSPResponseFromSideChannelFunction)(
128 CERTCertDBHandle *handle, CERTCertificate *cert, PRTime time,
129 SECItem *encodedResponse, void *pwArg);
130
[email protected]71d6ccaa2011-01-06 17:43:21131// On Linux, we dynamically link against the system version of libnss3.so. In
132// order to continue working on systems without up-to-date versions of NSS we
[email protected]b92ead12011-01-19 15:29:09133// lookup CERT_CacheOCSPResponseFromSideChannel with dlsym.
[email protected]71d6ccaa2011-01-06 17:43:21134
[email protected]b92ead12011-01-19 15:29:09135// RuntimeLibNSSFunctionPointers is a singleton which caches the results of any
136// runtime symbol resolution that we need.
137class RuntimeLibNSSFunctionPointers {
138 public:
139 CacheOCSPResponseFromSideChannelFunction
140 GetCacheOCSPResponseFromSideChannelFunction() {
141 return cache_ocsp_response_from_side_channel_;
142 }
143
144 static RuntimeLibNSSFunctionPointers* GetInstance() {
145 return Singleton<RuntimeLibNSSFunctionPointers>::get();
146 }
147
148 private:
149 friend struct DefaultSingletonTraits<RuntimeLibNSSFunctionPointers>;
150
151 RuntimeLibNSSFunctionPointers() {
152 cache_ocsp_response_from_side_channel_ =
153 (CacheOCSPResponseFromSideChannelFunction)
154 dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel");
155 }
156
157 CacheOCSPResponseFromSideChannelFunction
158 cache_ocsp_response_from_side_channel_;
159};
160
161static CacheOCSPResponseFromSideChannelFunction
162GetCacheOCSPResponseFromSideChannelFunction() {
163 return RuntimeLibNSSFunctionPointers::GetInstance()
164 ->GetCacheOCSPResponseFromSideChannelFunction();
[email protected]71d6ccaa2011-01-06 17:43:21165}
[email protected]35a43f92011-02-09 04:39:48166
167static bool IsOCSPStaplingSupported() {
168 return GetCacheOCSPResponseFromSideChannelFunction() != NULL;
169}
[email protected]71d6ccaa2011-01-06 17:43:21170#else
[email protected]35a43f92011-02-09 04:39:48171// TODO(agl): Figure out if we can plumb the OCSP response into Mac's system
172// certificate validation functions.
173static bool IsOCSPStaplingSupported() {
174 return false;
[email protected]71d6ccaa2011-01-06 17:43:21175}
176#endif
177
[email protected]b43c97c2008-10-22 19:50:58178namespace net {
179
[email protected]e17b4c12008-11-05 22:04:08180// State machines are easier to debug if you log state transitions.
181// Enable these if you want to see what's going on.
182#if 1
183#define EnterFunction(x)
184#define LeaveFunction(x)
[email protected]a3ff5e92009-10-13 04:48:06185#define GotoState(s) next_handshake_state_ = s
[email protected]e17b4c12008-11-05 22:04:08186#else
[email protected]b30a3f52010-10-16 01:05:46187#define EnterFunction(x)\
188 VLOG(1) << (void *)this << " " << __FUNCTION__ << " enter " << x\
189 << "; next_handshake_state " << next_handshake_state_
190#define LeaveFunction(x)\
191 VLOG(1) << (void *)this << " " << __FUNCTION__ << " leave " << x\
192 << "; next_handshake_state " << next_handshake_state_
193#define GotoState(s)\
194 do {\
195 VLOG(1) << (void *)this << " " << __FUNCTION__ << " jump to state " << s;\
196 next_handshake_state_ = s;\
197 } while (0)
[email protected]e17b4c12008-11-05 22:04:08198#endif
199
[email protected]ea224582008-12-07 20:25:46200namespace {
201
[email protected]37a0b112010-05-08 02:23:46202#if defined(OS_WIN)
203
[email protected]01640f62010-08-10 19:42:12204// This callback is intended to be used with CertFindChainInStore. In addition
205// to filtering by extended/enhanced key usage, we do not show expired
206// certificates and require digital signature usage in the key usage
207// extension.
208//
209// This matches our behavior on Mac OS X and that of NSS. It also matches the
210// default behavior of IE8. See http://support.microsoft.com/kb/890326 and
211// 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
212BOOL WINAPI ClientCertFindCallback(PCCERT_CONTEXT cert_context,
213 void* find_arg) {
[email protected]b30a3f52010-10-16 01:05:46214 VLOG(1) << "Calling ClientCertFindCallback from _nss";
[email protected]01640f62010-08-10 19:42:12215 // Verify the certificate's KU is good.
216 BYTE key_usage;
217 if (CertGetIntendedKeyUsage(X509_ASN_ENCODING, cert_context->pCertInfo,
218 &key_usage, 1)) {
219 if (!(key_usage & CERT_DIGITAL_SIGNATURE_KEY_USAGE))
220 return FALSE;
221 } else {
222 DWORD err = GetLastError();
223 // If |err| is non-zero, it's an actual error. Otherwise the extension
224 // just isn't present, and we treat it as if everything was allowed.
225 if (err) {
226 DLOG(ERROR) << "CertGetIntendedKeyUsage failed: " << err;
227 return FALSE;
228 }
229 }
230
231 // Verify the current time is within the certificate's validity period.
232 if (CertVerifyTimeValidity(NULL, cert_context->pCertInfo) != 0)
233 return FALSE;
234
[email protected]187f48b2011-03-03 04:59:23235 // Verify private key metadata is associated with this certificate.
236 DWORD size = 0;
237 if (!CertGetCertificateContextProperty(
238 cert_context, CERT_KEY_PROV_INFO_PROP_ID, NULL, &size)) {
239 return FALSE;
240 }
241
[email protected]01640f62010-08-10 19:42:12242 return TRUE;
243}
244
[email protected]37a0b112010-05-08 02:23:46245#endif
246
[email protected]17570702010-10-28 15:16:09247// PeerCertificateChain is a helper object which extracts the certificate
248// chain, as given by the server, from an NSS socket and performs the needed
249// resource management. The first element of the chain is the leaf certificate
250// and the other elements are in the order given by the server.
251class PeerCertificateChain {
252 public:
[email protected]b92a96e2010-11-02 21:03:05253 explicit PeerCertificateChain(PRFileDesc* nss_fd)
[email protected]17570702010-10-28 15:16:09254 : num_certs_(0),
255 certs_(NULL) {
256 SECStatus rv = SSL_PeerCertificateChain(nss_fd, NULL, &num_certs_);
257 DCHECK_EQ(rv, SECSuccess);
258
259 certs_ = new CERTCertificate*[num_certs_];
260 const unsigned expected_num_certs = num_certs_;
261 rv = SSL_PeerCertificateChain(nss_fd, certs_, &num_certs_);
262 DCHECK_EQ(rv, SECSuccess);
263 DCHECK_EQ(num_certs_, expected_num_certs);
264 }
265
266 ~PeerCertificateChain() {
267 for (unsigned i = 0; i < num_certs_; i++)
268 CERT_DestroyCertificate(certs_[i]);
269 delete[] certs_;
270 }
271
272 unsigned size() const { return num_certs_; }
273
274 CERTCertificate* operator[](unsigned i) {
275 DCHECK_LT(i, num_certs_);
276 return certs_[i];
277 }
278
[email protected]d8fbf582010-11-04 21:51:12279 std::vector<base::StringPiece> AsStringPieceVector() const {
280 std::vector<base::StringPiece> v(size());
281 for (unsigned i = 0; i < size(); i++) {
282 v[i] = base::StringPiece(
283 reinterpret_cast<const char*>(certs_[i]->derCert.data),
284 certs_[i]->derCert.len);
285 }
286
287 return v;
288 }
289
[email protected]17570702010-10-28 15:16:09290 private:
291 unsigned num_certs_;
292 CERTCertificate** certs_;
293};
294
[email protected]d100e44f2011-01-26 22:47:11295void DestroyCertificates(CERTCertificate** certs, unsigned len) {
296 for (unsigned i = 0; i < len; i++)
297 CERT_DestroyCertificate(certs[i]);
298}
299
300// DNSValidationResult enumerates the possible outcomes from processing a
301// set of DNS records.
302enum DNSValidationResult {
303 DNSVR_SUCCESS, // the cert is immediately acceptable.
304 DNSVR_FAILURE, // the cert is unconditionally rejected.
305 DNSVR_CONTINUE, // perform CA validation as usual.
306};
307
[email protected]bad796d2011-06-02 21:06:54308// VerifyCAARecords processes DNSSEC validated RRDATA for a number of DNS CAA
309// records and checks them against the given chain.
310// server_cert_nss: the server's leaf certificate.
311// rrdatas: the CAA records for the current domain.
312// port: the TCP port number that we connected to.
313DNSValidationResult VerifyCAARecords(
[email protected]d100e44f2011-01-26 22:47:11314 CERTCertificate* server_cert_nss,
[email protected]bad796d2011-06-02 21:06:54315 const std::vector<base::StringPiece>& rrdatas,
316 uint16 port) {
317 DnsCAARecord::Policy policy;
318 const DnsCAARecord::ParseResult r = DnsCAARecord::Parse(rrdatas, &policy);
319 if (r == DnsCAARecord::SYNTAX_ERROR || r == DnsCAARecord::UNKNOWN_CRITICAL)
320 return DNSVR_FAILURE;
321 if (r == DnsCAARecord::DISCARD)
322 return DNSVR_CONTINUE;
323 DCHECK(r == DnsCAARecord::SUCCESS);
[email protected]d100e44f2011-01-26 22:47:11324
[email protected]bad796d2011-06-02 21:06:54325 for (std::vector<DnsCAARecord::Policy::Hash>::const_iterator
326 hash = policy.authorized_hashes.begin();
327 hash != policy.authorized_hashes.end();
328 ++hash) {
329 if (hash->target == DnsCAARecord::Policy::SUBJECT_PUBLIC_KEY_INFO &&
330 (hash->port == 0 || hash->port == port)) {
331 CHECK_LE(hash->data.size(), static_cast<unsigned>(SHA512_LENGTH));
332 uint8 calculated_hash[SHA512_LENGTH]; // SHA512 is the largest.
333 SECStatus rv = HASH_HashBuf(
334 static_cast<HASH_HashType>(hash->algorithm),
335 calculated_hash,
336 server_cert_nss->derPublicKey.data,
337 server_cert_nss->derPublicKey.len);
338 DCHECK(rv == SECSuccess);
339 const std::string actual_digest(reinterpret_cast<char*>(calculated_hash),
340 hash->data.size());
[email protected]d100e44f2011-01-26 22:47:11341
[email protected]bad796d2011-06-02 21:06:54342 // Note that the parser ensures that hash->data.size() is correct for the
343 // given algorithm. An attacker cannot give a zero length hash that
344 // always matches.
345 if (actual_digest == hash->data) {
346 // A DNSSEC secure hash over the public key of the leaf-certificate
347 // is sufficient.
[email protected]d100e44f2011-01-26 22:47:11348 return DNSVR_SUCCESS;
[email protected]bad796d2011-06-02 21:06:54349 }
[email protected]d100e44f2011-01-26 22:47:11350 }
351 }
352
[email protected]bad796d2011-06-02 21:06:54353 // If a CAA record was found, but nothing matched, then we reject the
354 // certificate.
355 return DNSVR_FAILURE;
[email protected]d100e44f2011-01-26 22:47:11356}
357
358// CheckDNSSECChain tries to validate a DNSSEC chain embedded in
359// |server_cert_nss_|. It returns true iff a chain is found that proves the
[email protected]bad796d2011-06-02 21:06:54360// value of a CAA record that contains a valid public key fingerprint.
361// |port| contains the TCP port number that we connected to as CAA records can
362// be specific to a given port.
[email protected]d100e44f2011-01-26 22:47:11363DNSValidationResult CheckDNSSECChain(
364 const std::string& hostname,
[email protected]bad796d2011-06-02 21:06:54365 CERTCertificate* server_cert_nss,
366 uint16 port) {
[email protected]d100e44f2011-01-26 22:47:11367 if (!server_cert_nss)
368 return DNSVR_CONTINUE;
369
370 // CERT_FindCertExtensionByOID isn't exported so we have to install an OID,
371 // get a tag for it and find the extension by using that tag.
372 static SECOidTag dnssec_chain_tag;
373 static bool dnssec_chain_tag_valid;
374 if (!dnssec_chain_tag_valid) {
375 // It's harmless if multiple threads enter this block concurrently.
376 static const uint8 kDNSSECChainOID[] =
377 // 1.3.6.1.4.1.11129.2.1.4
378 // (iso.org.dod.internet.private.enterprises.google.googleSecurity.
379 // certificateExtensions.dnssecEmbeddedChain)
380 {0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x04};
381 SECOidData oid_data;
382 memset(&oid_data, 0, sizeof(oid_data));
383 oid_data.oid.data = const_cast<uint8*>(kDNSSECChainOID);
384 oid_data.oid.len = sizeof(kDNSSECChainOID);
385 oid_data.desc = "DNSSEC chain";
386 oid_data.supportedExtension = SUPPORTED_CERT_EXTENSION;
387 dnssec_chain_tag = SECOID_AddEntry(&oid_data);
388 DCHECK_NE(SEC_OID_UNKNOWN, dnssec_chain_tag);
389 dnssec_chain_tag_valid = true;
390 }
391
392 SECItem dnssec_embedded_chain;
393 SECStatus rv = CERT_FindCertExtension(server_cert_nss,
394 dnssec_chain_tag, &dnssec_embedded_chain);
395 if (rv != SECSuccess)
396 return DNSVR_CONTINUE;
397
398 base::StringPiece chain(
399 reinterpret_cast<char*>(dnssec_embedded_chain.data),
400 dnssec_embedded_chain.len);
401 std::string dns_hostname;
402 if (!DNSDomainFromDot(hostname, &dns_hostname))
403 return DNSVR_CONTINUE;
404 DNSSECChainVerifier verifier(dns_hostname, chain);
405 DNSSECChainVerifier::Error err = verifier.Verify();
406 if (err != DNSSECChainVerifier::OK) {
407 LOG(ERROR) << "DNSSEC chain verification failed: " << err;
408 return DNSVR_CONTINUE;
409 }
410
[email protected]bad796d2011-06-02 21:06:54411 if (verifier.rrtype() != kDNS_CAA)
[email protected]d100e44f2011-01-26 22:47:11412 return DNSVR_CONTINUE;
413
[email protected]bad796d2011-06-02 21:06:54414 DNSValidationResult r = VerifyCAARecords(
415 server_cert_nss, verifier.rrdatas(), port);
[email protected]d100e44f2011-01-26 22:47:11416 SECITEM_FreeItem(&dnssec_embedded_chain, PR_FALSE);
[email protected]bad796d2011-06-02 21:06:54417
[email protected]d100e44f2011-01-26 22:47:11418 return r;
419}
420
[email protected]ea224582008-12-07 20:25:46421} // namespace
422
[email protected]e60e47a2010-07-14 03:37:18423SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket,
[email protected]4f4de7e62010-11-12 19:55:27424 const HostPortPair& host_and_port,
[email protected]7ab5bbd12010-10-19 13:33:21425 const SSLConfig& ssl_config,
[email protected]d8fbf582010-11-04 21:51:12426 SSLHostInfo* ssl_host_info,
[email protected]feb79bcd2011-07-21 16:55:17427 const SSLClientSocketContext& context)
[email protected]f505a9b2010-01-28 19:44:02428 : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_(
429 this, &SSLClientSocketNSS::BufferSendComplete)),
430 ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_(
431 this, &SSLClientSocketNSS::BufferRecvComplete)),
[email protected]b43c97c2008-10-22 19:50:58432 transport_send_busy_(false),
433 transport_recv_busy_(false),
[email protected]9ae2ee02010-09-08 16:41:14434 corked_(false),
[email protected]f505a9b2010-01-28 19:44:02435 ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_(
436 this, &SSLClientSocketNSS::OnHandshakeIOComplete)),
[email protected]b43c97c2008-10-22 19:50:58437 transport_(transport_socket),
[email protected]4f4de7e62010-11-12 19:55:27438 host_and_port_(host_and_port),
[email protected]b43c97c2008-10-22 19:50:58439 ssl_config_(ssl_config),
[email protected]a6eb576292009-06-30 16:19:00440 user_connect_callback_(NULL),
[email protected]a3ff5e92009-10-13 04:48:06441 user_read_callback_(NULL),
442 user_write_callback_(NULL),
443 user_read_buf_len_(0),
444 user_write_buf_len_(0),
[email protected]f505a9b2010-01-28 19:44:02445 server_cert_nss_(NULL),
[email protected]3b1d3db2010-10-28 16:39:40446 server_cert_verify_result_(NULL),
[email protected]757f2e2b2010-10-27 23:28:35447 ssl_connection_status_(0),
[email protected]d84b3722009-10-15 21:23:37448 client_auth_cert_needed_(false),
[email protected]feb79bcd2011-07-21 16:55:17449 cert_verifier_(context.cert_verifier),
450 origin_bound_cert_service_(context.origin_bound_cert_service),
[email protected]39afe642010-04-29 14:55:18451 handshake_callback_called_(false),
[email protected]b43c97c2008-10-22 19:50:58452 completed_handshake_(false),
[email protected]563cbcc62010-10-11 23:07:52453 eset_mitm_detected_(false),
[email protected]30bd4e352011-07-01 16:22:27454 kaspersky_mitm_detected_(false),
[email protected]3b1d3db2010-10-28 16:39:40455 predicted_cert_chain_correct_(false),
[email protected]a3ff5e92009-10-13 04:48:06456 next_handshake_state_(STATE_NONE),
[email protected]b43c97c2008-10-22 19:50:58457 nss_fd_(NULL),
[email protected]a2006ece2010-04-23 16:44:02458 nss_bufs_(NULL),
[email protected]7a8de3072010-10-01 16:25:54459 net_log_(transport_socket->socket()->NetLog()),
[email protected]d8fbf582010-11-04 21:51:12460 ssl_host_info_(ssl_host_info),
[email protected]feb79bcd2011-07-21 16:55:17461 dns_cert_checker_(context.dns_cert_checker),
[email protected]93c57682011-02-12 02:05:08462 valid_thread_id_(base::kInvalidThreadId) {
[email protected]e17b4c12008-11-05 22:04:08463 EnterFunction("");
[email protected]b43c97c2008-10-22 19:50:58464}
465
466SSLClientSocketNSS::~SSLClientSocketNSS() {
[email protected]e17b4c12008-11-05 22:04:08467 EnterFunction("");
[email protected]b43c97c2008-10-22 19:50:58468 Disconnect();
[email protected]e17b4c12008-11-05 22:04:08469 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:58470}
471
[email protected]d100e44f2011-01-26 22:47:11472// static
473void SSLClientSocketNSS::ClearSessionCache() {
474 SSL_ClearSessionCache();
475}
476
477void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
[email protected]e17b4c12008-11-05 22:04:08478 EnterFunction("");
[email protected]d100e44f2011-01-26 22:47:11479 ssl_info->Reset();
[email protected]b43c97c2008-10-22 19:50:58480
[email protected]3d5c1bd2011-07-20 02:14:01481 if (!server_cert_nss_)
[email protected]7a8de3072010-10-01 16:25:54482 return;
[email protected]7a8de3072010-10-01 16:25:54483
[email protected]d100e44f2011-01-26 22:47:11484 ssl_info->cert_status = server_cert_verify_result_->cert_status;
[email protected]d100e44f2011-01-26 22:47:11485 ssl_info->cert = server_cert_;
486 ssl_info->connection_status = ssl_connection_status_;
[email protected]1f522492011-04-13 22:06:38487 ssl_info->public_key_hashes = server_cert_verify_result_->public_key_hashes;
488 ssl_info->is_issued_by_known_root =
489 server_cert_verify_result_->is_issued_by_known_root;
[email protected]7a8de3072010-10-01 16:25:54490
[email protected]d100e44f2011-01-26 22:47:11491 PRUint16 cipher_suite =
492 SSLConnectionStatusToCipherSuite(ssl_connection_status_);
493 SSLCipherSuiteInfo cipher_info;
494 SECStatus ok = SSL_GetCipherSuiteInfo(cipher_suite,
495 &cipher_info, sizeof(cipher_info));
496 if (ok == SECSuccess) {
497 ssl_info->security_bits = cipher_info.effectiveKeyBits;
[email protected]98f397e2010-10-26 13:56:57498 } else {
[email protected]d100e44f2011-01-26 22:47:11499 ssl_info->security_bits = -1;
500 LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError()
501 << " for cipherSuite " << cipher_suite;
[email protected]98f397e2010-10-26 13:56:57502 }
[email protected]b076d6c2011-06-29 14:47:51503
504 PRBool last_handshake_resumed;
505 ok = SSL_HandshakeResumedSession(nss_fd_, &last_handshake_resumed);
506 if (ok == SECSuccess) {
507 if (last_handshake_resumed) {
508 ssl_info->handshake_type = SSLInfo::HANDSHAKE_RESUME;
509 } else {
510 ssl_info->handshake_type = SSLInfo::HANDSHAKE_FULL;
511 }
512 }
513
[email protected]d100e44f2011-01-26 22:47:11514 LeaveFunction("");
[email protected]7a8de3072010-10-01 16:25:54515}
516
[email protected]d100e44f2011-01-26 22:47:11517void SSLClientSocketNSS::GetSSLCertRequestInfo(
518 SSLCertRequestInfo* cert_request_info) {
519 EnterFunction("");
520 // TODO(rch): switch SSLCertRequestInfo.host_and_port to a HostPortPair
521 cert_request_info->host_and_port = host_and_port_.ToString();
522 cert_request_info->client_certs = client_certs_;
523 LeaveFunction(cert_request_info->client_certs.size());
[email protected]7a8de3072010-10-01 16:25:54524}
525
[email protected]d100e44f2011-01-26 22:47:11526SSLClientSocket::NextProtoStatus
527SSLClientSocketNSS::GetNextProto(std::string* proto) {
528#if defined(SSL_NEXT_PROTO_NEGOTIATED)
[email protected]d100e44f2011-01-26 22:47:11529 unsigned char buf[255];
530 int state;
531 unsigned len;
532 SECStatus rv = SSL_GetNextProto(nss_fd_, &state, buf, &len, sizeof(buf));
533 if (rv != SECSuccess) {
534 NOTREACHED() << "Error return from SSL_GetNextProto: " << rv;
535 proto->clear();
536 return kNextProtoUnsupported;
[email protected]7a8de3072010-10-01 16:25:54537 }
[email protected]d100e44f2011-01-26 22:47:11538 // We don't check for truncation because sizeof(buf) is large enough to hold
539 // the maximum protocol size.
540 switch (state) {
541 case SSL_NEXT_PROTO_NO_SUPPORT:
542 proto->clear();
543 return kNextProtoUnsupported;
544 case SSL_NEXT_PROTO_NEGOTIATED:
545 *proto = std::string(reinterpret_cast<char*>(buf), len);
546 return kNextProtoNegotiated;
547 case SSL_NEXT_PROTO_NO_OVERLAP:
548 *proto = std::string(reinterpret_cast<char*>(buf), len);
549 return kNextProtoNoOverlap;
550 default:
551 NOTREACHED() << "Unknown status from SSL_GetNextProto: " << state;
552 proto->clear();
553 return kNextProtoUnsupported;
[email protected]d0672be2010-10-20 16:30:19554 }
[email protected]d100e44f2011-01-26 22:47:11555#else
556 // No NPN support in the libssl that we are building with.
557 proto->clear();
558 return kNextProtoUnsupported;
559#endif
[email protected]7a8de3072010-10-01 16:25:54560}
561
[email protected]a2006ece2010-04-23 16:44:02562int SSLClientSocketNSS::Connect(CompletionCallback* callback) {
[email protected]e17b4c12008-11-05 22:04:08563 EnterFunction("");
[email protected]b43c97c2008-10-22 19:50:58564 DCHECK(transport_.get());
[email protected]a3ff5e92009-10-13 04:48:06565 DCHECK(next_handshake_state_ == STATE_NONE);
566 DCHECK(!user_read_callback_);
567 DCHECK(!user_write_callback_);
[email protected]a6eb576292009-06-30 16:19:00568 DCHECK(!user_connect_callback_);
[email protected]a3ff5e92009-10-13 04:48:06569 DCHECK(!user_read_buf_);
570 DCHECK(!user_write_buf_);
[email protected]b43c97c2008-10-22 19:50:58571
[email protected]93c57682011-02-12 02:05:08572 EnsureThreadIdAssigned();
573
[email protected]ec11be62010-04-28 19:28:09574 net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT, NULL);
[email protected]5a05c47a2009-11-02 23:25:19575
[email protected]dbc13b52010-04-16 00:59:56576 int rv = Init();
577 if (rv != OK) {
[email protected]d7fd1782011-02-08 19:16:43578 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
[email protected]dbc13b52010-04-16 00:59:56579 return rv;
[email protected]0ef0bcf2009-04-03 20:39:43580 }
581
[email protected]dbc13b52010-04-16 00:59:56582 rv = InitializeSSLOptions();
[email protected]5a05c47a2009-11-02 23:25:19583 if (rv != OK) {
[email protected]d7fd1782011-02-08 19:16:43584 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
[email protected]5a05c47a2009-11-02 23:25:19585 return rv;
586 }
587
[email protected]efaba4812011-06-22 20:31:53588 rv = InitializeSSLPeerName();
589 if (rv != OK) {
590 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
591 return rv;
[email protected]7f7e92392010-10-26 18:29:29592 }
593
[email protected]2fb7e3ba2011-06-22 19:24:38594 if (ssl_config_.cached_info_enabled && ssl_host_info_.get()) {
595 GotoState(STATE_LOAD_SSL_HOST_INFO);
596 } else {
597 GotoState(STATE_HANDSHAKE);
598 }
[email protected]7a8de3072010-10-01 16:25:54599
[email protected]5a05c47a2009-11-02 23:25:19600 rv = DoHandshakeLoop(OK);
601 if (rv == ERR_IO_PENDING) {
[email protected]8d371892011-04-12 19:46:27602 user_connect_callback_ = callback;
[email protected]5a05c47a2009-11-02 23:25:19603 } else {
[email protected]d7fd1782011-02-08 19:16:43604 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
[email protected]5a05c47a2009-11-02 23:25:19605 }
606
607 LeaveFunction("");
608 return rv > OK ? OK : rv;
609}
610
[email protected]d100e44f2011-01-26 22:47:11611void SSLClientSocketNSS::Disconnect() {
612 EnterFunction("");
613
[email protected]0bc83b3e2011-03-08 22:32:53614 CHECK(CalledOnValidThread());
615
[email protected]93c57682011-02-12 02:05:08616 // Shut down anything that may call us back (through buffer_send_callback_,
617 // buffer_recv_callback, or handshake_io_callback_).
618 verifier_.reset();
619 transport_->socket()->Disconnect();
620
[email protected]d100e44f2011-01-26 22:47:11621 // TODO(wtc): Send SSL close_notify alert.
622 if (nss_fd_ != NULL) {
623 PR_Close(nss_fd_);
624 nss_fd_ = NULL;
625 }
626
[email protected]d100e44f2011-01-26 22:47:11627 // Reset object state
628 transport_send_busy_ = false;
629 transport_recv_busy_ = false;
630 user_connect_callback_ = NULL;
631 user_read_callback_ = NULL;
632 user_write_callback_ = NULL;
633 user_read_buf_ = NULL;
634 user_read_buf_len_ = 0;
635 user_write_buf_ = NULL;
636 user_write_buf_len_ = 0;
637 server_cert_ = NULL;
638 if (server_cert_nss_) {
639 CERT_DestroyCertificate(server_cert_nss_);
640 server_cert_nss_ = NULL;
641 }
642 local_server_cert_verify_result_.Reset();
643 server_cert_verify_result_ = NULL;
644 ssl_connection_status_ = 0;
645 completed_handshake_ = false;
[email protected]d100e44f2011-01-26 22:47:11646 eset_mitm_detected_ = false;
[email protected]30bd4e352011-07-01 16:22:27647 kaspersky_mitm_detected_ = false;
[email protected]d100e44f2011-01-26 22:47:11648 start_cert_verification_time_ = base::TimeTicks();
649 predicted_cert_chain_correct_ = false;
[email protected]d100e44f2011-01-26 22:47:11650 nss_bufs_ = NULL;
651 client_certs_.clear();
652 client_auth_cert_needed_ = false;
653
654 LeaveFunction("");
655}
656
657bool SSLClientSocketNSS::IsConnected() const {
658 // Ideally, we should also check if we have received the close_notify alert
659 // message from the server, and return false in that case. We're not doing
660 // that, so this function may return a false positive. Since the upper
661 // layer (HttpNetworkTransaction) needs to handle a persistent connection
662 // closed by the server when we send a request anyway, a false positive in
663 // exchange for simpler code is a good trade-off.
664 EnterFunction("");
[email protected]8d371892011-04-12 19:46:27665 bool ret = completed_handshake_ && transport_->socket()->IsConnected();
[email protected]d100e44f2011-01-26 22:47:11666 LeaveFunction("");
667 return ret;
668}
669
670bool SSLClientSocketNSS::IsConnectedAndIdle() const {
671 // Unlike IsConnected, this method doesn't return a false positive.
672 //
673 // Strictly speaking, we should check if we have received the close_notify
674 // alert message from the server, and return false in that case. Although
675 // the close_notify alert message means EOF in the SSL layer, it is just
676 // bytes to the transport layer below, so
677 // transport_->socket()->IsConnectedAndIdle() returns the desired false
678 // when we receive close_notify.
679 EnterFunction("");
[email protected]8d371892011-04-12 19:46:27680 bool ret = completed_handshake_ && transport_->socket()->IsConnectedAndIdle();
[email protected]d100e44f2011-01-26 22:47:11681 LeaveFunction("");
682 return ret;
683}
684
685int SSLClientSocketNSS::GetPeerAddress(AddressList* address) const {
686 return transport_->socket()->GetPeerAddress(address);
687}
688
[email protected]e7f74da2011-04-19 23:49:35689int SSLClientSocketNSS::GetLocalAddress(IPEndPoint* address) const {
690 return transport_->socket()->GetLocalAddress(address);
691}
692
[email protected]d100e44f2011-01-26 22:47:11693const BoundNetLog& SSLClientSocketNSS::NetLog() const {
694 return net_log_;
695}
696
697void SSLClientSocketNSS::SetSubresourceSpeculation() {
698 if (transport_.get() && transport_->socket()) {
699 transport_->socket()->SetSubresourceSpeculation();
700 } else {
701 NOTREACHED();
702 }
703}
704
705void SSLClientSocketNSS::SetOmniboxSpeculation() {
706 if (transport_.get() && transport_->socket()) {
707 transport_->socket()->SetOmniboxSpeculation();
708 } else {
709 NOTREACHED();
710 }
711}
712
713bool SSLClientSocketNSS::WasEverUsed() const {
714 if (transport_.get() && transport_->socket()) {
715 return transport_->socket()->WasEverUsed();
716 }
717 NOTREACHED();
718 return false;
719}
720
721bool SSLClientSocketNSS::UsingTCPFastOpen() const {
722 if (transport_.get() && transport_->socket()) {
723 return transport_->socket()->UsingTCPFastOpen();
724 }
725 NOTREACHED();
726 return false;
727}
728
[email protected]5e6efa52011-06-27 17:26:41729int64 SSLClientSocketNSS::NumBytesRead() const {
730 if (transport_.get() && transport_->socket()) {
731 return transport_->socket()->NumBytesRead();
732 }
733 NOTREACHED();
734 return -1;
735}
736
737base::TimeDelta SSLClientSocketNSS::GetConnectTimeMicros() const {
738 if (transport_.get() && transport_->socket()) {
739 return transport_->socket()->GetConnectTimeMicros();
740 }
741 NOTREACHED();
742 return base::TimeDelta::FromMicroseconds(-1);
743}
744
[email protected]d100e44f2011-01-26 22:47:11745int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len,
746 CompletionCallback* callback) {
747 EnterFunction(buf_len);
[email protected]8d371892011-04-12 19:46:27748 DCHECK(completed_handshake_);
749 DCHECK(next_handshake_state_ == STATE_NONE);
[email protected]d100e44f2011-01-26 22:47:11750 DCHECK(!user_read_callback_);
751 DCHECK(!user_connect_callback_);
752 DCHECK(!user_read_buf_);
753 DCHECK(nss_bufs_);
754
755 user_read_buf_ = buf;
756 user_read_buf_len_ = buf_len;
757
[email protected]d100e44f2011-01-26 22:47:11758 int rv = DoReadLoop(OK);
759
760 if (rv == ERR_IO_PENDING) {
761 user_read_callback_ = callback;
762 } else {
763 user_read_buf_ = NULL;
764 user_read_buf_len_ = 0;
765 }
766 LeaveFunction(rv);
767 return rv;
768}
769
770int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len,
771 CompletionCallback* callback) {
772 EnterFunction(buf_len);
[email protected]8d371892011-04-12 19:46:27773 DCHECK(completed_handshake_);
774 DCHECK(next_handshake_state_ == STATE_NONE);
[email protected]d100e44f2011-01-26 22:47:11775 DCHECK(!user_write_callback_);
[email protected]8d371892011-04-12 19:46:27776 DCHECK(!user_connect_callback_);
[email protected]d100e44f2011-01-26 22:47:11777 DCHECK(!user_write_buf_);
778 DCHECK(nss_bufs_);
779
780 user_write_buf_ = buf;
781 user_write_buf_len_ = buf_len;
782
[email protected]d100e44f2011-01-26 22:47:11783 if (corked_) {
784 corked_ = false;
785 uncork_timer_.Reset();
786 }
787 int rv = DoWriteLoop(OK);
788
789 if (rv == ERR_IO_PENDING) {
790 user_write_callback_ = callback;
791 } else {
792 user_write_buf_ = NULL;
793 user_write_buf_len_ = 0;
794 }
795 LeaveFunction(rv);
796 return rv;
797}
798
799bool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) {
800 return transport_->socket()->SetReceiveBufferSize(size);
801}
802
803bool SSLClientSocketNSS::SetSendBufferSize(int32 size) {
804 return transport_->socket()->SetSendBufferSize(size);
805}
806
807int SSLClientSocketNSS::Init() {
808 EnterFunction("");
809 // Initialize the NSS SSL library in a threadsafe way. This also
810 // initializes the NSS base library.
811 EnsureNSSSSLInit();
812 if (!NSS_IsInitialized())
813 return ERR_UNEXPECTED;
814#if !defined(OS_MACOSX) && !defined(OS_WIN)
815 // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop
816 // by MessageLoopForIO::current().
817 // X509Certificate::Verify() runs on a worker thread of CertVerifier.
818 EnsureOCSPInit();
819#endif
820
821 LeaveFunction("");
822 return OK;
823}
824
[email protected]5a05c47a2009-11-02 23:25:19825int SSLClientSocketNSS::InitializeSSLOptions() {
[email protected]0ef0bcf2009-04-03 20:39:43826 // Transport connected, now hook it up to nss
827 // TODO(port): specify rx and tx buffer sizes separately
828 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize);
829 if (nss_fd_ == NULL) {
[email protected]38a18722009-12-04 00:09:04830 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code.
[email protected]0ef0bcf2009-04-03 20:39:43831 }
832
[email protected]0ef0bcf2009-04-03 20:39:43833 // Grab pointer to buffers
834 nss_bufs_ = memio_GetSecret(nss_fd_);
835
836 /* Create SSL state machine */
837 /* Push SSL onto our fake I/O socket */
838 nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
839 if (nss_fd_ == NULL) {
[email protected]7cbc6df12010-10-04 16:25:39840 LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
[email protected]4e91b5c2010-09-22 01:04:38841 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR/NSS error code.
[email protected]0ef0bcf2009-04-03 20:39:43842 }
843 // TODO(port): set more ssl options! Check errors!
844
845 int rv;
846
847 rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
[email protected]7cbc6df12010-10-04 16:25:39848 if (rv != SECSuccess) {
849 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
[email protected]4e91b5c2010-09-22 01:04:38850 return ERR_UNEXPECTED;
[email protected]7cbc6df12010-10-04 16:25:39851 }
[email protected]0ef0bcf2009-04-03 20:39:43852
[email protected]cc50fdf72010-11-30 17:48:54853 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
[email protected]7cbc6df12010-10-04 16:25:39854 if (rv != SECSuccess) {
855 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
[email protected]4e91b5c2010-09-22 01:04:38856 return ERR_UNEXPECTED;
[email protected]7cbc6df12010-10-04 16:25:39857 }
[email protected]0ef0bcf2009-04-03 20:39:43858
[email protected]cc50fdf72010-11-30 17:48:54859 // Don't do V2 compatible hellos because they don't support TLS extensions.
860 rv = SSL_OptionSet(nss_fd_, SSL_V2_COMPATIBLE_HELLO, PR_FALSE);
[email protected]7cbc6df12010-10-04 16:25:39861 if (rv != SECSuccess) {
862 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_V2_COMPATIBLE_HELLO");
863 return ERR_UNEXPECTED;
864 }
[email protected]0ef0bcf2009-04-03 20:39:43865
866 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL3, ssl_config_.ssl3_enabled);
[email protected]7cbc6df12010-10-04 16:25:39867 if (rv != SECSuccess) {
868 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL3");
869 return ERR_UNEXPECTED;
870 }
[email protected]0ef0bcf2009-04-03 20:39:43871
872 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_TLS, ssl_config_.tls1_enabled);
[email protected]7cbc6df12010-10-04 16:25:39873 if (rv != SECSuccess) {
874 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_TLS");
875 return ERR_UNEXPECTED;
876 }
[email protected]0ef0bcf2009-04-03 20:39:43877
[email protected]47f7d742010-11-11 04:12:53878 for (std::vector<uint16>::const_iterator it =
879 ssl_config_.disabled_cipher_suites.begin();
880 it != ssl_config_.disabled_cipher_suites.end(); ++it) {
881 // This will fail if the specified cipher is not implemented by NSS, but
882 // the failure is harmless.
883 SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
884 }
885
[email protected]0ef0bcf2009-04-03 20:39:43886#ifdef SSL_ENABLE_SESSION_TICKETS
887 // Support RFC 5077
888 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
[email protected]7cbc6df12010-10-04 16:25:39889 if (rv != SECSuccess) {
890 LogFailedNSSFunction(
891 net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
892 }
[email protected]0ef0bcf2009-04-03 20:39:43893#else
894 #error "You need to install NSS-3.12 or later to build chromium"
895#endif
896
[email protected]7e52ed72009-11-17 00:40:12897#ifdef SSL_ENABLE_DEFLATE
[email protected]074c1582010-01-08 21:38:28898 // Some web servers have been found to break if TLS is used *or* if DEFLATE
899 // is advertised. Thus, if TLS is disabled (probably because we are doing
900 // SSLv3 fallback), we disable DEFLATE also.
901 // See http://crbug.com/31628
902 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_DEFLATE, ssl_config_.tls1_enabled);
[email protected]7e52ed72009-11-17 00:40:12903 if (rv != SECSuccess)
[email protected]7cbc6df12010-10-04 16:25:39904 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_DEFLATE");
[email protected]7e52ed72009-11-17 00:40:12905#endif
906
[email protected]c2def1c2010-03-02 21:40:34907#ifdef SSL_ENABLE_FALSE_START
[email protected]a0deaecf2010-08-18 23:39:52908 rv = SSL_OptionSet(
909 nss_fd_, SSL_ENABLE_FALSE_START,
910 ssl_config_.false_start_enabled &&
[email protected]4f4de7e62010-11-12 19:55:27911 !SSLConfigService::IsKnownFalseStartIncompatibleServer(
912 host_and_port_.host()));
[email protected]c2def1c2010-03-02 21:40:34913 if (rv != SECSuccess)
[email protected]7cbc6df12010-10-04 16:25:39914 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_FALSE_START");
[email protected]c2def1c2010-03-02 21:40:34915#endif
916
[email protected]33b3eb92010-01-06 01:35:04917#ifdef SSL_ENABLE_RENEGOTIATION
[email protected]53a17e22011-04-05 19:54:14918 // We allow servers to request renegotiation. Since we're a client,
919 // prohibiting this is rather a waste of time. Only servers are in a
920 // position to prevent renegotiation attacks.
921 // http://extendedsubset.com/?p=8
[email protected]d102f542010-06-30 14:51:05922
[email protected]53a17e22011-04-05 19:54:14923 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_RENEGOTIATION,
924 SSL_RENEGOTIATE_TRANSITIONAL);
[email protected]7cbc6df12010-10-04 16:25:39925 if (rv != SECSuccess) {
926 LogFailedNSSFunction(
927 net_log_, "SSL_OptionSet", "SSL_ENABLE_RENEGOTIATION");
928 }
[email protected]d102f542010-06-30 14:51:05929#endif // SSL_ENABLE_RENEGOTIATION
[email protected]33b3eb92010-01-06 01:35:04930
[email protected]644bdca2009-11-30 20:40:53931#ifdef SSL_NEXT_PROTO_NEGOTIATED
932 if (!ssl_config_.next_protos.empty()) {
933 rv = SSL_SetNextProtoNego(
934 nss_fd_,
935 reinterpret_cast<const unsigned char *>(ssl_config_.next_protos.data()),
936 ssl_config_.next_protos.size());
937 if (rv != SECSuccess)
[email protected]7cbc6df12010-10-04 16:25:39938 LogFailedNSSFunction(net_log_, "SSL_SetNextProtoNego", "");
[email protected]644bdca2009-11-30 20:40:53939 }
940#endif
941
[email protected]71d6ccaa2011-01-06 17:43:21942#ifdef SSL_ENABLE_OCSP_STAPLING
[email protected]8d371892011-04-12 19:46:27943 if (IsOCSPStaplingSupported()) {
[email protected]71d6ccaa2011-01-06 17:43:21944 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, PR_TRUE);
[email protected]2fb7e3ba2011-06-22 19:24:38945 if (rv != SECSuccess) {
946 LogFailedNSSFunction(net_log_, "SSL_OptionSet",
947 "SSL_ENABLE_OCSP_STAPLING");
948 }
[email protected]71d6ccaa2011-01-06 17:43:21949 }
950#endif
951
[email protected]2fb7e3ba2011-06-22 19:24:38952#ifdef SSL_ENABLE_CACHED_INFO
953 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_CACHED_INFO,
954 ssl_config_.cached_info_enabled);
955 if (rv != SECSuccess)
956 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_CACHED_INFO");
957#endif
958
[email protected]42329422011-07-14 18:45:31959#ifdef SSL_ENABLE_OB_CERTS
[email protected]2619d3312011-07-20 23:50:34960 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OB_CERTS,
961 ssl_config_.origin_bound_certs_enabled);
[email protected]42329422011-07-14 18:45:31962 if (rv != SECSuccess)
963 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_OB_CERTS");
964#endif
965
[email protected]0ef0bcf2009-04-03 20:39:43966 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
[email protected]7cbc6df12010-10-04 16:25:39967 if (rv != SECSuccess) {
968 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
969 return ERR_UNEXPECTED;
970 }
[email protected]0ef0bcf2009-04-03 20:39:43971
972 rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
[email protected]7cbc6df12010-10-04 16:25:39973 if (rv != SECSuccess) {
974 LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
975 return ERR_UNEXPECTED;
976 }
[email protected]0ef0bcf2009-04-03 20:39:43977
[email protected]4a842342010-11-04 16:21:33978#if defined(NSS_PLATFORM_CLIENT_AUTH)
979 rv = SSL_GetPlatformClientAuthDataHook(nss_fd_, PlatformClientAuthHandler,
980 this);
981#else
[email protected]d84b3722009-10-15 21:23:37982 rv = SSL_GetClientAuthDataHook(nss_fd_, ClientAuthHandler, this);
[email protected]4a842342010-11-04 16:21:33983#endif
[email protected]7cbc6df12010-10-04 16:25:39984 if (rv != SECSuccess) {
985 LogFailedNSSFunction(net_log_, "SSL_GetClientAuthDataHook", "");
986 return ERR_UNEXPECTED;
987 }
[email protected]d84b3722009-10-15 21:23:37988
[email protected]2345cc52009-06-04 09:18:47989 rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
[email protected]7cbc6df12010-10-04 16:25:39990 if (rv != SECSuccess) {
991 LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", "");
[email protected]2345cc52009-06-04 09:18:47992 return ERR_UNEXPECTED;
[email protected]7cbc6df12010-10-04 16:25:39993 }
[email protected]0ef0bcf2009-04-03 20:39:43994
995 // Tell SSL the hostname we're trying to connect to.
[email protected]4f4de7e62010-11-12 19:55:27996 SSL_SetURL(nss_fd_, host_and_port_.host().c_str());
[email protected]0ef0bcf2009-04-03 20:39:43997
[email protected]7f7e92392010-10-26 18:29:29998 // Tell SSL we're a client; needed if not letting NSPR do socket I/O
[email protected]efaba4812011-06-22 20:31:53999 SSL_ResetHandshake(nss_fd_, PR_FALSE);
[email protected]7f7e92392010-10-26 18:29:291000
1001 return OK;
1002}
1003
1004int SSLClientSocketNSS::InitializeSSLPeerName() {
1005 // Tell NSS who we're connected to
1006 AddressList peer_address;
1007 int err = transport_->socket()->GetPeerAddress(&peer_address);
1008 if (err != OK)
1009 return err;
1010
1011 const struct addrinfo* ai = peer_address.head();
1012
1013 PRNetAddr peername;
1014 memset(&peername, 0, sizeof(peername));
1015 DCHECK_LE(ai->ai_addrlen, sizeof(peername));
1016 size_t len = std::min(static_cast<size_t>(ai->ai_addrlen),
1017 sizeof(peername));
1018 memcpy(&peername, ai->ai_addr, len);
1019
1020 // Adjust the address family field for BSD, whose sockaddr
1021 // structure has a one-byte length and one-byte address family
1022 // field at the beginning. PRNetAddr has a two-byte address
1023 // family field at the beginning.
1024 peername.raw.family = ai->ai_addr->sa_family;
1025
1026 memio_SetPeerName(nss_fd_, &peername);
1027
[email protected]52c27fb2009-11-30 22:40:231028 // Set the peer ID for session reuse. This is necessary when we create an
1029 // SSL tunnel through a proxy -- GetPeerName returns the proxy's address
1030 // rather than the destination server's address in that case.
[email protected]4f4de7e62010-11-12 19:55:271031 std::string peer_id = host_and_port_.ToString();
[email protected]7f7e92392010-10-26 18:29:291032 SECStatus rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str()));
[email protected]52c27fb2009-11-30 22:40:231033 if (rv != SECSuccess)
[email protected]7cbc6df12010-10-04 16:25:391034 LogFailedNSSFunction(net_log_, "SSL_SetSockPeerID", peer_id.c_str());
[email protected]52c27fb2009-11-30 22:40:231035
[email protected]5a05c47a2009-11-02 23:25:191036 return OK;
[email protected]b43c97c2008-10-22 19:50:581037}
1038
[email protected]2d6e77832010-11-10 22:13:461039
[email protected]757f2e2b2010-10-27 23:28:351040// Sets server_cert_ and server_cert_nss_ if not yet set.
[email protected]3d5c1bd2011-07-20 02:14:011041void SSLClientSocketNSS::UpdateServerCert() {
[email protected]757f2e2b2010-10-27 23:28:351042 // We set the server_cert_ from HandshakeCallback().
[email protected]bacff652009-03-31 17:50:331043 if (server_cert_ == NULL) {
[email protected]f505a9b2010-01-28 19:44:021044 server_cert_nss_ = SSL_PeerCertificate(nss_fd_);
1045 if (server_cert_nss_) {
[email protected]4feca4b2010-10-28 16:50:321046 PeerCertificateChain certs(nss_fd_);
[email protected]3d5c1bd2011-07-20 02:14:011047 // This call may fail when SSL is used inside sandbox. In that
1048 // case CreateFromDERCertChain() returns NULL.
[email protected]d8fbf582010-11-04 21:51:121049 server_cert_ = X509Certificate::CreateFromDERCertChain(
1050 certs.AsStringPieceVector());
[email protected]bacff652009-03-31 17:50:331051 }
1052 }
[email protected]bacff652009-03-31 17:50:331053}
1054
[email protected]757f2e2b2010-10-27 23:28:351055// Sets ssl_connection_status_.
1056void SSLClientSocketNSS::UpdateConnectionStatus() {
1057 SSLChannelInfo channel_info;
1058 SECStatus ok = SSL_GetChannelInfo(nss_fd_,
1059 &channel_info, sizeof(channel_info));
1060 if (ok == SECSuccess &&
1061 channel_info.length == sizeof(channel_info) &&
1062 channel_info.cipherSuite) {
1063 ssl_connection_status_ |=
1064 (static_cast<int>(channel_info.cipherSuite) &
1065 SSL_CONNECTION_CIPHERSUITE_MASK) <<
1066 SSL_CONNECTION_CIPHERSUITE_SHIFT;
1067
1068 ssl_connection_status_ |=
1069 (static_cast<int>(channel_info.compressionMethod) &
1070 SSL_CONNECTION_COMPRESSION_MASK) <<
1071 SSL_CONNECTION_COMPRESSION_SHIFT;
1072
[email protected]b92a96e2010-11-02 21:03:051073 // NSS 3.12.x doesn't have version macros for TLS 1.1 and 1.2 (because NSS
1074 // doesn't support them yet), so we use 0x0302 and 0x0303 directly.
[email protected]757f2e2b2010-10-27 23:28:351075 int version = SSL_CONNECTION_VERSION_UNKNOWN;
1076 if (channel_info.protocolVersion < SSL_LIBRARY_VERSION_3_0) {
1077 // All versions less than SSL_LIBRARY_VERSION_3_0 are treated as SSL
1078 // version 2.
1079 version = SSL_CONNECTION_VERSION_SSL2;
1080 } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_0) {
1081 version = SSL_CONNECTION_VERSION_SSL3;
1082 } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_1_TLS) {
1083 version = SSL_CONNECTION_VERSION_TLS1;
[email protected]b92a96e2010-11-02 21:03:051084 } else if (channel_info.protocolVersion == 0x0302) {
1085 version = SSL_CONNECTION_VERSION_TLS1_1;
1086 } else if (channel_info.protocolVersion == 0x0303) {
1087 version = SSL_CONNECTION_VERSION_TLS1_2;
[email protected]757f2e2b2010-10-27 23:28:351088 }
1089 ssl_connection_status_ |=
1090 (version & SSL_CONNECTION_VERSION_MASK) <<
1091 SSL_CONNECTION_VERSION_SHIFT;
1092 }
1093
[email protected]1e7cd2c72010-02-27 01:31:191094 // SSL_HandshakeNegotiatedExtension was added in NSS 3.12.6.
1095 // Since SSL_MAX_EXTENSIONS was added at the same time, we can test
1096 // SSL_MAX_EXTENSIONS for the presence of SSL_HandshakeNegotiatedExtension.
1097#if defined(SSL_MAX_EXTENSIONS)
[email protected]757f2e2b2010-10-27 23:28:351098 PRBool peer_supports_renego_ext;
1099 ok = SSL_HandshakeNegotiatedExtension(nss_fd_, ssl_renegotiation_info_xtn,
1100 &peer_supports_renego_ext);
1101 if (ok == SECSuccess) {
1102 if (!peer_supports_renego_ext) {
1103 ssl_connection_status_ |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
1104 // Log an informational message if the server does not support secure
1105 // renegotiation (RFC 5746).
[email protected]4f4de7e62010-11-12 19:55:271106 VLOG(1) << "The server " << host_and_port_.ToString()
[email protected]757f2e2b2010-10-27 23:28:351107 << " does not support the TLS renegotiation_info extension.";
1108 }
1109 UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported",
1110 peer_supports_renego_ext, 2);
[email protected]1e7cd2c72010-02-27 01:31:191111 }
1112#endif
[email protected]757f2e2b2010-10-27 23:28:351113
1114 if (ssl_config_.ssl3_fallback)
1115 ssl_connection_status_ |= SSL_CONNECTION_SSL3_FALLBACK;
[email protected]1e7cd2c72010-02-27 01:31:191116}
1117
[email protected]a3ff5e92009-10-13 04:48:061118void SSLClientSocketNSS::DoReadCallback(int rv) {
[email protected]e17b4c12008-11-05 22:04:081119 EnterFunction(rv);
[email protected]b43c97c2008-10-22 19:50:581120 DCHECK(rv != ERR_IO_PENDING);
[email protected]a3ff5e92009-10-13 04:48:061121 DCHECK(user_read_callback_);
[email protected]b43c97c2008-10-22 19:50:581122
[email protected]a3ff5e92009-10-13 04:48:061123 // Since Run may result in Read being called, clear |user_read_callback_|
1124 // up front.
1125 CompletionCallback* c = user_read_callback_;
1126 user_read_callback_ = NULL;
1127 user_read_buf_ = NULL;
1128 user_read_buf_len_ = 0;
1129 c->Run(rv);
1130 LeaveFunction("");
1131}
1132
1133void SSLClientSocketNSS::DoWriteCallback(int rv) {
1134 EnterFunction(rv);
1135 DCHECK(rv != ERR_IO_PENDING);
1136 DCHECK(user_write_callback_);
1137
1138 // Since Run may result in Write being called, clear |user_write_callback_|
1139 // up front.
1140 CompletionCallback* c = user_write_callback_;
1141 user_write_callback_ = NULL;
1142 user_write_buf_ = NULL;
1143 user_write_buf_len_ = 0;
[email protected]b43c97c2008-10-22 19:50:581144 c->Run(rv);
[email protected]e17b4c12008-11-05 22:04:081145 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581146}
1147
[email protected]a6eb576292009-06-30 16:19:001148// As part of Connect(), the SSLClientSocketNSS object performs an SSL
1149// handshake. This requires network IO, which in turn calls
1150// BufferRecvComplete() with a non-zero byte count. This byte count eventually
1151// winds its way through the state machine and ends up being passed to the
1152// callback. For Read() and Write(), that's what we want. But for Connect(),
1153// the caller expects OK (i.e. 0) for success.
1154//
1155void SSLClientSocketNSS::DoConnectCallback(int rv) {
1156 EnterFunction(rv);
1157 DCHECK_NE(rv, ERR_IO_PENDING);
[email protected]8d371892011-04-12 19:46:271158 DCHECK(user_connect_callback_);
[email protected]a6eb576292009-06-30 16:19:001159
[email protected]a6eb576292009-06-30 16:19:001160 CompletionCallback* c = user_connect_callback_;
1161 user_connect_callback_ = NULL;
1162 c->Run(rv > OK ? OK : rv);
1163 LeaveFunction("");
1164}
1165
[email protected]a3ff5e92009-10-13 04:48:061166void SSLClientSocketNSS::OnHandshakeIOComplete(int result) {
[email protected]e17b4c12008-11-05 22:04:081167 EnterFunction(result);
[email protected]a3ff5e92009-10-13 04:48:061168 int rv = DoHandshakeLoop(result);
[email protected]5a05c47a2009-11-02 23:25:191169 if (rv != ERR_IO_PENDING) {
[email protected]d7fd1782011-02-08 19:16:431170 net_log_.EndEventWithNetErrorCode(net::NetLog::TYPE_SSL_CONNECT, rv);
[email protected]8d371892011-04-12 19:46:271171 DoConnectCallback(rv);
[email protected]5a05c47a2009-11-02 23:25:191172 }
[email protected]a3ff5e92009-10-13 04:48:061173 LeaveFunction("");
1174}
1175
1176void SSLClientSocketNSS::OnSendComplete(int result) {
1177 EnterFunction(result);
[email protected]45965de2010-02-25 23:23:311178 if (next_handshake_state_ == STATE_HANDSHAKE) {
[email protected]a3ff5e92009-10-13 04:48:061179 // In handshake phase.
1180 OnHandshakeIOComplete(result);
1181 LeaveFunction("");
1182 return;
[email protected]a6eb576292009-06-30 16:19:001183 }
[email protected]a3ff5e92009-10-13 04:48:061184
1185 // OnSendComplete may need to call DoPayloadRead while the renegotiation
1186 // handshake is in progress.
1187 int rv_read = ERR_IO_PENDING;
1188 int rv_write = ERR_IO_PENDING;
1189 bool network_moved;
1190 do {
1191 if (user_read_buf_)
1192 rv_read = DoPayloadRead();
1193 if (user_write_buf_)
1194 rv_write = DoPayloadWrite();
1195 network_moved = DoTransportIO();
1196 } while (rv_read == ERR_IO_PENDING &&
1197 rv_write == ERR_IO_PENDING &&
1198 network_moved);
1199
1200 if (user_read_buf_ && rv_read != ERR_IO_PENDING)
1201 DoReadCallback(rv_read);
1202 if (user_write_buf_ && rv_write != ERR_IO_PENDING)
1203 DoWriteCallback(rv_write);
1204
1205 LeaveFunction("");
1206}
1207
1208void SSLClientSocketNSS::OnRecvComplete(int result) {
1209 EnterFunction(result);
[email protected]45965de2010-02-25 23:23:311210 if (next_handshake_state_ == STATE_HANDSHAKE) {
[email protected]a3ff5e92009-10-13 04:48:061211 // In handshake phase.
1212 OnHandshakeIOComplete(result);
1213 LeaveFunction("");
1214 return;
1215 }
1216
1217 // Network layer received some data, check if client requested to read
[email protected]8d371892011-04-12 19:46:271218 // decrypted data.
1219 if (!user_read_buf_) {
[email protected]a3ff5e92009-10-13 04:48:061220 LeaveFunction("");
1221 return;
1222 }
1223
1224 int rv = DoReadLoop(result);
1225 if (rv != ERR_IO_PENDING)
1226 DoReadCallback(rv);
[email protected]e17b4c12008-11-05 22:04:081227 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581228}
1229
[email protected]a3ff5e92009-10-13 04:48:061230int SSLClientSocketNSS::DoHandshakeLoop(int last_io_result) {
[email protected]e17b4c12008-11-05 22:04:081231 EnterFunction(last_io_result);
[email protected]b43c97c2008-10-22 19:50:581232 bool network_moved;
1233 int rv = last_io_result;
1234 do {
[email protected]e17b4c12008-11-05 22:04:081235 // Default to STATE_NONE for next state.
[email protected]ea224582008-12-07 20:25:461236 // (This is a quirk carried over from the windows
[email protected]e17b4c12008-11-05 22:04:081237 // implementation. It makes reading the logs a bit harder.)
[email protected]ea224582008-12-07 20:25:461238 // State handlers can and often do call GotoState just
[email protected]e17b4c12008-11-05 22:04:081239 // to stay in the current state.
[email protected]a3ff5e92009-10-13 04:48:061240 State state = next_handshake_state_;
[email protected]e17b4c12008-11-05 22:04:081241 GotoState(STATE_NONE);
[email protected]b43c97c2008-10-22 19:50:581242 switch (state) {
[email protected]e17b4c12008-11-05 22:04:081243 case STATE_NONE:
1244 // we're just pumping data between the buffer and the network
1245 break;
[email protected]2fb7e3ba2011-06-22 19:24:381246 case STATE_LOAD_SSL_HOST_INFO:
1247 rv = DoLoadSSLHostInfo();
1248 break;
[email protected]a3ff5e92009-10-13 04:48:061249 case STATE_HANDSHAKE:
1250 rv = DoHandshake();
[email protected]b43c97c2008-10-22 19:50:581251 break;
[email protected]899c3e92010-08-28 15:53:501252 case STATE_VERIFY_DNSSEC:
1253 rv = DoVerifyDNSSEC(rv);
1254 break;
[email protected]2345cc52009-06-04 09:18:471255 case STATE_VERIFY_CERT:
1256 DCHECK(rv == OK);
1257 rv = DoVerifyCert(rv);
1258 break;
1259 case STATE_VERIFY_CERT_COMPLETE:
1260 rv = DoVerifyCertComplete(rv);
1261 break;
[email protected]b43c97c2008-10-22 19:50:581262 default:
1263 rv = ERR_UNEXPECTED;
[email protected]4e91b5c2010-09-22 01:04:381264 LOG(DFATAL) << "unexpected state " << state;
[email protected]b43c97c2008-10-22 19:50:581265 break;
1266 }
1267
1268 // Do the actual network I/O
[email protected]a3ff5e92009-10-13 04:48:061269 network_moved = DoTransportIO();
[email protected]72d1e592009-03-10 17:39:461270 } while ((rv != ERR_IO_PENDING || network_moved) &&
[email protected]7a8de3072010-10-01 16:25:541271 next_handshake_state_ != STATE_NONE);
[email protected]a3ff5e92009-10-13 04:48:061272 LeaveFunction("");
1273 return rv;
1274}
1275
1276int SSLClientSocketNSS::DoReadLoop(int result) {
1277 EnterFunction("");
1278 DCHECK(completed_handshake_);
1279 DCHECK(next_handshake_state_ == STATE_NONE);
1280
1281 if (result < 0)
1282 return result;
1283
[email protected]4e91b5c2010-09-22 01:04:381284 if (!nss_bufs_) {
1285 LOG(DFATAL) << "!nss_bufs_";
[email protected]7cbc6df12010-10-04 16:25:391286 int rv = ERR_UNEXPECTED;
[email protected]00cd9c42010-11-02 20:15:571287 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
1288 make_scoped_refptr(new SSLErrorParams(rv, 0)));
[email protected]7cbc6df12010-10-04 16:25:391289 return rv;
[email protected]4e91b5c2010-09-22 01:04:381290 }
[email protected]a3ff5e92009-10-13 04:48:061291
1292 bool network_moved;
1293 int rv;
1294 do {
1295 rv = DoPayloadRead();
1296 network_moved = DoTransportIO();
1297 } while (rv == ERR_IO_PENDING && network_moved);
1298
1299 LeaveFunction("");
1300 return rv;
1301}
1302
1303int SSLClientSocketNSS::DoWriteLoop(int result) {
1304 EnterFunction("");
1305 DCHECK(completed_handshake_);
1306 DCHECK(next_handshake_state_ == STATE_NONE);
1307
1308 if (result < 0)
1309 return result;
1310
[email protected]4e91b5c2010-09-22 01:04:381311 if (!nss_bufs_) {
1312 LOG(DFATAL) << "!nss_bufs_";
[email protected]7cbc6df12010-10-04 16:25:391313 int rv = ERR_UNEXPECTED;
[email protected]00cd9c42010-11-02 20:15:571314 net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
1315 make_scoped_refptr(new SSLErrorParams(rv, 0)));
[email protected]7cbc6df12010-10-04 16:25:391316 return rv;
[email protected]4e91b5c2010-09-22 01:04:381317 }
[email protected]a3ff5e92009-10-13 04:48:061318
1319 bool network_moved;
1320 int rv;
1321 do {
1322 rv = DoPayloadWrite();
1323 network_moved = DoTransportIO();
1324 } while (rv == ERR_IO_PENDING && network_moved);
1325
[email protected]e17b4c12008-11-05 22:04:081326 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581327 return rv;
1328}
1329
[email protected]2fb7e3ba2011-06-22 19:24:381330bool SSLClientSocketNSS::LoadSSLHostInfo() {
1331 const SSLHostInfo::State& state(ssl_host_info_->state());
1332
1333 if (state.certs.empty())
1334 return false;
1335
1336 SECStatus rv;
1337 const std::vector<std::string>& certs_in = state.certs;
1338 scoped_array<CERTCertificate*> certs(new CERTCertificate*[certs_in.size()]);
1339
1340 for (size_t i = 0; i < certs_in.size(); i++) {
1341 SECItem derCert;
1342 derCert.data =
1343 const_cast<uint8*>(reinterpret_cast<const uint8*>(certs_in[i].data()));
1344 derCert.len = certs_in[i].size();
1345 certs[i] = CERT_NewTempCertificate(
1346 CERT_GetDefaultCertDB(), &derCert, NULL /* no nickname given */,
1347 PR_FALSE /* not permanent */, PR_TRUE /* copy DER data */);
1348 if (!certs[i]) {
1349 DestroyCertificates(&certs[0], i);
1350 NOTREACHED();
1351 return false;
1352 }
1353 }
1354
1355 rv = SSL_SetPredictedPeerCertificates(nss_fd_, certs.get(), certs_in.size());
1356 DestroyCertificates(&certs[0], certs_in.size());
1357 DCHECK_EQ(SECSuccess, rv);
1358
1359 return true;
1360}
1361
1362int SSLClientSocketNSS::DoLoadSSLHostInfo() {
1363 int rv;
1364
1365 EnterFunction("");
1366 rv = ssl_host_info_->WaitForDataReady(&handshake_io_callback_);
1367 GotoState(STATE_HANDSHAKE);
1368
1369 if (rv == OK) {
1370 if (!LoadSSLHostInfo())
1371 LOG(WARNING) << "LoadSSLHostInfo failed: " << host_and_port_.ToString();
1372 } else {
1373 DCHECK_EQ(ERR_IO_PENDING, rv);
1374 GotoState(STATE_LOAD_SSL_HOST_INFO);
1375 }
1376
1377 LeaveFunction("");
1378 return rv;
1379}
1380
[email protected]d100e44f2011-01-26 22:47:111381int SSLClientSocketNSS::DoHandshake() {
1382 EnterFunction("");
1383 int net_error = net::OK;
1384 SECStatus rv = SSL_ForceHandshake(nss_fd_);
1385
1386 if (client_auth_cert_needed_) {
1387 net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
1388 net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
1389 make_scoped_refptr(new SSLErrorParams(net_error, 0)));
1390 // If the handshake already succeeded (because the server requests but
1391 // doesn't require a client cert), we need to invalidate the SSL session
1392 // so that we won't try to resume the non-client-authenticated session in
1393 // the next handshake. This will cause the server to ask for a client
1394 // cert again.
1395 if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess) {
1396 LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError();
1397 }
1398 } else if (rv == SECSuccess) {
1399 if (handshake_callback_called_) {
1400 if (eset_mitm_detected_) {
1401 net_error = ERR_ESET_ANTI_VIRUS_SSL_INTERCEPTION;
[email protected]30bd4e352011-07-01 16:22:271402 } else if (kaspersky_mitm_detected_) {
1403 net_error = ERR_KASPERSKY_ANTI_VIRUS_SSL_INTERCEPTION;
[email protected]d100e44f2011-01-26 22:47:111404 } else {
1405 // We need to see if the predicted certificate chain (in
1406 // |ssl_host_info_->state().certs) matches the actual certificate chain
[email protected]2fb7e3ba2011-06-22 19:24:381407 // before we call SaveSSLHostInfo, as that will update
1408 // |ssl_host_info_|.
[email protected]d100e44f2011-01-26 22:47:111409 if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty()) {
1410 PeerCertificateChain certs(nss_fd_);
1411 const SSLHostInfo::State& state = ssl_host_info_->state();
1412 predicted_cert_chain_correct_ = certs.size() == state.certs.size();
1413 if (predicted_cert_chain_correct_) {
1414 for (unsigned i = 0; i < certs.size(); i++) {
1415 if (certs[i]->derCert.len != state.certs[i].size() ||
1416 memcmp(certs[i]->derCert.data, state.certs[i].data(),
1417 certs[i]->derCert.len) != 0) {
1418 predicted_cert_chain_correct_ = false;
1419 break;
1420 }
1421 }
1422 }
1423 }
1424
1425#if defined(SSL_ENABLE_OCSP_STAPLING)
[email protected]35a43f92011-02-09 04:39:481426 // TODO(agl): figure out how to plumb an OCSP response into the Mac
1427 // system library and update IsOCSPStaplingSupported for Mac.
1428 if (!predicted_cert_chain_correct_ && IsOCSPStaplingSupported()) {
[email protected]d100e44f2011-01-26 22:47:111429 unsigned int len = 0;
1430 SSL_GetStapledOCSPResponse(nss_fd_, NULL, &len);
1431 if (len) {
1432 const unsigned int orig_len = len;
1433 scoped_array<uint8> ocsp_response(new uint8[orig_len]);
1434 SSL_GetStapledOCSPResponse(nss_fd_, ocsp_response.get(), &len);
1435 DCHECK_EQ(orig_len, len);
1436
[email protected]35a43f92011-02-09 04:39:481437#if defined(OS_WIN)
1438 CRYPT_DATA_BLOB ocsp_response_blob;
1439 ocsp_response_blob.cbData = len;
1440 ocsp_response_blob.pbData = ocsp_response.get();
1441 BOOL ok = CertSetCertificateContextProperty(
1442 server_cert_->os_cert_handle(),
1443 CERT_OCSP_RESPONSE_PROP_ID,
1444 CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG,
1445 &ocsp_response_blob);
1446 if (!ok) {
1447 VLOG(1) << "Failed to set OCSP response property: "
1448 << GetLastError();
1449 }
1450#elif defined(USE_NSS)
1451 CacheOCSPResponseFromSideChannelFunction cache_ocsp_response =
1452 GetCacheOCSPResponseFromSideChannelFunction();
[email protected]d100e44f2011-01-26 22:47:111453 SECItem ocsp_response_item;
1454 ocsp_response_item.type = siBuffer;
1455 ocsp_response_item.data = ocsp_response.get();
1456 ocsp_response_item.len = len;
1457
1458 cache_ocsp_response(
1459 CERT_GetDefaultCertDB(), server_cert_nss_, PR_Now(),
1460 &ocsp_response_item, NULL);
[email protected]35a43f92011-02-09 04:39:481461#endif
[email protected]d100e44f2011-01-26 22:47:111462 }
1463 }
1464#endif
1465
[email protected]8d371892011-04-12 19:46:271466 SaveSSLHostInfo();
1467 // SSL handshake is completed. Let's verify the certificate.
1468 GotoState(STATE_VERIFY_DNSSEC);
[email protected]d100e44f2011-01-26 22:47:111469 }
1470 // Done!
1471 } else {
1472 // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=562434 -
1473 // SSL_ForceHandshake returned SECSuccess prematurely.
1474 rv = SECFailure;
1475 net_error = ERR_SSL_PROTOCOL_ERROR;
1476 net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
1477 make_scoped_refptr(new SSLErrorParams(net_error, 0)));
1478 }
1479 } else {
1480 PRErrorCode prerr = PR_GetError();
[email protected]83530b72011-02-05 04:53:131481 net_error = HandleNSSError(prerr, true);
[email protected]d100e44f2011-01-26 22:47:111482
1483 // If not done, stay in this state
1484 if (net_error == ERR_IO_PENDING) {
1485 GotoState(STATE_HANDSHAKE);
1486 } else {
[email protected]3f1fc2f2011-06-20 19:02:371487 LOG(ERROR) << "handshake with server " << host_and_port_.ToString()
1488 << " failed; NSS error code " << prerr
[email protected]d100e44f2011-01-26 22:47:111489 << ", net_error " << net_error;
1490 net_log_.AddEvent(
1491 NetLog::TYPE_SSL_HANDSHAKE_ERROR,
1492 make_scoped_refptr(new SSLErrorParams(net_error, prerr)));
1493 }
1494 }
1495
1496 LeaveFunction("");
1497 return net_error;
1498}
1499
1500int SSLClientSocketNSS::DoVerifyDNSSEC(int result) {
1501 if (ssl_config_.dns_cert_provenance_checking_enabled &&
1502 dns_cert_checker_) {
1503 PeerCertificateChain certs(nss_fd_);
1504 dns_cert_checker_->DoAsyncVerification(
1505 host_and_port_.host(), certs.AsStringPieceVector());
1506 }
1507
[email protected]c29b0b422011-06-03 00:20:431508 DNSValidationResult r = CheckDNSSECChain(host_and_port_.host(),
1509 server_cert_nss_,
1510 host_and_port_.port());
1511 if (r == DNSVR_SUCCESS) {
1512 local_server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC;
1513 server_cert_verify_result_ = &local_server_cert_verify_result_;
1514 GotoState(STATE_VERIFY_CERT_COMPLETE);
1515 return OK;
[email protected]d100e44f2011-01-26 22:47:111516 }
1517
[email protected]d100e44f2011-01-26 22:47:111518 GotoState(STATE_VERIFY_CERT);
[email protected]d100e44f2011-01-26 22:47:111519
1520 return OK;
1521}
1522
1523int SSLClientSocketNSS::DoVerifyCert(int result) {
[email protected]3d5c1bd2011-07-20 02:14:011524 DCHECK(server_cert_nss_);
[email protected]d100e44f2011-01-26 22:47:111525
1526 GotoState(STATE_VERIFY_CERT_COMPLETE);
[email protected]4dc832e2011-04-28 22:04:241527
[email protected]3d5c1bd2011-07-20 02:14:011528 // If the certificate is expected to be bad we can use the
1529 // expectation as the cert status. Don't use |server_cert_| here
1530 // because it can be set to NULL in case we failed to create
1531 // X509Certificate in UpdateServerCert(). This may happen when this
1532 // code is used inside sandbox.
1533 base::StringPiece der_cert(
1534 reinterpret_cast<char*>(server_cert_nss_->derCert.data),
1535 server_cert_nss_->derCert.len);
[email protected]4dc832e2011-04-28 22:04:241536 int cert_status;
[email protected]3d5c1bd2011-07-20 02:14:011537 if (ssl_config_.IsAllowedBadCert(der_cert, &cert_status)) {
[email protected]4dc832e2011-04-28 22:04:241538 DCHECK(start_cert_verification_time_.is_null());
1539 VLOG(1) << "Received an expected bad cert with status: " << cert_status;
1540 server_cert_verify_result_ = &local_server_cert_verify_result_;
1541 local_server_cert_verify_result_.Reset();
1542 local_server_cert_verify_result_.cert_status = cert_status;
1543 return OK;
1544 }
1545
[email protected]3d5c1bd2011-07-20 02:14:011546 // We may have failed to create X509Certificate object if we are
1547 // running inside sandbox.
1548 if (!server_cert_) {
1549 server_cert_verify_result_ = &local_server_cert_verify_result_;
1550 local_server_cert_verify_result_.Reset();
1551 local_server_cert_verify_result_.cert_status = CERT_STATUS_INVALID;
1552 return ERR_CERT_INVALID;
1553 }
1554
[email protected]d100e44f2011-01-26 22:47:111555 start_cert_verification_time_ = base::TimeTicks::Now();
1556
1557 if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty() &&
1558 predicted_cert_chain_correct_) {
1559 // If the SSLHostInfo had a prediction for the certificate chain of this
1560 // server then it will have optimistically started a verification of that
1561 // chain. So, if the prediction was correct, we should wait for that
1562 // verification to finish rather than start our own.
1563 net_log_.AddEvent(NetLog::TYPE_SSL_VERIFICATION_MERGED, NULL);
1564 UMA_HISTOGRAM_ENUMERATION("Net.SSLVerificationMerged", 1 /* true */, 2);
1565 base::TimeTicks end_time = ssl_host_info_->verification_end_time();
1566 if (end_time.is_null())
1567 end_time = base::TimeTicks::Now();
1568 UMA_HISTOGRAM_TIMES("Net.SSLVerificationMergedMsSaved",
1569 end_time - ssl_host_info_->verification_start_time());
1570 server_cert_verify_result_ = &ssl_host_info_->cert_verify_result();
1571 return ssl_host_info_->WaitForCertVerification(&handshake_io_callback_);
1572 } else {
1573 UMA_HISTOGRAM_ENUMERATION("Net.SSLVerificationMerged", 0 /* false */, 2);
1574 }
1575
1576 int flags = 0;
[email protected]0b711e42011-06-20 19:18:091577 if (ssl_config_.rev_checking_enabled)
1578 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
[email protected]d100e44f2011-01-26 22:47:111579 if (ssl_config_.verify_ev_cert)
1580 flags |= X509Certificate::VERIFY_EV_CERT;
1581 verifier_.reset(new SingleRequestCertVerifier(cert_verifier_));
1582 server_cert_verify_result_ = &local_server_cert_verify_result_;
1583 return verifier_->Verify(server_cert_, host_and_port_.host(), flags,
1584 &local_server_cert_verify_result_,
1585 &handshake_io_callback_);
1586}
1587
1588// Derived from AuthCertificateCallback() in
1589// mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp.
1590int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
1591 verifier_.reset();
1592
1593 if (!start_cert_verification_time_.is_null()) {
1594 base::TimeDelta verify_time =
1595 base::TimeTicks::Now() - start_cert_verification_time_;
1596 if (result == OK)
1597 UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTime", verify_time);
1598 else
1599 UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTimeError", verify_time);
1600 }
1601
[email protected]d100e44f2011-01-26 22:47:111602 // We used to remember the intermediate CA certs in the NSS database
1603 // persistently. However, NSS opens a connection to the SQLite database
1604 // during NSS initialization and doesn't close the connection until NSS
1605 // shuts down. If the file system where the database resides is gone,
1606 // the database connection goes bad. What's worse, the connection won't
1607 // recover when the file system comes back. Until this NSS or SQLite bug
1608 // is fixed, we need to avoid using the NSS database for non-essential
1609 // purposes. See https://bugzilla.mozilla.org/show_bug.cgi?id=508081 and
1610 // http://crbug.com/15630 for more info.
1611
[email protected]4dc832e2011-04-28 22:04:241612 // TODO(hclam): Skip logging if server cert was expected to be bad because
1613 // |server_cert_verify_results_| doesn't contain all the information about
1614 // the cert.
[email protected]d100e44f2011-01-26 22:47:111615 if (result == OK)
1616 LogConnectionTypeMetrics();
1617
1618 completed_handshake_ = true;
1619
[email protected]d100e44f2011-01-26 22:47:111620 if (user_read_callback_) {
1621 int rv = DoReadLoop(OK);
1622 if (rv != ERR_IO_PENDING)
1623 DoReadCallback(rv);
1624 }
1625
1626 // Exit DoHandshakeLoop and return the result to the caller to Connect.
1627 DCHECK(next_handshake_state_ == STATE_NONE);
1628 return result;
1629}
1630
1631int SSLClientSocketNSS::DoPayloadRead() {
1632 EnterFunction(user_read_buf_len_);
1633 DCHECK(user_read_buf_);
1634 DCHECK_GT(user_read_buf_len_, 0);
1635 int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_);
1636 if (client_auth_cert_needed_) {
1637 // We don't need to invalidate the non-client-authenticated SSL session
1638 // because the server will renegotiate anyway.
1639 LeaveFunction("");
1640 rv = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
1641 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
1642 make_scoped_refptr(new SSLErrorParams(rv, 0)));
1643 return rv;
1644 }
1645 if (rv >= 0) {
[email protected]267a0d66d2011-06-01 21:15:191646 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
1647 user_read_buf_->data());
[email protected]d100e44f2011-01-26 22:47:111648 LeaveFunction("");
1649 return rv;
1650 }
1651 PRErrorCode prerr = PR_GetError();
1652 if (prerr == PR_WOULD_BLOCK_ERROR) {
1653 LeaveFunction("");
1654 return ERR_IO_PENDING;
1655 }
1656 LeaveFunction("");
[email protected]83530b72011-02-05 04:53:131657 rv = HandleNSSError(prerr, false);
[email protected]d100e44f2011-01-26 22:47:111658 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
1659 make_scoped_refptr(new SSLErrorParams(rv, prerr)));
1660 return rv;
1661}
1662
1663int SSLClientSocketNSS::DoPayloadWrite() {
1664 EnterFunction(user_write_buf_len_);
1665 DCHECK(user_write_buf_);
1666 int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
1667 if (rv >= 0) {
[email protected]267a0d66d2011-06-01 21:15:191668 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv,
1669 user_write_buf_->data());
[email protected]d100e44f2011-01-26 22:47:111670 LeaveFunction("");
1671 return rv;
1672 }
1673 PRErrorCode prerr = PR_GetError();
1674 if (prerr == PR_WOULD_BLOCK_ERROR) {
1675 LeaveFunction("");
1676 return ERR_IO_PENDING;
1677 }
1678 LeaveFunction("");
[email protected]83530b72011-02-05 04:53:131679 rv = HandleNSSError(prerr, false);
[email protected]d100e44f2011-01-26 22:47:111680 net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
1681 make_scoped_refptr(new SSLErrorParams(rv, prerr)));
1682 return rv;
1683}
1684
1685void SSLClientSocketNSS::LogConnectionTypeMetrics() const {
1686 UpdateConnectionTypeHistograms(CONNECTION_SSL);
1687 if (server_cert_verify_result_->has_md5)
1688 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5);
1689 if (server_cert_verify_result_->has_md2)
1690 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2);
1691 if (server_cert_verify_result_->has_md4)
1692 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD4);
1693 if (server_cert_verify_result_->has_md5_ca)
1694 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5_CA);
1695 if (server_cert_verify_result_->has_md2_ca)
1696 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA);
1697 int ssl_version = SSLConnectionStatusToVersion(ssl_connection_status_);
1698 switch (ssl_version) {
1699 case SSL_CONNECTION_VERSION_SSL2:
1700 UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL2);
1701 break;
1702 case SSL_CONNECTION_VERSION_SSL3:
1703 UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL3);
1704 break;
1705 case SSL_CONNECTION_VERSION_TLS1:
1706 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1);
1707 break;
1708 case SSL_CONNECTION_VERSION_TLS1_1:
1709 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_1);
1710 break;
1711 case SSL_CONNECTION_VERSION_TLS1_2:
1712 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_2);
1713 break;
1714 };
1715}
1716
[email protected]8d371892011-04-12 19:46:271717// SaveSSLHostInfo saves the certificate chain of the connection so that we can
1718// start verification faster in the future.
1719void SSLClientSocketNSS::SaveSSLHostInfo() {
[email protected]d100e44f2011-01-26 22:47:111720 if (!ssl_host_info_.get())
1721 return;
1722
1723 // If the SSLHostInfo hasn't managed to load from disk yet then we can't save
1724 // anything.
1725 if (ssl_host_info_->WaitForDataReady(NULL) != OK)
1726 return;
1727
[email protected]d100e44f2011-01-26 22:47:111728 SSLHostInfo::State* state = ssl_host_info_->mutable_state();
1729
[email protected]d100e44f2011-01-26 22:47:111730 state->certs.clear();
1731 PeerCertificateChain certs(nss_fd_);
1732 for (unsigned i = 0; i < certs.size(); i++) {
1733 if (certs[i]->derCert.len > std::numeric_limits<uint16>::max())
1734 return;
1735
1736 state->certs.push_back(std::string(
1737 reinterpret_cast<char*>(certs[i]->derCert.data),
1738 certs[i]->derCert.len));
1739 }
1740
1741 ssl_host_info_->Persist();
1742}
1743
[email protected]d100e44f2011-01-26 22:47:111744void SSLClientSocketNSS::UncorkAfterTimeout() {
1745 corked_ = false;
1746 int nsent;
1747 do {
1748 nsent = BufferSend();
1749 } while (nsent > 0);
1750}
1751
[email protected]55ee0e52011-07-21 18:29:441752// Do as much network I/O as possible between the buffer and the
1753// transport socket. Return true if some I/O performed, false
1754// otherwise (error or ERR_IO_PENDING).
[email protected]d100e44f2011-01-26 22:47:111755bool SSLClientSocketNSS::DoTransportIO() {
1756 EnterFunction("");
1757 bool network_moved = false;
1758 if (nss_bufs_ != NULL) {
[email protected]55ee0e52011-07-21 18:29:441759 int rv;
1760 // Read and write as much data as we can. The loop is neccessary
1761 // because Write() may return synchronously.
1762 do {
1763 rv = BufferSend();
1764 if (rv > 0)
1765 network_moved = true;
1766 } while (rv > 0);
1767 if (BufferRecv() >= 0)
1768 network_moved = true;
[email protected]d100e44f2011-01-26 22:47:111769 }
1770 LeaveFunction(network_moved);
1771 return network_moved;
1772}
1773
1774// Return 0 for EOF,
1775// > 0 for bytes transferred immediately,
1776// < 0 for error (or the non-error ERR_IO_PENDING).
1777int SSLClientSocketNSS::BufferSend(void) {
1778 if (transport_send_busy_)
1779 return ERR_IO_PENDING;
1780
1781 EnterFunction("");
1782 const char* buf1;
1783 const char* buf2;
1784 unsigned int len1, len2;
1785 memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2);
1786 const unsigned int len = len1 + len2;
1787
1788 if (corked_ && len < kRecvBufferSize / 2)
1789 return 0;
1790
1791 int rv = 0;
1792 if (len) {
1793 scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
1794 memcpy(send_buffer->data(), buf1, len1);
1795 memcpy(send_buffer->data() + len1, buf2, len2);
1796 rv = transport_->socket()->Write(send_buffer, len,
1797 &buffer_send_callback_);
1798 if (rv == ERR_IO_PENDING) {
1799 transport_send_busy_ = true;
1800 } else {
1801 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
1802 }
1803 }
1804
1805 LeaveFunction(rv);
1806 return rv;
1807}
1808
1809void SSLClientSocketNSS::BufferSendComplete(int result) {
1810 EnterFunction(result);
[email protected]d100e44f2011-01-26 22:47:111811 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
1812 transport_send_busy_ = false;
1813 OnSendComplete(result);
1814 LeaveFunction("");
1815}
1816
1817int SSLClientSocketNSS::BufferRecv(void) {
1818 if (transport_recv_busy_) return ERR_IO_PENDING;
1819
1820 char *buf;
1821 int nb = memio_GetReadParams(nss_bufs_, &buf);
1822 EnterFunction(nb);
1823 int rv;
1824 if (!nb) {
1825 // buffer too full to read into, so no I/O possible at moment
1826 rv = ERR_IO_PENDING;
1827 } else {
1828 recv_buffer_ = new IOBuffer(nb);
1829 rv = transport_->socket()->Read(recv_buffer_, nb, &buffer_recv_callback_);
1830 if (rv == ERR_IO_PENDING) {
1831 transport_recv_busy_ = true;
1832 } else {
1833 if (rv > 0)
1834 memcpy(buf, recv_buffer_->data(), rv);
1835 memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
1836 recv_buffer_ = NULL;
1837 }
1838 }
1839 LeaveFunction(rv);
1840 return rv;
1841}
1842
1843void SSLClientSocketNSS::BufferRecvComplete(int result) {
1844 EnterFunction(result);
1845 if (result > 0) {
1846 char *buf;
1847 memio_GetReadParams(nss_bufs_, &buf);
1848 memcpy(buf, recv_buffer_->data(), result);
1849 }
1850 recv_buffer_ = NULL;
1851 memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
1852 transport_recv_busy_ = false;
1853 OnRecvComplete(result);
1854 LeaveFunction("");
1855}
1856
[email protected]83530b72011-02-05 04:53:131857int SSLClientSocketNSS::HandleNSSError(PRErrorCode nss_error,
1858 bool handshake_error) {
1859 int net_error = handshake_error ? MapNSSHandshakeError(nss_error) :
1860 MapNSSError(nss_error);
1861
1862#if defined(OS_WIN)
1863 // On Windows, a handle to the HCRYPTPROV is cached in the X509Certificate
1864 // os_cert_handle() as an optimization. However, if the certificate
1865 // private key is stored on a smart card, and the smart card is removed,
1866 // the cached HCRYPTPROV will not be able to obtain the HCRYPTKEY again,
1867 // preventing client certificate authentication. Because the
1868 // X509Certificate may outlive the individual SSLClientSocketNSS, due to
1869 // caching in X509Certificate, this failure ends up preventing client
1870 // certificate authentication with the same certificate for all future
1871 // attempts, even after the smart card has been re-inserted. By setting
1872 // the CERT_KEY_PROV_HANDLE_PROP_ID to NULL, the cached HCRYPTPROV will
1873 // typically be freed. This allows a new HCRYPTPROV to be obtained from
1874 // the certificate on the next attempt, which should succeed if the smart
1875 // card has been re-inserted, or will typically prompt the user to
1876 // re-insert the smart card if not.
1877 if ((net_error == ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY ||
1878 net_error == ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED) &&
1879 ssl_config_.send_client_cert && ssl_config_.client_cert) {
1880 CertSetCertificateContextProperty(
1881 ssl_config_.client_cert->os_cert_handle(),
1882 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
1883 }
1884#endif
1885
1886 return net_error;
1887}
1888
[email protected]bacff652009-03-31 17:50:331889// static
1890// NSS calls this if an incoming certificate needs to be verified.
[email protected]2345cc52009-06-04 09:18:471891// Do nothing but return SECSuccess.
1892// This is called only in full handshake mode.
1893// Peer certificate is retrieved in HandshakeCallback() later, which is called
1894// in full handshake mode or in resumption handshake mode.
[email protected]bacff652009-03-31 17:50:331895SECStatus SSLClientSocketNSS::OwnAuthCertHandler(void* arg,
1896 PRFileDesc* socket,
1897 PRBool checksig,
1898 PRBool is_server) {
[email protected]9ae2ee02010-09-08 16:41:141899#ifdef SSL_ENABLE_FALSE_START
1900 // In the event that we are False Starting this connection, we wish to send
1901 // out the Finished message and first application data record in the same
1902 // packet. This prevents non-determinism when talking to False Start
1903 // intolerant servers which, otherwise, might see the two messages in
1904 // different reads or not, depending on network conditions.
1905 PRBool false_start = 0;
1906 SECStatus rv = SSL_OptionGet(socket, SSL_ENABLE_FALSE_START, &false_start);
[email protected]79ba2d82010-11-05 14:07:461907 DCHECK_EQ(SECSuccess, rv);
1908
[email protected]30bd4e352011-07-01 16:22:271909 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg);
1910 CERTCertificate* cert = SSL_PeerCertificate(that->nss_fd_);
1911 if (cert) {
1912 char* common_name = CERT_GetCommonName(&cert->issuer);
1913 if (common_name) {
1914 if (false_start && strcmp(common_name, "ESET_RootSslCert") == 0)
1915 // ESET anti-virus is capable of intercepting HTTPS connections on
1916 // Windows. However, it is False Start intolerant and causes the
1917 // connections to hang forever. We detect ESET by the issuer of the
1918 // leaf certificate and set a flag to return a specific error, giving
1919 // the user instructions for reconfiguring ESET.
1920 that->eset_mitm_detected_ = true;
1921 if (strcmp(common_name,
1922 "Kaspersky Anti-Virus personal root certificate") == 0) {
1923 // Kaspersky has an unknown intolerance to our HTTPS handshakes and so
1924 // we detect and give a more helpful error message.
1925 that->kaspersky_mitm_detected_ = true;
[email protected]563cbcc62010-10-11 23:07:521926 }
[email protected]30bd4e352011-07-01 16:22:271927 if (false_start &&
1928 strcmp(common_name, "ContentWatch Root Certificate Authority") == 0) {
1929 // This is NetNanny. NetNanny are updating their product so we
1930 // silently disable False Start for now.
1931 rv = SSL_OptionSet(socket, SSL_ENABLE_FALSE_START, PR_FALSE);
1932 DCHECK_EQ(SECSuccess, rv);
1933 false_start = 0;
1934 }
1935 PORT_Free(common_name);
[email protected]563cbcc62010-10-11 23:07:521936 }
[email protected]30bd4e352011-07-01 16:22:271937 CERT_DestroyCertificate(cert);
1938 }
[email protected]79ba2d82010-11-05 14:07:461939
[email protected]30bd4e352011-07-01 16:22:271940 if (false_start && !that->handshake_callback_called_) {
1941 that->corked_ = true;
1942 that->uncork_timer_.Start(
1943 base::TimeDelta::FromMilliseconds(kCorkTimeoutMs),
1944 that, &SSLClientSocketNSS::UncorkAfterTimeout);
[email protected]9ae2ee02010-09-08 16:41:141945 }
1946#endif
1947
[email protected]2345cc52009-06-04 09:18:471948 // Tell NSS to not verify the certificate.
1949 return SECSuccess;
1950}
1951
[email protected]4a842342010-11-04 16:21:331952#if defined(NSS_PLATFORM_CLIENT_AUTH)
[email protected]2345cc52009-06-04 09:18:471953// static
[email protected]d84b3722009-10-15 21:23:371954// NSS calls this if a client certificate is needed.
[email protected]4a842342010-11-04 16:21:331955SECStatus SSLClientSocketNSS::PlatformClientAuthHandler(
[email protected]d84b3722009-10-15 21:23:371956 void* arg,
1957 PRFileDesc* socket,
1958 CERTDistNames* ca_names,
[email protected]4a842342010-11-04 16:21:331959 CERTCertList** result_certs,
1960 void** result_private_key) {
[email protected]d84b3722009-10-15 21:23:371961 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg);
1962
1963 that->client_auth_cert_needed_ = !that->ssl_config_.send_client_cert;
[email protected]1d583612010-03-12 17:47:141964#if defined(OS_WIN)
1965 if (that->ssl_config_.send_client_cert) {
[email protected]4a842342010-11-04 16:21:331966 if (that->ssl_config_.client_cert) {
1967 PCCERT_CONTEXT cert_context =
1968 that->ssl_config_.client_cert->os_cert_handle();
[email protected]39815a02011-02-05 04:47:151969 PCERT_KEY_CONTEXT key_context = reinterpret_cast<PCERT_KEY_CONTEXT>(
1970 PORT_ZAlloc(sizeof(CERT_KEY_CONTEXT)));
1971 if (!key_context)
1972 return SECFailure;
1973 key_context->cbSize = sizeof(*key_context);
[email protected]b493c0b92010-11-11 05:12:421974
[email protected]4a842342010-11-04 16:21:331975 BOOL must_free = FALSE;
1976 BOOL acquired_key = CryptAcquireCertificatePrivateKey(
[email protected]fbe693bf2011-02-06 02:28:161977 cert_context, CRYPT_ACQUIRE_CACHE_FLAG, NULL,
1978 &key_context->hCryptProv, &key_context->dwKeySpec, &must_free);
[email protected]39815a02011-02-05 04:47:151979 if (acquired_key && key_context->hCryptProv) {
1980 DCHECK_NE(key_context->dwKeySpec, CERT_NCRYPT_KEY_SPEC);
[email protected]4a842342010-11-04 16:21:331981
1982 // The certificate cache may have been updated/used, in which case,
1983 // duplicate the existing handle, since NSS will free it when no
1984 // longer in use.
1985 if (!must_free)
[email protected]39815a02011-02-05 04:47:151986 CryptContextAddRef(key_context->hCryptProv, NULL, 0);
[email protected]4a842342010-11-04 16:21:331987
1988 SECItem der_cert;
1989 der_cert.type = siDERCertBuffer;
1990 der_cert.data = cert_context->pbCertEncoded;
1991 der_cert.len = cert_context->cbCertEncoded;
1992
1993 // TODO(rsleevi): Error checking for NSS allocation errors.
1994 *result_certs = CERT_NewCertList();
1995 CERTCertDBHandle* db_handle = CERT_GetDefaultCertDB();
1996 CERTCertificate* user_cert = CERT_NewTempCertificate(
1997 db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE);
1998 CERT_AddCertToListTail(*result_certs, user_cert);
1999
2000 // Add the intermediates.
2001 X509Certificate::OSCertHandles intermediates =
2002 that->ssl_config_.client_cert->GetIntermediateCertificates();
2003 for (X509Certificate::OSCertHandles::const_iterator it =
2004 intermediates.begin(); it != intermediates.end(); ++it) {
2005 der_cert.data = (*it)->pbCertEncoded;
2006 der_cert.len = (*it)->cbCertEncoded;
2007
2008 CERTCertificate* intermediate = CERT_NewTempCertificate(
2009 db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE);
2010 CERT_AddCertToListTail(*result_certs, intermediate);
2011 }
[email protected]39815a02011-02-05 04:47:152012 *result_private_key = key_context;
[email protected]4a842342010-11-04 16:21:332013 return SECSuccess;
2014 }
[email protected]39815a02011-02-05 04:47:152015 PORT_Free(key_context);
[email protected]4a842342010-11-04 16:21:332016 LOG(WARNING) << "Client cert found without private key";
2017 }
[email protected]1d583612010-03-12 17:47:142018 // Send no client certificate.
2019 return SECFailure;
2020 }
2021
2022 that->client_certs_.clear();
2023
2024 std::vector<CERT_NAME_BLOB> issuer_list(ca_names->nnames);
2025 for (int i = 0; i < ca_names->nnames; ++i) {
2026 issuer_list[i].cbData = ca_names->names[i].len;
2027 issuer_list[i].pbData = ca_names->names[i].data;
2028 }
2029
2030 // Client certificates of the user are in the "MY" system certificate store.
2031 HCERTSTORE my_cert_store = CertOpenSystemStore(NULL, L"MY");
2032 if (!my_cert_store) {
2033 LOG(ERROR) << "Could not open the \"MY\" system certificate store: "
2034 << GetLastError();
2035 return SECFailure;
2036 }
2037
2038 // Enumerate the client certificates.
2039 CERT_CHAIN_FIND_BY_ISSUER_PARA find_by_issuer_para;
2040 memset(&find_by_issuer_para, 0, sizeof(find_by_issuer_para));
2041 find_by_issuer_para.cbSize = sizeof(find_by_issuer_para);
2042 find_by_issuer_para.pszUsageIdentifier = szOID_PKIX_KP_CLIENT_AUTH;
2043 find_by_issuer_para.cIssuer = ca_names->nnames;
2044 find_by_issuer_para.rgIssuer = ca_names->nnames ? &issuer_list[0] : NULL;
[email protected]01640f62010-08-10 19:42:122045 find_by_issuer_para.pfnFindCallback = ClientCertFindCallback;
[email protected]1d583612010-03-12 17:47:142046
2047 PCCERT_CHAIN_CONTEXT chain_context = NULL;
2048
2049 for (;;) {
2050 // Find a certificate chain.
2051 chain_context = CertFindChainInStore(my_cert_store,
2052 X509_ASN_ENCODING,
2053 0,
2054 CERT_CHAIN_FIND_BY_ISSUER,
2055 &find_by_issuer_para,
2056 chain_context);
2057 if (!chain_context) {
2058 DWORD err = GetLastError();
2059 if (err != CRYPT_E_NOT_FOUND)
2060 DLOG(ERROR) << "CertFindChainInStore failed: " << err;
2061 break;
2062 }
2063
2064 // Get the leaf certificate.
2065 PCCERT_CONTEXT cert_context =
2066 chain_context->rgpChain[0]->rgpElement[0]->pCertContext;
[email protected]40a089c2011-07-21 04:48:172067 // Copy it to our own certificate store, so that we can close the "MY"
2068 // certificate store before returning from this function.
[email protected]1d583612010-03-12 17:47:142069 PCCERT_CONTEXT cert_context2;
[email protected]40a089c2011-07-21 04:48:172070 BOOL ok = CertAddCertificateContextToStore(X509Certificate::cert_store(),
2071 cert_context,
[email protected]1d583612010-03-12 17:47:142072 CERT_STORE_ADD_USE_EXISTING,
2073 &cert_context2);
2074 if (!ok) {
2075 NOTREACHED();
2076 continue;
2077 }
[email protected]4a842342010-11-04 16:21:332078
2079 // Copy the rest of the chain to our own store as well. Copying the chain
2080 // stops gracefully if an error is encountered, with the partial chain
2081 // being used as the intermediates, rather than failing to consider the
2082 // client certificate.
2083 net::X509Certificate::OSCertHandles intermediates;
2084 for (DWORD i = 1; i < chain_context->rgpChain[0]->cElement; i++) {
2085 PCCERT_CONTEXT intermediate_copy;
[email protected]40a089c2011-07-21 04:48:172086 ok = CertAddCertificateContextToStore(X509Certificate::cert_store(),
2087 chain_context->rgpChain[0]->rgpElement[i]->pCertContext,
[email protected]4a842342010-11-04 16:21:332088 CERT_STORE_ADD_USE_EXISTING, &intermediate_copy);
2089 if (!ok) {
2090 NOTREACHED();
2091 break;
2092 }
2093 intermediates.push_back(intermediate_copy);
2094 }
2095
[email protected]1d583612010-03-12 17:47:142096 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle(
[email protected]72f508122011-07-19 05:12:172097 cert_context2, intermediates);
[email protected]1d583612010-03-12 17:47:142098 that->client_certs_.push_back(cert);
[email protected]4a842342010-11-04 16:21:332099
2100 X509Certificate::FreeOSCertHandle(cert_context2);
2101 for (net::X509Certificate::OSCertHandles::iterator it =
2102 intermediates.begin(); it != intermediates.end(); ++it) {
2103 net::X509Certificate::FreeOSCertHandle(*it);
2104 }
[email protected]1d583612010-03-12 17:47:142105 }
2106
2107 BOOL ok = CertCloseStore(my_cert_store, CERT_CLOSE_STORE_CHECK_FLAG);
2108 DCHECK(ok);
2109
2110 // Tell NSS to suspend the client authentication. We will then abort the
2111 // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
2112 return SECWouldBlock;
[email protected]3dd6f5e2010-06-01 20:28:032113#elif defined(OS_MACOSX)
[email protected]fd4f139f2010-06-11 17:02:202114 if (that->ssl_config_.send_client_cert) {
[email protected]4a842342010-11-04 16:21:332115 if (that->ssl_config_.client_cert) {
2116 OSStatus os_error = noErr;
2117 SecIdentityRef identity = NULL;
2118 SecKeyRef private_key = NULL;
2119 CFArrayRef chain =
2120 that->ssl_config_.client_cert->CreateClientCertificateChain();
2121 if (chain) {
2122 identity = reinterpret_cast<SecIdentityRef>(
2123 const_cast<void*>(CFArrayGetValueAtIndex(chain, 0)));
2124 }
2125 if (identity)
2126 os_error = SecIdentityCopyPrivateKey(identity, &private_key);
2127
2128 if (chain && identity && os_error == noErr) {
2129 // TODO(rsleevi): Error checking for NSS allocation errors.
2130 *result_certs = CERT_NewCertList();
[email protected]39815a02011-02-05 04:47:152131 *result_private_key = private_key;
[email protected]4a842342010-11-04 16:21:332132
2133 for (CFIndex i = 0; i < CFArrayGetCount(chain); ++i) {
2134 CSSM_DATA cert_data;
2135 SecCertificateRef cert_ref;
2136 if (i == 0) {
2137 cert_ref = that->ssl_config_.client_cert->os_cert_handle();
2138 } else {
2139 cert_ref = reinterpret_cast<SecCertificateRef>(
2140 const_cast<void*>(CFArrayGetValueAtIndex(chain, i)));
2141 }
2142 os_error = SecCertificateGetData(cert_ref, &cert_data);
2143 if (os_error != noErr)
2144 break;
2145
2146 SECItem der_cert;
2147 der_cert.type = siDERCertBuffer;
2148 der_cert.data = cert_data.Data;
2149 der_cert.len = cert_data.Length;
2150 CERTCertificate* nss_cert = CERT_NewTempCertificate(
2151 CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
2152 CERT_AddCertToListTail(*result_certs, nss_cert);
2153 }
2154 }
2155 if (os_error == noErr) {
2156 CFRelease(chain);
2157 return SECSuccess;
2158 }
2159 LOG(WARNING) << "Client cert found, but could not be used: "
2160 << os_error;
2161 if (*result_certs) {
2162 CERT_DestroyCertList(*result_certs);
2163 *result_certs = NULL;
2164 }
2165 if (*result_private_key)
2166 *result_private_key = NULL;
2167 if (private_key)
2168 CFRelease(private_key);
2169 if (chain)
2170 CFRelease(chain);
2171 }
[email protected]fd4f139f2010-06-11 17:02:202172 // Send no client certificate.
2173 return SECFailure;
2174 }
2175
2176 that->client_certs_.clear();
2177
2178 // First, get the cert issuer names allowed by the server.
2179 std::vector<CertPrincipal> valid_issuers;
2180 int n = ca_names->nnames;
2181 for (int i = 0; i < n; i++) {
2182 // Parse each name into a CertPrincipal object.
2183 CertPrincipal p;
2184 if (p.ParseDistinguishedName(ca_names->names[i].data,
2185 ca_names->names[i].len)) {
2186 valid_issuers.push_back(p);
2187 }
2188 }
2189
2190 // Now get the available client certs whose issuers are allowed by the server.
[email protected]4f4de7e62010-11-12 19:55:272191 X509Certificate::GetSSLClientCertificates(that->host_and_port_.host(),
[email protected]fd4f139f2010-06-11 17:02:202192 valid_issuers,
2193 &that->client_certs_);
2194
2195 // Tell NSS to suspend the client authentication. We will then abort the
2196 // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
2197 return SECWouldBlock;
[email protected]1d583612010-03-12 17:47:142198#else
[email protected]4a842342010-11-04 16:21:332199 return SECFailure;
2200#endif
2201}
2202
2203#else // NSS_PLATFORM_CLIENT_AUTH
2204
2205// static
2206// NSS calls this if a client certificate is needed.
2207// Based on Mozilla's NSS_GetClientAuthData.
2208SECStatus SSLClientSocketNSS::ClientAuthHandler(
2209 void* arg,
2210 PRFileDesc* socket,
2211 CERTDistNames* ca_names,
2212 CERTCertificate** result_certificate,
2213 SECKEYPrivateKey** result_private_key) {
2214 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg);
2215
2216 that->client_auth_cert_needed_ = !that->ssl_config_.send_client_cert;
[email protected]b8fee152009-10-24 03:39:312217 void* wincx = SSL_RevealPinArg(socket);
2218
[email protected]d84b3722009-10-15 21:23:372219 // Second pass: a client certificate should have been selected.
2220 if (that->ssl_config_.send_client_cert) {
2221 if (that->ssl_config_.client_cert) {
[email protected]701e8692010-08-17 20:00:432222 CERTCertificate* cert = CERT_DupCertificate(
[email protected]d84b3722009-10-15 21:23:372223 that->ssl_config_.client_cert->os_cert_handle());
[email protected]701e8692010-08-17 20:00:432224 SECKEYPrivateKey* privkey = PK11_FindKeyByAnyCert(cert, wincx);
[email protected]d84b3722009-10-15 21:23:372225 if (privkey) {
2226 // TODO(jsorianopastor): We should wait for server certificate
2227 // verification before sending our credentials. See
2228 // http://crbug.com/13934.
2229 *result_certificate = cert;
2230 *result_private_key = privkey;
2231 return SECSuccess;
2232 }
2233 LOG(WARNING) << "Client cert found without private key";
2234 }
2235 // Send no client certificate.
2236 return SECFailure;
2237 }
2238
[email protected]701e8692010-08-17 20:00:432239 // Iterate over all client certificates.
2240 CERTCertList* client_certs = CERT_FindUserCertsByUsage(
2241 CERT_GetDefaultCertDB(), certUsageSSLClient,
2242 PR_FALSE, PR_FALSE, wincx);
2243 if (client_certs) {
2244 for (CERTCertListNode* node = CERT_LIST_HEAD(client_certs);
2245 !CERT_LIST_END(node, client_certs);
2246 node = CERT_LIST_NEXT(node)) {
2247 // Only offer unexpired certificates.
2248 if (CERT_CheckCertValidTimes(node->cert, PR_Now(), PR_TRUE) !=
2249 secCertTimeValid)
[email protected]b8fee152009-10-24 03:39:312250 continue;
[email protected]701e8692010-08-17 20:00:432251 // Filter by issuer.
2252 //
2253 // TODO(davidben): This does a binary comparison of the DER-encoded
2254 // issuers. We should match according to RFC 5280 sec. 7.1. We should find
2255 // an appropriate NSS function or add one if needbe.
2256 if (ca_names->nnames &&
2257 NSS_CmpCertChainWCANames(node->cert, ca_names) != SECSuccess)
2258 continue;
2259 X509Certificate* x509_cert = X509Certificate::CreateFromHandle(
[email protected]72f508122011-07-19 05:12:172260 node->cert, net::X509Certificate::OSCertHandles());
[email protected]701e8692010-08-17 20:00:432261 that->client_certs_.push_back(x509_cert);
[email protected]b8fee152009-10-24 03:39:312262 }
[email protected]701e8692010-08-17 20:00:432263 CERT_DestroyCertList(client_certs);
[email protected]b8fee152009-10-24 03:39:312264 }
[email protected]d84b3722009-10-15 21:23:372265
[email protected]f6ee0a012010-03-05 22:00:242266 // Tell NSS to suspend the client authentication. We will then abort the
2267 // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
2268 return SECWouldBlock;
[email protected]d84b3722009-10-15 21:23:372269}
[email protected]4a842342010-11-04 16:21:332270#endif // NSS_PLATFORM_CLIENT_AUTH
[email protected]d84b3722009-10-15 21:23:372271
2272// static
[email protected]2345cc52009-06-04 09:18:472273// NSS calls this when handshake is completed.
2274// After the SSL handshake is finished, use CertVerifier to verify
2275// the saved server certificate.
2276void SSLClientSocketNSS::HandshakeCallback(PRFileDesc* socket,
2277 void* arg) {
[email protected]bacff652009-03-31 17:50:332278 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg);
2279
[email protected]7a8de3072010-10-01 16:25:542280 that->handshake_callback_called_ = true;
[email protected]39afe642010-04-29 14:55:182281
[email protected]2345cc52009-06-04 09:18:472282 that->UpdateServerCert();
[email protected]757f2e2b2010-10-27 23:28:352283 that->UpdateConnectionStatus();
[email protected]2345cc52009-06-04 09:18:472284}
[email protected]bacff652009-03-31 17:50:332285
[email protected]93c57682011-02-12 02:05:082286void SSLClientSocketNSS::EnsureThreadIdAssigned() const {
2287 base::AutoLock auto_lock(lock_);
2288 if (valid_thread_id_ != base::kInvalidThreadId)
2289 return;
2290 valid_thread_id_ = base::PlatformThread::CurrentId();
2291}
2292
2293bool SSLClientSocketNSS::CalledOnValidThread() const {
2294 EnsureThreadIdAssigned();
2295 base::AutoLock auto_lock(lock_);
2296 return valid_thread_id_ == base::PlatformThread::CurrentId();
2297}
2298
[email protected]b43c97c2008-10-22 19:50:582299} // namespace net