blob: 035007f116ef897ff6c987f920c1e7155f84d288 [file] [log] [blame]
[email protected]a2006ece2010-04-23 16:44:021// Copyright (c) 2010 The Chromium Authors. All rights reserved.
[email protected]b43c97c2008-10-22 19:50:582// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]e83ba1c42009-11-30 18:18:325// This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived
6// from AuthCertificateCallback() in
[email protected]bf0136d2009-05-29 05:55:047// mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp.
8
9/* ***** BEGIN LICENSE BLOCK *****
10 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
11 *
12 * The contents of this file are subject to the Mozilla Public License Version
13 * 1.1 (the "License"); you may not use this file except in compliance with
14 * the License. You may obtain a copy of the License at
15 * http://www.mozilla.org/MPL/
16 *
17 * Software distributed under the License is distributed on an "AS IS" basis,
18 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
19 * for the specific language governing rights and limitations under the
20 * License.
21 *
22 * The Original Code is the Netscape security libraries.
23 *
24 * The Initial Developer of the Original Code is
25 * Netscape Communications Corporation.
26 * Portions created by the Initial Developer are Copyright (C) 2000
27 * the Initial Developer. All Rights Reserved.
28 *
29 * Contributor(s):
30 * Ian McGreer <[email protected]>
31 * Javier Delgadillo <[email protected]>
32 * Kai Engert <[email protected]>
33 *
34 * Alternatively, the contents of this file may be used under the terms of
35 * either the GNU General Public License Version 2 or later (the "GPL"), or
36 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
37 * in which case the provisions of the GPL or the LGPL are applicable instead
38 * of those above. If you wish to allow use of your version of this file only
39 * under the terms of either the GPL or the LGPL, and not to allow others to
40 * use your version of this file under the terms of the MPL, indicate your
41 * decision by deleting the provisions above and replace them with the notice
42 * and other provisions required by the GPL or the LGPL. If you do not delete
43 * the provisions above, a recipient may use your version of this file under
44 * the terms of any one of the MPL, the GPL or the LGPL.
45 *
46 * ***** END LICENSE BLOCK ***** */
47
[email protected]f7984fc62009-06-22 23:26:4448#include "net/socket/ssl_client_socket_nss.h"
[email protected]b43c97c2008-10-22 19:50:5849
[email protected]829296f2010-01-27 02:58:0350#if defined(USE_SYSTEM_SSL)
51#include <dlfcn.h>
52#endif
[email protected]bf0136d2009-05-29 05:55:0453#include <certdb.h>
[email protected]b24713592010-08-11 19:50:0254#include <hasht.h>
[email protected]d84b3722009-10-15 21:23:3755#include <keyhi.h>
[email protected]b43c97c2008-10-22 19:50:5856#include <nspr.h>
57#include <nss.h>
[email protected]ea224582008-12-07 20:25:4658#include <secerr.h>
[email protected]b24713592010-08-11 19:50:0259#include <sechash.h>
[email protected]b43c97c2008-10-22 19:50:5860#include <ssl.h>
[email protected]ea224582008-12-07 20:25:4661#include <sslerr.h>
[email protected]b43c97c2008-10-22 19:50:5862#include <pk11pub.h>
[email protected]b43c97c2008-10-22 19:50:5863
[email protected]bacff652009-03-31 17:50:3364#include "base/compiler_specific.h"
[email protected]fc7de492010-07-12 14:49:0465#include "base/histogram.h"
[email protected]b43c97c2008-10-22 19:50:5866#include "base/logging.h"
[email protected]1b1a264a2010-01-14 22:36:3567#include "base/nss_util.h"
[email protected]829296f2010-01-27 02:58:0368#include "base/singleton.h"
[email protected]899c3e92010-08-28 15:53:5069#include "base/string_number_conversions.h"
[email protected]b43c97c2008-10-22 19:50:5870#include "base/string_util.h"
[email protected]ac9eec62010-02-20 18:50:3871#include "net/base/address_list.h"
[email protected]92d9cad2009-06-25 23:40:2472#include "net/base/cert_verifier.h"
[email protected]899c3e92010-08-28 15:53:5073#include "net/base/dnsrr_resolver.h"
[email protected]b24713592010-08-11 19:50:0274#include "net/base/dnssec_chain_verifier.h"
75#include "net/base/dns_util.h"
[email protected]597cf6e2009-05-29 09:43:2676#include "net/base/io_buffer.h"
[email protected]b43c97c2008-10-22 19:50:5877#include "net/base/net_errors.h"
[email protected]899c3e92010-08-28 15:53:5078#include "net/base/net_log.h"
[email protected]d84b3722009-10-15 21:23:3779#include "net/base/ssl_cert_request_info.h"
[email protected]fc7de492010-07-12 14:49:0480#include "net/base/ssl_connection_status_flags.h"
[email protected]b43c97c2008-10-22 19:50:5881#include "net/base/ssl_info.h"
[email protected]ac9eec62010-02-20 18:50:3882#include "net/base/sys_addrinfo.h"
[email protected]2a0c0a52009-07-31 07:51:3283#include "net/ocsp/nss_ocsp.h"
[email protected]e60e47a2010-07-14 03:37:1884#include "net/socket/client_socket_handle.h"
[email protected]b43c97c2008-10-22 19:50:5885
86static const int kRecvBufferSize = 4096;
87
[email protected]b43c97c2008-10-22 19:50:5888namespace net {
89
[email protected]e17b4c12008-11-05 22:04:0890// State machines are easier to debug if you log state transitions.
91// Enable these if you want to see what's going on.
92#if 1
93#define EnterFunction(x)
94#define LeaveFunction(x)
[email protected]a3ff5e92009-10-13 04:48:0695#define GotoState(s) next_handshake_state_ = s
[email protected]ea224582008-12-07 20:25:4696#define LogData(s, len)
[email protected]e17b4c12008-11-05 22:04:0897#else
98#define EnterFunction(x) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \
[email protected]a3ff5e92009-10-13 04:48:0699 " enter " << x << \
100 "; next_handshake_state " << next_handshake_state_
[email protected]e17b4c12008-11-05 22:04:08101#define LeaveFunction(x) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \
[email protected]a3ff5e92009-10-13 04:48:06102 " leave " << x << \
103 "; next_handshake_state " << next_handshake_state_
[email protected]e17b4c12008-11-05 22:04:08104#define GotoState(s) do { LOG(INFO) << (void *)this << " " << __FUNCTION__ << \
[email protected]a3ff5e92009-10-13 04:48:06105 " jump to state " << s; \
106 next_handshake_state_ = s; } while (0)
[email protected]ea224582008-12-07 20:25:46107#define LogData(s, len) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \
108 " data [" << std::string(s, len) << "]";
109
[email protected]e17b4c12008-11-05 22:04:08110#endif
111
[email protected]ea224582008-12-07 20:25:46112namespace {
113
[email protected]829296f2010-01-27 02:58:03114class NSSSSLInitSingleton {
115 public:
116 NSSSSLInitSingleton() {
117 base::EnsureNSSInit();
118
119 NSS_SetDomesticPolicy();
120
121#if defined(USE_SYSTEM_SSL)
122 // Use late binding to avoid scary but benign warning
123 // "Symbol `SSL_ImplementedCiphers' has different size in shared object,
124 // consider re-linking"
[email protected]4d3040f42010-04-14 02:40:20125 // TODO(wtc): Use the new SSL_GetImplementedCiphers and
126 // SSL_GetNumImplementedCiphers functions when we require NSS 3.12.6.
127 // See https://bugzilla.mozilla.org/show_bug.cgi?id=496993.
[email protected]829296f2010-01-27 02:58:03128 const PRUint16* pSSL_ImplementedCiphers = static_cast<const PRUint16*>(
129 dlsym(RTLD_DEFAULT, "SSL_ImplementedCiphers"));
130 if (pSSL_ImplementedCiphers == NULL) {
131 NOTREACHED() << "Can't get list of supported ciphers";
132 return;
133 }
134#else
135#define pSSL_ImplementedCiphers SSL_ImplementedCiphers
136#endif
137
138 // Explicitly enable exactly those ciphers with keys of at least 80 bits
139 for (int i = 0; i < SSL_NumImplementedCiphers; i++) {
140 SSLCipherSuiteInfo info;
141 if (SSL_GetCipherSuiteInfo(pSSL_ImplementedCiphers[i], &info,
142 sizeof(info)) == SECSuccess) {
143 SSL_CipherPrefSetDefault(pSSL_ImplementedCiphers[i],
144 (info.effectiveKeyBits >= 80));
145 }
146 }
147
148 // Enable SSL.
149 SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE);
150
151 // All other SSL options are set per-session by SSLClientSocket.
152 }
153
154 ~NSSSSLInitSingleton() {
155 // Have to clear the cache, or NSS_Shutdown fails with SEC_ERROR_BUSY.
156 SSL_ClearSessionCache();
157 }
158};
159
160// Initialize the NSS SSL library if it isn't already initialized. This must
161// be called before any other NSS SSL functions. This function is
162// thread-safe, and the NSS SSL library will only ever be initialized once.
163// The NSS SSL library will be properly shut down on program exit.
164void EnsureNSSSSLInit() {
165 Singleton<NSSSSLInitSingleton>::get();
166}
167
[email protected]2e9a5b6982010-01-15 22:29:03168// The default error mapping function.
169// Maps an NSPR error code to a network error code.
170int MapNSPRError(PRErrorCode err) {
[email protected]ea224582008-12-07 20:25:46171 // TODO(port): fill this out as we learn what's important
172 switch (err) {
173 case PR_WOULD_BLOCK_ERROR:
174 return ERR_IO_PENDING;
[email protected]b0735462009-11-04 22:11:26175 case PR_ADDRESS_NOT_SUPPORTED_ERROR: // For connect.
176 case PR_NO_ACCESS_RIGHTS_ERROR:
177 return ERR_ACCESS_DENIED;
178 case PR_IO_TIMEOUT_ERROR:
179 return ERR_TIMED_OUT;
180 case PR_CONNECT_RESET_ERROR:
181 return ERR_CONNECTION_RESET;
182 case PR_CONNECT_ABORTED_ERROR:
183 return ERR_CONNECTION_ABORTED;
184 case PR_CONNECT_REFUSED_ERROR:
185 return ERR_CONNECTION_REFUSED;
186 case PR_HOST_UNREACHABLE_ERROR:
187 case PR_NETWORK_UNREACHABLE_ERROR:
188 return ERR_ADDRESS_UNREACHABLE;
189 case PR_ADDRESS_NOT_AVAILABLE_ERROR:
190 return ERR_ADDRESS_INVALID;
[email protected]58f43332010-08-11 17:21:16191 case PR_INVALID_ARGUMENT_ERROR:
192 return ERR_INVALID_ARGUMENT;
193
194 case SEC_ERROR_INVALID_ARGS:
195 return ERR_INVALID_ARGUMENT;
[email protected]b0735462009-11-04 22:11:26196
[email protected]4d3040f42010-04-14 02:40:20197 case SSL_ERROR_SSL_DISABLED:
198 return ERR_NO_SSL_VERSIONS_ENABLED;
[email protected]ea224582008-12-07 20:25:46199 case SSL_ERROR_NO_CYPHER_OVERLAP:
[email protected]2e9a5b6982010-01-15 22:29:03200 case SSL_ERROR_UNSUPPORTED_VERSION:
[email protected]ea224582008-12-07 20:25:46201 return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
[email protected]d84b3722009-10-15 21:23:37202 case SSL_ERROR_HANDSHAKE_FAILURE_ALERT:
[email protected]4d3040f42010-04-14 02:40:20203 case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT:
204 case SSL_ERROR_ILLEGAL_PARAMETER_ALERT:
[email protected]d84b3722009-10-15 21:23:37205 return ERR_SSL_PROTOCOL_ERROR;
[email protected]aeaca1f2010-04-20 22:05:21206 case SSL_ERROR_DECOMPRESSION_FAILURE_ALERT:
207 return ERR_SSL_DECOMPRESSION_FAILURE_ALERT;
[email protected]0ed94682010-05-18 15:09:00208 case SSL_ERROR_BAD_MAC_ALERT:
209 return ERR_SSL_BAD_RECORD_MAC_ALERT;
[email protected]d102f542010-06-30 14:51:05210 case SSL_ERROR_UNSAFE_NEGOTIATION:
211 return ERR_SSL_UNSAFE_NEGOTIATION;
[email protected]e7bad86e2010-08-17 00:56:40212 case SSL_ERROR_WEAK_SERVER_KEY:
[email protected]b9a3dc32010-08-30 16:44:23213 return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY;
[email protected]ea224582008-12-07 20:25:46214
215 default: {
216 if (IS_SSL_ERROR(err)) {
217 LOG(WARNING) << "Unknown SSL error " << err <<
218 " mapped to net::ERR_SSL_PROTOCOL_ERROR";
219 return ERR_SSL_PROTOCOL_ERROR;
220 }
[email protected]ea224582008-12-07 20:25:46221 LOG(WARNING) << "Unknown error " << err <<
222 " mapped to net::ERR_FAILED";
223 return ERR_FAILED;
224 }
225 }
226}
227
[email protected]2e9a5b6982010-01-15 22:29:03228// Context-sensitive error mapping functions.
229
230int MapHandshakeError(PRErrorCode err) {
231 switch (err) {
232 // If the server closed on us, it is a protocol error.
233 // Some TLS-intolerant servers do this when we request TLS.
234 case PR_END_OF_FILE_ERROR:
235 // The handshake may fail because some signature (for example, the
236 // signature in the ServerKeyExchange message for an ephemeral
237 // Diffie-Hellman cipher suite) is invalid.
238 case SEC_ERROR_BAD_SIGNATURE:
239 return ERR_SSL_PROTOCOL_ERROR;
240 default:
241 return MapNSPRError(err);
242 }
243}
244
[email protected]37a0b112010-05-08 02:23:46245#if defined(OS_WIN)
246
247// A certificate for COMODO EV SGC CA, issued by AddTrust External CA Root,
248// causes CertGetCertificateChain to report CERT_TRUST_IS_NOT_VALID_FOR_USAGE.
249// It seems to be caused by the szOID_APPLICATION_CERT_POLICIES extension in
250// that certificate.
251//
252// This function is used in the workaround for http://crbug.com/43538
253bool IsProblematicComodoEVCACert(const CERTCertificate& cert) {
254 // Issuer:
255 // CN = AddTrust External CA Root
256 // OU = AddTrust External TTP Network
257 // O = AddTrust AB
258 // C = SE
259 static const uint8 kIssuer[] = {
260 0x30, 0x6f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
261 0x06, 0x13, 0x02, 0x53, 0x45, 0x31, 0x14, 0x30, 0x12, 0x06,
262 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x64, 0x64, 0x54,
263 0x72, 0x75, 0x73, 0x74, 0x20, 0x41, 0x42, 0x31, 0x26, 0x30,
264 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1d, 0x41, 0x64,
265 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x78, 0x74,
266 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x54, 0x54, 0x50, 0x20,
267 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31, 0x22, 0x30,
268 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x41, 0x64,
269 0x64, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x78, 0x74,
270 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x43, 0x41, 0x20, 0x52,
271 0x6f, 0x6f, 0x74
272 };
273
274 // Serial number: 79:0A:83:4D:48:40:6B:AB:6C:35:2A:D5:1F:42:83:FE.
275 static const uint8 kSerialNumber[] = {
276 0x79, 0x0a, 0x83, 0x4d, 0x48, 0x40, 0x6b, 0xab, 0x6c, 0x35,
277 0x2a, 0xd5, 0x1f, 0x42, 0x83, 0xfe
278 };
279
280 return cert.derIssuer.len == sizeof(kIssuer) &&
281 memcmp(cert.derIssuer.data, kIssuer, cert.derIssuer.len) == 0 &&
282 cert.serialNumber.len == sizeof(kSerialNumber) &&
283 memcmp(cert.serialNumber.data, kSerialNumber,
284 cert.serialNumber.len) == 0;
285}
286
[email protected]01640f62010-08-10 19:42:12287// This callback is intended to be used with CertFindChainInStore. In addition
288// to filtering by extended/enhanced key usage, we do not show expired
289// certificates and require digital signature usage in the key usage
290// extension.
291//
292// This matches our behavior on Mac OS X and that of NSS. It also matches the
293// default behavior of IE8. See http://support.microsoft.com/kb/890326 and
294// 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
295BOOL WINAPI ClientCertFindCallback(PCCERT_CONTEXT cert_context,
296 void* find_arg) {
297 LOG(INFO) << "Calling ClientCertFindCallback from _nss";
298 // Verify the certificate's KU is good.
299 BYTE key_usage;
300 if (CertGetIntendedKeyUsage(X509_ASN_ENCODING, cert_context->pCertInfo,
301 &key_usage, 1)) {
302 if (!(key_usage & CERT_DIGITAL_SIGNATURE_KEY_USAGE))
303 return FALSE;
304 } else {
305 DWORD err = GetLastError();
306 // If |err| is non-zero, it's an actual error. Otherwise the extension
307 // just isn't present, and we treat it as if everything was allowed.
308 if (err) {
309 DLOG(ERROR) << "CertGetIntendedKeyUsage failed: " << err;
310 return FALSE;
311 }
312 }
313
314 // Verify the current time is within the certificate's validity period.
315 if (CertVerifyTimeValidity(NULL, cert_context->pCertInfo) != 0)
316 return FALSE;
317
318 return TRUE;
319}
320
[email protected]37a0b112010-05-08 02:23:46321#endif
322
[email protected]ea224582008-12-07 20:25:46323} // namespace
324
[email protected]f505a9b2010-01-28 19:44:02325#if defined(OS_WIN)
326// static
327HCERTSTORE SSLClientSocketNSS::cert_store_ = NULL;
328#endif
[email protected]b43c97c2008-10-22 19:50:58329
[email protected]e60e47a2010-07-14 03:37:18330SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket,
[email protected]b43c97c2008-10-22 19:50:58331 const std::string& hostname,
332 const SSLConfig& ssl_config)
[email protected]f505a9b2010-01-28 19:44:02333 : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_(
334 this, &SSLClientSocketNSS::BufferSendComplete)),
335 ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_(
336 this, &SSLClientSocketNSS::BufferRecvComplete)),
[email protected]b43c97c2008-10-22 19:50:58337 transport_send_busy_(false),
338 transport_recv_busy_(false),
[email protected]9ae2ee02010-09-08 16:41:14339 corked_(false),
[email protected]f505a9b2010-01-28 19:44:02340 ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_(
341 this, &SSLClientSocketNSS::OnHandshakeIOComplete)),
[email protected]b43c97c2008-10-22 19:50:58342 transport_(transport_socket),
343 hostname_(hostname),
344 ssl_config_(ssl_config),
[email protected]a6eb576292009-06-30 16:19:00345 user_connect_callback_(NULL),
[email protected]a3ff5e92009-10-13 04:48:06346 user_read_callback_(NULL),
347 user_write_callback_(NULL),
348 user_read_buf_len_(0),
349 user_write_buf_len_(0),
[email protected]f505a9b2010-01-28 19:44:02350 server_cert_nss_(NULL),
[email protected]d84b3722009-10-15 21:23:37351 client_auth_cert_needed_(false),
[email protected]39afe642010-04-29 14:55:18352 handshake_callback_called_(false),
[email protected]b43c97c2008-10-22 19:50:58353 completed_handshake_(false),
[email protected]899c3e92010-08-28 15:53:50354 dnssec_provider_(NULL),
[email protected]a3ff5e92009-10-13 04:48:06355 next_handshake_state_(STATE_NONE),
[email protected]b43c97c2008-10-22 19:50:58356 nss_fd_(NULL),
[email protected]a2006ece2010-04-23 16:44:02357 nss_bufs_(NULL),
[email protected]e60e47a2010-07-14 03:37:18358 net_log_(transport_socket->socket()->NetLog()) {
[email protected]e17b4c12008-11-05 22:04:08359 EnterFunction("");
[email protected]b43c97c2008-10-22 19:50:58360}
361
362SSLClientSocketNSS::~SSLClientSocketNSS() {
[email protected]e17b4c12008-11-05 22:04:08363 EnterFunction("");
[email protected]b43c97c2008-10-22 19:50:58364 Disconnect();
[email protected]e17b4c12008-11-05 22:04:08365 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:58366}
367
368int SSLClientSocketNSS::Init() {
[email protected]e17b4c12008-11-05 22:04:08369 EnterFunction("");
[email protected]829296f2010-01-27 02:58:03370 // Initialize the NSS SSL library in a threadsafe way. This also
371 // initializes the NSS base library.
372 EnsureNSSSSLInit();
[email protected]dbc13b52010-04-16 00:59:56373 if (!NSS_IsInitialized())
374 return ERR_UNEXPECTED;
[email protected]3dd6f5e2010-06-01 20:28:03375#if !defined(OS_MACOSX) && !defined(OS_WIN)
[email protected]2a0c0a52009-07-31 07:51:32376 // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop
377 // by MessageLoopForIO::current().
378 // X509Certificate::Verify() runs on a worker thread of CertVerifier.
379 EnsureOCSPInit();
[email protected]f505a9b2010-01-28 19:44:02380#endif
[email protected]b43c97c2008-10-22 19:50:58381
[email protected]e17b4c12008-11-05 22:04:08382 LeaveFunction("");
383 return OK;
[email protected]b43c97c2008-10-22 19:50:58384}
385
[email protected]a2006ece2010-04-23 16:44:02386int SSLClientSocketNSS::Connect(CompletionCallback* callback) {
[email protected]e17b4c12008-11-05 22:04:08387 EnterFunction("");
[email protected]b43c97c2008-10-22 19:50:58388 DCHECK(transport_.get());
[email protected]a3ff5e92009-10-13 04:48:06389 DCHECK(next_handshake_state_ == STATE_NONE);
390 DCHECK(!user_read_callback_);
391 DCHECK(!user_write_callback_);
[email protected]a6eb576292009-06-30 16:19:00392 DCHECK(!user_connect_callback_);
[email protected]a3ff5e92009-10-13 04:48:06393 DCHECK(!user_read_buf_);
394 DCHECK(!user_write_buf_);
[email protected]b43c97c2008-10-22 19:50:58395
[email protected]ec11be62010-04-28 19:28:09396 net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT, NULL);
[email protected]5a05c47a2009-11-02 23:25:19397
[email protected]dbc13b52010-04-16 00:59:56398 int rv = Init();
399 if (rv != OK) {
[email protected]ec11be62010-04-28 19:28:09400 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
[email protected]dbc13b52010-04-16 00:59:56401 return rv;
[email protected]0ef0bcf2009-04-03 20:39:43402 }
403
[email protected]dbc13b52010-04-16 00:59:56404 rv = InitializeSSLOptions();
[email protected]5a05c47a2009-11-02 23:25:19405 if (rv != OK) {
[email protected]ec11be62010-04-28 19:28:09406 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
[email protected]5a05c47a2009-11-02 23:25:19407 return rv;
408 }
409
410 GotoState(STATE_HANDSHAKE);
411 rv = DoHandshakeLoop(OK);
412 if (rv == ERR_IO_PENDING) {
413 user_connect_callback_ = callback;
[email protected]5a05c47a2009-11-02 23:25:19414 } else {
[email protected]ec11be62010-04-28 19:28:09415 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
[email protected]5a05c47a2009-11-02 23:25:19416 }
417
418 LeaveFunction("");
419 return rv > OK ? OK : rv;
420}
421
422int SSLClientSocketNSS::InitializeSSLOptions() {
[email protected]0ef0bcf2009-04-03 20:39:43423 // Transport connected, now hook it up to nss
424 // TODO(port): specify rx and tx buffer sizes separately
425 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize);
426 if (nss_fd_ == NULL) {
[email protected]38a18722009-12-04 00:09:04427 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code.
[email protected]0ef0bcf2009-04-03 20:39:43428 }
429
430 // Tell NSS who we're connected to
[email protected]ac9eec62010-02-20 18:50:38431 AddressList peer_address;
[email protected]e60e47a2010-07-14 03:37:18432 int err = transport_->socket()->GetPeerAddress(&peer_address);
[email protected]ac9eec62010-02-20 18:50:38433 if (err != OK)
434 return err;
[email protected]f32c1732010-03-31 05:12:02435
[email protected]ac9eec62010-02-20 18:50:38436 const struct addrinfo* ai = peer_address.head();
[email protected]f32c1732010-03-31 05:12:02437
438 PRNetAddr peername;
439 memset(&peername, 0, sizeof(peername));
440 DCHECK_LE(ai->ai_addrlen, sizeof(peername));
441 size_t len = std::min(static_cast<size_t>(ai->ai_addrlen), sizeof(peername));
442 memcpy(&peername, ai->ai_addr, len);
443
444 // Adjust the address family field for BSD, whose sockaddr
445 // structure has a one-byte length and one-byte address family
446 // field at the beginning. PRNetAddr has a two-byte address
447 // family field at the beginning.
448 peername.raw.family = ai->ai_addr->sa_family;
449
450 memio_SetPeerName(nss_fd_, &peername);
[email protected]0ef0bcf2009-04-03 20:39:43451
452 // Grab pointer to buffers
453 nss_bufs_ = memio_GetSecret(nss_fd_);
454
455 /* Create SSL state machine */
456 /* Push SSL onto our fake I/O socket */
457 nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
458 if (nss_fd_ == NULL) {
[email protected]38a18722009-12-04 00:09:04459 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR/NSS error code.
[email protected]0ef0bcf2009-04-03 20:39:43460 }
461 // TODO(port): set more ssl options! Check errors!
462
463 int rv;
464
465 rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
466 if (rv != SECSuccess)
467 return ERR_UNEXPECTED;
468
469 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, ssl_config_.ssl2_enabled);
470 if (rv != SECSuccess)
471 return ERR_UNEXPECTED;
472
473 // SNI is enabled automatically if TLS is enabled -- as long as
474 // SSL_V2_COMPATIBLE_HELLO isn't.
475 // So don't do V2 compatible hellos unless we're really using SSL2,
476 // to avoid errors like
477 // "common name `mail.google.com' != requested host name `gmail.com'"
478 rv = SSL_OptionSet(nss_fd_, SSL_V2_COMPATIBLE_HELLO,
479 ssl_config_.ssl2_enabled);
480 if (rv != SECSuccess)
481 return ERR_UNEXPECTED;
482
483 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL3, ssl_config_.ssl3_enabled);
484 if (rv != SECSuccess)
485 return ERR_UNEXPECTED;
486
487 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_TLS, ssl_config_.tls1_enabled);
488 if (rv != SECSuccess)
489 return ERR_UNEXPECTED;
490
491#ifdef SSL_ENABLE_SESSION_TICKETS
492 // Support RFC 5077
493 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
494 if (rv != SECSuccess)
495 LOG(INFO) << "SSL_ENABLE_SESSION_TICKETS failed. Old system nss?";
496#else
497 #error "You need to install NSS-3.12 or later to build chromium"
498#endif
499
[email protected]7e52ed72009-11-17 00:40:12500#ifdef SSL_ENABLE_DEFLATE
[email protected]074c1582010-01-08 21:38:28501 // Some web servers have been found to break if TLS is used *or* if DEFLATE
502 // is advertised. Thus, if TLS is disabled (probably because we are doing
503 // SSLv3 fallback), we disable DEFLATE also.
504 // See http://crbug.com/31628
505 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_DEFLATE, ssl_config_.tls1_enabled);
[email protected]7e52ed72009-11-17 00:40:12506 if (rv != SECSuccess)
507 LOG(INFO) << "SSL_ENABLE_DEFLATE failed. Old system nss?";
508#endif
509
[email protected]c2def1c2010-03-02 21:40:34510#ifdef SSL_ENABLE_FALSE_START
[email protected]a0deaecf2010-08-18 23:39:52511 rv = SSL_OptionSet(
512 nss_fd_, SSL_ENABLE_FALSE_START,
513 ssl_config_.false_start_enabled &&
514 !SSLConfigService::IsKnownFalseStartIncompatibleServer(hostname_));
[email protected]c2def1c2010-03-02 21:40:34515 if (rv != SECSuccess)
[email protected]a0deaecf2010-08-18 23:39:52516 LOG(INFO) << "SSL_ENABLE_FALSE_START failed. Old system nss?";
[email protected]c2def1c2010-03-02 21:40:34517#endif
518
[email protected]33b3eb92010-01-06 01:35:04519#ifdef SSL_ENABLE_RENEGOTIATION
[email protected]304b0e352010-09-13 18:10:08520 // Deliberately disable this check for now: http://crbug.com/55410
521 if (false &&
522 SSLConfigService::IsKnownStrictTLSServer(hostname_) &&
[email protected]944a0a12010-08-19 20:02:28523 !ssl_config_.mitm_proxies_allowed) {
[email protected]d102f542010-06-30 14:51:05524 rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_SAFE_NEGOTIATION, PR_TRUE);
525 if (rv != SECSuccess)
526 LOG(INFO) << "SSL_REQUIRE_SAFE_NEGOTIATION failed.";
527 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_RENEGOTIATION,
528 SSL_RENEGOTIATE_REQUIRES_XTN);
529 } else {
530 // We allow servers to request renegotiation. Since we're a client,
531 // prohibiting this is rather a waste of time. Only servers are in a
532 // position to prevent renegotiation attacks.
533 // http://extendedsubset.com/?p=8
534
535 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_RENEGOTIATION,
[email protected]e7bad86e2010-08-17 00:56:40536 SSL_RENEGOTIATE_TRANSITIONAL);
[email protected]d102f542010-06-30 14:51:05537 }
[email protected]33b3eb92010-01-06 01:35:04538 if (rv != SECSuccess)
539 LOG(INFO) << "SSL_ENABLE_RENEGOTIATION failed.";
[email protected]d102f542010-06-30 14:51:05540#endif // SSL_ENABLE_RENEGOTIATION
[email protected]33b3eb92010-01-06 01:35:04541
[email protected]644bdca2009-11-30 20:40:53542#ifdef SSL_NEXT_PROTO_NEGOTIATED
543 if (!ssl_config_.next_protos.empty()) {
544 rv = SSL_SetNextProtoNego(
545 nss_fd_,
546 reinterpret_cast<const unsigned char *>(ssl_config_.next_protos.data()),
547 ssl_config_.next_protos.size());
548 if (rv != SECSuccess)
549 LOG(INFO) << "SSL_SetNextProtoNego failed.";
550 }
551#endif
552
[email protected]0ef0bcf2009-04-03 20:39:43553 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
554 if (rv != SECSuccess)
555 return ERR_UNEXPECTED;
556
557 rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
558 if (rv != SECSuccess)
559 return ERR_UNEXPECTED;
560
[email protected]d84b3722009-10-15 21:23:37561 rv = SSL_GetClientAuthDataHook(nss_fd_, ClientAuthHandler, this);
562 if (rv != SECSuccess)
563 return ERR_UNEXPECTED;
564
[email protected]2345cc52009-06-04 09:18:47565 rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
[email protected]0ef0bcf2009-04-03 20:39:43566 if (rv != SECSuccess)
[email protected]2345cc52009-06-04 09:18:47567 return ERR_UNEXPECTED;
[email protected]0ef0bcf2009-04-03 20:39:43568
569 // Tell SSL the hostname we're trying to connect to.
570 SSL_SetURL(nss_fd_, hostname_.c_str());
571
[email protected]52c27fb2009-11-30 22:40:23572 // Set the peer ID for session reuse. This is necessary when we create an
573 // SSL tunnel through a proxy -- GetPeerName returns the proxy's address
574 // rather than the destination server's address in that case.
[email protected]ac9eec62010-02-20 18:50:38575 // TODO(wtc): port in |peer_address| is not the server's port when a proxy is
576 // used.
[email protected]52c27fb2009-11-30 22:40:23577 std::string peer_id = StringPrintf("%s:%d", hostname_.c_str(),
[email protected]ac9eec62010-02-20 18:50:38578 peer_address.GetPort());
[email protected]52c27fb2009-11-30 22:40:23579 rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str()));
580 if (rv != SECSuccess)
581 LOG(INFO) << "SSL_SetSockPeerID failed: peer_id=" << peer_id;
582
[email protected]0ef0bcf2009-04-03 20:39:43583 // Tell SSL we're a client; needed if not letting NSPR do socket I/O
584 SSL_ResetHandshake(nss_fd_, 0);
585
[email protected]5a05c47a2009-11-02 23:25:19586 return OK;
[email protected]b43c97c2008-10-22 19:50:58587}
588
[email protected]bacff652009-03-31 17:50:33589void SSLClientSocketNSS::InvalidateSessionIfBadCertificate() {
590 if (UpdateServerCert() != NULL &&
[email protected]127017872009-08-13 17:54:42591 ssl_config_.IsAllowedBadCert(server_cert_)) {
[email protected]bacff652009-03-31 17:50:33592 SSL_InvalidateSession(nss_fd_);
593 }
[email protected]b43c97c2008-10-22 19:50:58594}
595
596void SSLClientSocketNSS::Disconnect() {
[email protected]e17b4c12008-11-05 22:04:08597 EnterFunction("");
[email protected]bacff652009-03-31 17:50:33598
[email protected]b43c97c2008-10-22 19:50:58599 // TODO(wtc): Send SSL close_notify alert.
600 if (nss_fd_ != NULL) {
[email protected]bacff652009-03-31 17:50:33601 InvalidateSessionIfBadCertificate();
[email protected]b43c97c2008-10-22 19:50:58602 PR_Close(nss_fd_);
603 nss_fd_ = NULL;
604 }
[email protected]bacff652009-03-31 17:50:33605
[email protected]92d9cad2009-06-25 23:40:24606 // Shut down anything that may call us back (through buffer_send_callback_,
[email protected]a3ff5e92009-10-13 04:48:06607 // buffer_recv_callback, or handshake_io_callback_).
[email protected]92d9cad2009-06-25 23:40:24608 verifier_.reset();
[email protected]e60e47a2010-07-14 03:37:18609 transport_->socket()->Disconnect();
[email protected]bf0136d2009-05-29 05:55:04610
611 // Reset object state
[email protected]a6eb576292009-06-30 16:19:00612 transport_send_busy_ = false;
613 transport_recv_busy_ = false;
614 user_connect_callback_ = NULL;
[email protected]a3ff5e92009-10-13 04:48:06615 user_read_callback_ = NULL;
616 user_write_callback_ = NULL;
617 user_read_buf_ = NULL;
618 user_read_buf_len_ = 0;
619 user_write_buf_ = NULL;
620 user_write_buf_len_ = 0;
[email protected]a6eb576292009-06-30 16:19:00621 server_cert_ = NULL;
[email protected]f505a9b2010-01-28 19:44:02622 if (server_cert_nss_) {
623 CERT_DestroyCertificate(server_cert_nss_);
624 server_cert_nss_ = NULL;
625 }
[email protected]2345cc52009-06-04 09:18:47626 server_cert_verify_result_.Reset();
[email protected]a6eb576292009-06-30 16:19:00627 completed_handshake_ = false;
628 nss_bufs_ = NULL;
[email protected]b8fee152009-10-24 03:39:31629 client_certs_.clear();
[email protected]d84b3722009-10-15 21:23:37630 client_auth_cert_needed_ = false;
[email protected]bf0136d2009-05-29 05:55:04631
[email protected]e17b4c12008-11-05 22:04:08632 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:58633}
634
635bool SSLClientSocketNSS::IsConnected() const {
[email protected]b2197852009-02-19 23:27:33636 // Ideally, we should also check if we have received the close_notify alert
637 // message from the server, and return false in that case. We're not doing
638 // that, so this function may return a false positive. Since the upper
639 // layer (HttpNetworkTransaction) needs to handle a persistent connection
640 // closed by the server when we send a request anyway, a false positive in
641 // exchange for simpler code is a good trade-off.
[email protected]e17b4c12008-11-05 22:04:08642 EnterFunction("");
[email protected]e60e47a2010-07-14 03:37:18643 bool ret = completed_handshake_ && transport_->socket()->IsConnected();
[email protected]e17b4c12008-11-05 22:04:08644 LeaveFunction("");
645 return ret;
[email protected]b43c97c2008-10-22 19:50:58646}
647
[email protected]b2197852009-02-19 23:27:33648bool SSLClientSocketNSS::IsConnectedAndIdle() const {
649 // Unlike IsConnected, this method doesn't return a false positive.
650 //
651 // Strictly speaking, we should check if we have received the close_notify
652 // alert message from the server, and return false in that case. Although
653 // the close_notify alert message means EOF in the SSL layer, it is just
[email protected]e60e47a2010-07-14 03:37:18654 // bytes to the transport layer below, so
655 // transport_->socket()->IsConnectedAndIdle() returns the desired false
656 // when we receive close_notify.
[email protected]b2197852009-02-19 23:27:33657 EnterFunction("");
[email protected]e60e47a2010-07-14 03:37:18658 bool ret = completed_handshake_ && transport_->socket()->IsConnectedAndIdle();
[email protected]b2197852009-02-19 23:27:33659 LeaveFunction("");
660 return ret;
661}
662
[email protected]ac9eec62010-02-20 18:50:38663int SSLClientSocketNSS::GetPeerAddress(AddressList* address) const {
[email protected]e60e47a2010-07-14 03:37:18664 return transport_->socket()->GetPeerAddress(address);
[email protected]9f864b32010-01-20 15:01:16665}
666
[email protected]9b5614a2010-08-25 20:29:45667void SSLClientSocketNSS::SetSubresourceSpeculation() {
668 if (transport_.get() && transport_->socket()) {
669 transport_->socket()->SetSubresourceSpeculation();
670 } else {
671 NOTREACHED();
672 }
673}
674
675void SSLClientSocketNSS::SetOmniboxSpeculation() {
676 if (transport_.get() && transport_->socket()) {
677 transport_->socket()->SetOmniboxSpeculation();
678 } else {
679 NOTREACHED();
680 }
681}
682
[email protected]0f873e82010-09-02 16:09:01683bool SSLClientSocketNSS::WasEverUsed() const {
684 if (transport_.get() && transport_->socket()) {
685 return transport_->socket()->WasEverUsed();
686 }
687 NOTREACHED();
688 return false;
689}
690
[email protected]ffeb0882009-04-30 21:51:25691int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len,
[email protected]ea224582008-12-07 20:25:46692 CompletionCallback* callback) {
[email protected]e17b4c12008-11-05 22:04:08693 EnterFunction(buf_len);
[email protected]b43c97c2008-10-22 19:50:58694 DCHECK(completed_handshake_);
[email protected]a3ff5e92009-10-13 04:48:06695 DCHECK(next_handshake_state_ == STATE_NONE);
696 DCHECK(!user_read_callback_);
[email protected]a6eb576292009-06-30 16:19:00697 DCHECK(!user_connect_callback_);
[email protected]a3ff5e92009-10-13 04:48:06698 DCHECK(!user_read_buf_);
699 DCHECK(nss_bufs_);
[email protected]b43c97c2008-10-22 19:50:58700
[email protected]a3ff5e92009-10-13 04:48:06701 user_read_buf_ = buf;
702 user_read_buf_len_ = buf_len;
[email protected]b43c97c2008-10-22 19:50:58703
[email protected]a3ff5e92009-10-13 04:48:06704 int rv = DoReadLoop(OK);
705
[email protected]1d583612010-03-12 17:47:14706 if (rv == ERR_IO_PENDING) {
[email protected]a3ff5e92009-10-13 04:48:06707 user_read_callback_ = callback;
[email protected]1d583612010-03-12 17:47:14708 } else {
[email protected]a3ff5e92009-10-13 04:48:06709 user_read_buf_ = NULL;
710 user_read_buf_len_ = 0;
711 }
[email protected]ea224582008-12-07 20:25:46712 LeaveFunction(rv);
[email protected]b43c97c2008-10-22 19:50:58713 return rv;
714}
715
[email protected]ffeb0882009-04-30 21:51:25716int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len,
[email protected]a3ff5e92009-10-13 04:48:06717 CompletionCallback* callback) {
[email protected]e17b4c12008-11-05 22:04:08718 EnterFunction(buf_len);
[email protected]b43c97c2008-10-22 19:50:58719 DCHECK(completed_handshake_);
[email protected]a3ff5e92009-10-13 04:48:06720 DCHECK(next_handshake_state_ == STATE_NONE);
721 DCHECK(!user_write_callback_);
[email protected]a6eb576292009-06-30 16:19:00722 DCHECK(!user_connect_callback_);
[email protected]a3ff5e92009-10-13 04:48:06723 DCHECK(!user_write_buf_);
724 DCHECK(nss_bufs_);
[email protected]b43c97c2008-10-22 19:50:58725
[email protected]a3ff5e92009-10-13 04:48:06726 user_write_buf_ = buf;
727 user_write_buf_len_ = buf_len;
[email protected]b43c97c2008-10-22 19:50:58728
[email protected]9ae2ee02010-09-08 16:41:14729 corked_ = false;
[email protected]a3ff5e92009-10-13 04:48:06730 int rv = DoWriteLoop(OK);
731
[email protected]1d583612010-03-12 17:47:14732 if (rv == ERR_IO_PENDING) {
[email protected]a3ff5e92009-10-13 04:48:06733 user_write_callback_ = callback;
[email protected]1d583612010-03-12 17:47:14734 } else {
[email protected]a3ff5e92009-10-13 04:48:06735 user_write_buf_ = NULL;
736 user_write_buf_len_ = 0;
737 }
[email protected]ea224582008-12-07 20:25:46738 LeaveFunction(rv);
[email protected]b43c97c2008-10-22 19:50:58739 return rv;
740}
741
[email protected]d3f66572009-09-09 22:38:04742bool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) {
[email protected]e60e47a2010-07-14 03:37:18743 return transport_->socket()->SetReceiveBufferSize(size);
[email protected]d3f66572009-09-09 22:38:04744}
745
746bool SSLClientSocketNSS::SetSendBufferSize(int32 size) {
[email protected]e60e47a2010-07-14 03:37:18747 return transport_->socket()->SetSendBufferSize(size);
[email protected]d3f66572009-09-09 22:38:04748}
749
[email protected]e9b084c2010-06-04 18:17:23750#if defined(OS_WIN)
751// static
752X509Certificate::OSCertHandle SSLClientSocketNSS::CreateOSCert(
753 const SECItem& der_cert) {
754 // TODO(wtc): close cert_store_ at shutdown.
755 if (!cert_store_)
756 cert_store_ = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL);
757
758 X509Certificate::OSCertHandle cert_handle = NULL;
759 BOOL ok = CertAddEncodedCertificateToStore(
760 cert_store_, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
761 der_cert.data, der_cert.len, CERT_STORE_ADD_USE_EXISTING, &cert_handle);
762 return ok ? cert_handle : NULL;
763}
764#elif defined(OS_MACOSX)
765// static
766X509Certificate::OSCertHandle SSLClientSocketNSS::CreateOSCert(
767 const SECItem& der_cert) {
768 return X509Certificate::CreateOSCertHandleFromBytes(
769 reinterpret_cast<char*>(der_cert.data), der_cert.len);
770}
771#endif
772
[email protected]bacff652009-03-31 17:50:33773X509Certificate *SSLClientSocketNSS::UpdateServerCert() {
774 // We set the server_cert_ from OwnAuthCertHandler(), but this handler
775 // does not necessarily get called if we are continuing a cached SSL
776 // session.
777 if (server_cert_ == NULL) {
[email protected]f505a9b2010-01-28 19:44:02778 server_cert_nss_ = SSL_PeerCertificate(nss_fd_);
779 if (server_cert_nss_) {
[email protected]3dd6f5e2010-06-01 20:28:03780#if defined(OS_MACOSX) || defined(OS_WIN)
[email protected]4bee851c2010-03-05 23:44:45781 // Get each of the intermediate certificates in the server's chain.
782 // These will be added to the server's X509Certificate object, making
783 // them available to X509Certificate::Verify() for chain building.
784 X509Certificate::OSCertHandles intermediate_ca_certs;
[email protected]3dd6f5e2010-06-01 20:28:03785 X509Certificate::OSCertHandle cert_handle = NULL;
[email protected]4bee851c2010-03-05 23:44:45786 CERTCertList* cert_list = CERT_GetCertChainFromCert(
787 server_cert_nss_, PR_Now(), certUsageSSLCA);
788 if (cert_list) {
789 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
790 !CERT_LIST_END(node, cert_list);
791 node = CERT_LIST_NEXT(node)) {
[email protected]37a0b112010-05-08 02:23:46792 if (node->cert == server_cert_nss_)
793 continue;
[email protected]3dd6f5e2010-06-01 20:28:03794#if defined(OS_WIN)
[email protected]37a0b112010-05-08 02:23:46795 // Work around http://crbug.com/43538 by not importing the
796 // problematic COMODO EV SGC CA certificate. CryptoAPI will
797 // download a good certificate for that CA, issued by COMODO
798 // Certification Authority, using the AIA extension in the server
799 // certificate.
800 if (IsProblematicComodoEVCACert(*node->cert))
801 continue;
[email protected]3dd6f5e2010-06-01 20:28:03802#endif
[email protected]e9b084c2010-06-04 18:17:23803 cert_handle = CreateOSCert(node->cert->derCert);
[email protected]3dd6f5e2010-06-01 20:28:03804 DCHECK(cert_handle);
805 intermediate_ca_certs.push_back(cert_handle);
[email protected]4bee851c2010-03-05 23:44:45806 }
807 CERT_DestroyCertList(cert_list);
808 }
809
810 // Finally create the X509Certificate object.
[email protected]e9b084c2010-06-04 18:17:23811 cert_handle = CreateOSCert(server_cert_nss_->derCert);
[email protected]3dd6f5e2010-06-01 20:28:03812 DCHECK(cert_handle);
[email protected]bacff652009-03-31 17:50:33813 server_cert_ = X509Certificate::CreateFromHandle(
[email protected]3dd6f5e2010-06-01 20:28:03814 cert_handle,
[email protected]4bee851c2010-03-05 23:44:45815 X509Certificate::SOURCE_FROM_NETWORK,
816 intermediate_ca_certs);
[email protected]1c8857bc2010-06-26 18:44:05817 X509Certificate::FreeOSCertHandle(cert_handle);
[email protected]4bee851c2010-03-05 23:44:45818 for (size_t i = 0; i < intermediate_ca_certs.size(); ++i)
[email protected]3dd6f5e2010-06-01 20:28:03819 X509Certificate::FreeOSCertHandle(intermediate_ca_certs[i]);
[email protected]f505a9b2010-01-28 19:44:02820#else
821 server_cert_ = X509Certificate::CreateFromHandle(
[email protected]1c8857bc2010-06-26 18:44:05822 server_cert_nss_,
[email protected]4bee851c2010-03-05 23:44:45823 X509Certificate::SOURCE_FROM_NETWORK,
824 X509Certificate::OSCertHandles());
[email protected]f505a9b2010-01-28 19:44:02825#endif
[email protected]bacff652009-03-31 17:50:33826 }
827 }
828 return server_cert_;
829}
830
[email protected]1e7cd2c72010-02-27 01:31:19831// Log an informational message if the server does not support secure
832// renegotiation (RFC 5746).
833void SSLClientSocketNSS::CheckSecureRenegotiation() const {
834 // SSL_HandshakeNegotiatedExtension was added in NSS 3.12.6.
835 // Since SSL_MAX_EXTENSIONS was added at the same time, we can test
836 // SSL_MAX_EXTENSIONS for the presence of SSL_HandshakeNegotiatedExtension.
837#if defined(SSL_MAX_EXTENSIONS)
838 PRBool received_renego_info;
839 if (SSL_HandshakeNegotiatedExtension(nss_fd_, ssl_renegotiation_info_xtn,
840 &received_renego_info) == SECSuccess &&
841 !received_renego_info) {
842 LOG(INFO) << "The server " << hostname_
[email protected]d48fd7b2010-03-03 22:46:13843 << " does not support the TLS renegotiation_info extension.";
[email protected]1e7cd2c72010-02-27 01:31:19844 }
845#endif
846}
847
[email protected]b43c97c2008-10-22 19:50:58848void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
[email protected]e17b4c12008-11-05 22:04:08849 EnterFunction("");
[email protected]b43c97c2008-10-22 19:50:58850 ssl_info->Reset();
[email protected]2345cc52009-06-04 09:18:47851 if (!server_cert_)
852 return;
853
[email protected]ea224582008-12-07 20:25:46854 SSLChannelInfo channel_info;
855 SECStatus ok = SSL_GetChannelInfo(nss_fd_,
856 &channel_info, sizeof(channel_info));
[email protected]9f8821ed2008-12-09 18:02:37857 if (ok == SECSuccess &&
858 channel_info.length == sizeof(channel_info) &&
859 channel_info.cipherSuite) {
[email protected]ea224582008-12-07 20:25:46860 SSLCipherSuiteInfo cipher_info;
861 ok = SSL_GetCipherSuiteInfo(channel_info.cipherSuite,
862 &cipher_info, sizeof(cipher_info));
863 if (ok == SECSuccess) {
864 ssl_info->security_bits = cipher_info.effectiveKeyBits;
865 } else {
866 ssl_info->security_bits = -1;
[email protected]9f8821ed2008-12-09 18:02:37867 LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError()
868 << " for cipherSuite " << channel_info.cipherSuite;
[email protected]ea224582008-12-07 20:25:46869 }
[email protected]d8654bf2010-07-18 16:01:32870 ssl_info->connection_status |=
871 (((int)channel_info.cipherSuite) & SSL_CONNECTION_CIPHERSUITE_MASK) <<
872 SSL_CONNECTION_CIPHERSUITE_SHIFT;
873
874 ssl_info->connection_status |=
875 (((int)channel_info.compressionMethod) &
876 SSL_CONNECTION_COMPRESSION_MASK) <<
877 SSL_CONNECTION_COMPRESSION_SHIFT;
878
[email protected]bacff652009-03-31 17:50:33879 UpdateServerCert();
[email protected]ea224582008-12-07 20:25:46880 }
[email protected]2345cc52009-06-04 09:18:47881 ssl_info->cert_status = server_cert_verify_result_.cert_status;
[email protected]bacff652009-03-31 17:50:33882 DCHECK(server_cert_ != NULL);
883 ssl_info->cert = server_cert_;
[email protected]644bdca2009-11-30 20:40:53884
[email protected]fc7de492010-07-12 14:49:04885 PRBool peer_supports_renego_ext;
886 ok = SSL_HandshakeNegotiatedExtension(nss_fd_, ssl_renegotiation_info_xtn,
887 &peer_supports_renego_ext);
888 if (ok == SECSuccess) {
889 if (!peer_supports_renego_ext)
890 ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
891 UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported",
892 (int)peer_supports_renego_ext, 2);
893 }
894
895 if (ssl_config_.ssl3_fallback)
896 ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK;
897
[email protected]e17b4c12008-11-05 22:04:08898 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:58899}
900
[email protected]0b45559b2009-06-12 21:45:11901void SSLClientSocketNSS::GetSSLCertRequestInfo(
902 SSLCertRequestInfo* cert_request_info) {
[email protected]d84b3722009-10-15 21:23:37903 EnterFunction("");
[email protected]1d583612010-03-12 17:47:14904 cert_request_info->host_and_port = hostname_; // TODO(wtc): no port!
[email protected]b8fee152009-10-24 03:39:31905 cert_request_info->client_certs = client_certs_;
[email protected]d84b3722009-10-15 21:23:37906 LeaveFunction(cert_request_info->client_certs.size());
[email protected]0b45559b2009-06-12 21:45:11907}
908
[email protected]b28f19d72009-12-10 21:52:27909SSLClientSocket::NextProtoStatus
[email protected]f49ea7d2009-12-11 20:03:50910SSLClientSocketNSS::GetNextProto(std::string* proto) {
911#if defined(SSL_NEXT_PROTO_NEGOTIATED)
912 unsigned char buf[255];
[email protected]b28f19d72009-12-10 21:52:27913 int state;
914 unsigned len;
915 SECStatus rv = SSL_GetNextProto(nss_fd_, &state, buf, &len, sizeof(buf));
916 if (rv != SECSuccess) {
917 NOTREACHED() << "Error return from SSL_GetNextProto: " << rv;
918 proto->clear();
919 return kNextProtoUnsupported;
920 }
[email protected]f49ea7d2009-12-11 20:03:50921 // We don't check for truncation because sizeof(buf) is large enough to hold
922 // the maximum protocol size.
[email protected]829296f2010-01-27 02:58:03923 switch (state) {
[email protected]f49ea7d2009-12-11 20:03:50924 case SSL_NEXT_PROTO_NO_SUPPORT:
925 proto->clear();
926 return kNextProtoUnsupported;
927 case SSL_NEXT_PROTO_NEGOTIATED:
928 *proto = std::string(reinterpret_cast<char*>(buf), len);
929 return kNextProtoNegotiated;
930 case SSL_NEXT_PROTO_NO_OVERLAP:
931 *proto = std::string(reinterpret_cast<char*>(buf), len);
932 return kNextProtoNoOverlap;
933 default:
934 NOTREACHED() << "Unknown status from SSL_GetNextProto: " << state;
935 proto->clear();
936 return kNextProtoUnsupported;
[email protected]b28f19d72009-12-10 21:52:27937 }
[email protected]f49ea7d2009-12-11 20:03:50938#else
939 // No NPN support in the libssl that we are building with.
940 proto->clear();
941 return kNextProtoUnsupported;
[email protected]b28f19d72009-12-10 21:52:27942#endif
943}
944
[email protected]899c3e92010-08-28 15:53:50945void SSLClientSocketNSS::UseDNSSEC(DNSSECProvider* provider) {
946 dnssec_provider_ = provider;
947}
948
[email protected]a3ff5e92009-10-13 04:48:06949void SSLClientSocketNSS::DoReadCallback(int rv) {
[email protected]e17b4c12008-11-05 22:04:08950 EnterFunction(rv);
[email protected]b43c97c2008-10-22 19:50:58951 DCHECK(rv != ERR_IO_PENDING);
[email protected]a3ff5e92009-10-13 04:48:06952 DCHECK(user_read_callback_);
[email protected]b43c97c2008-10-22 19:50:58953
[email protected]a3ff5e92009-10-13 04:48:06954 // Since Run may result in Read being called, clear |user_read_callback_|
955 // up front.
956 CompletionCallback* c = user_read_callback_;
957 user_read_callback_ = NULL;
958 user_read_buf_ = NULL;
959 user_read_buf_len_ = 0;
960 c->Run(rv);
961 LeaveFunction("");
962}
963
964void SSLClientSocketNSS::DoWriteCallback(int rv) {
965 EnterFunction(rv);
966 DCHECK(rv != ERR_IO_PENDING);
967 DCHECK(user_write_callback_);
968
969 // Since Run may result in Write being called, clear |user_write_callback_|
970 // up front.
971 CompletionCallback* c = user_write_callback_;
972 user_write_callback_ = NULL;
973 user_write_buf_ = NULL;
974 user_write_buf_len_ = 0;
[email protected]b43c97c2008-10-22 19:50:58975 c->Run(rv);
[email protected]e17b4c12008-11-05 22:04:08976 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:58977}
978
[email protected]a6eb576292009-06-30 16:19:00979// As part of Connect(), the SSLClientSocketNSS object performs an SSL
980// handshake. This requires network IO, which in turn calls
981// BufferRecvComplete() with a non-zero byte count. This byte count eventually
982// winds its way through the state machine and ends up being passed to the
983// callback. For Read() and Write(), that's what we want. But for Connect(),
984// the caller expects OK (i.e. 0) for success.
985//
986void SSLClientSocketNSS::DoConnectCallback(int rv) {
987 EnterFunction(rv);
988 DCHECK_NE(rv, ERR_IO_PENDING);
989 DCHECK(user_connect_callback_);
990
[email protected]a6eb576292009-06-30 16:19:00991 CompletionCallback* c = user_connect_callback_;
992 user_connect_callback_ = NULL;
993 c->Run(rv > OK ? OK : rv);
994 LeaveFunction("");
995}
996
[email protected]a3ff5e92009-10-13 04:48:06997void SSLClientSocketNSS::OnHandshakeIOComplete(int result) {
[email protected]e17b4c12008-11-05 22:04:08998 EnterFunction(result);
[email protected]a3ff5e92009-10-13 04:48:06999 int rv = DoHandshakeLoop(result);
[email protected]5a05c47a2009-11-02 23:25:191000 if (rv != ERR_IO_PENDING) {
[email protected]ec11be62010-04-28 19:28:091001 net_log_.EndEvent(net::NetLog::TYPE_SSL_CONNECT, NULL);
[email protected]a3ff5e92009-10-13 04:48:061002 DoConnectCallback(rv);
[email protected]5a05c47a2009-11-02 23:25:191003 }
[email protected]a3ff5e92009-10-13 04:48:061004 LeaveFunction("");
1005}
1006
1007void SSLClientSocketNSS::OnSendComplete(int result) {
1008 EnterFunction(result);
[email protected]45965de2010-02-25 23:23:311009 if (next_handshake_state_ == STATE_HANDSHAKE) {
[email protected]a3ff5e92009-10-13 04:48:061010 // In handshake phase.
1011 OnHandshakeIOComplete(result);
1012 LeaveFunction("");
1013 return;
[email protected]a6eb576292009-06-30 16:19:001014 }
[email protected]a3ff5e92009-10-13 04:48:061015
1016 // OnSendComplete may need to call DoPayloadRead while the renegotiation
1017 // handshake is in progress.
1018 int rv_read = ERR_IO_PENDING;
1019 int rv_write = ERR_IO_PENDING;
1020 bool network_moved;
1021 do {
1022 if (user_read_buf_)
1023 rv_read = DoPayloadRead();
1024 if (user_write_buf_)
1025 rv_write = DoPayloadWrite();
1026 network_moved = DoTransportIO();
1027 } while (rv_read == ERR_IO_PENDING &&
1028 rv_write == ERR_IO_PENDING &&
1029 network_moved);
1030
1031 if (user_read_buf_ && rv_read != ERR_IO_PENDING)
1032 DoReadCallback(rv_read);
1033 if (user_write_buf_ && rv_write != ERR_IO_PENDING)
1034 DoWriteCallback(rv_write);
1035
1036 LeaveFunction("");
1037}
1038
1039void SSLClientSocketNSS::OnRecvComplete(int result) {
1040 EnterFunction(result);
[email protected]45965de2010-02-25 23:23:311041 if (next_handshake_state_ == STATE_HANDSHAKE) {
[email protected]a3ff5e92009-10-13 04:48:061042 // In handshake phase.
1043 OnHandshakeIOComplete(result);
1044 LeaveFunction("");
1045 return;
1046 }
1047
1048 // Network layer received some data, check if client requested to read
1049 // decrypted data.
1050 if (!user_read_buf_) {
1051 LeaveFunction("");
1052 return;
1053 }
1054
1055 int rv = DoReadLoop(result);
1056 if (rv != ERR_IO_PENDING)
1057 DoReadCallback(rv);
[email protected]e17b4c12008-11-05 22:04:081058 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581059}
1060
[email protected]b0735462009-11-04 22:11:261061// Map a Chromium net error code to an NSS error code.
[email protected]b43c97c2008-10-22 19:50:581062// See _MD_unix_map_default_error in the NSS source
1063// tree for inspiration.
1064static PRErrorCode MapErrorToNSS(int result) {
1065 if (result >=0)
1066 return result;
[email protected]b0735462009-11-04 22:11:261067
1068 switch (result) {
1069 case ERR_IO_PENDING:
1070 return PR_WOULD_BLOCK_ERROR;
1071 case ERR_ACCESS_DENIED:
1072 // For connect, this could be mapped to PR_ADDRESS_NOT_SUPPORTED_ERROR.
1073 return PR_NO_ACCESS_RIGHTS_ERROR;
1074 case ERR_INTERNET_DISCONNECTED: // Equivalent to ENETDOWN.
1075 return PR_NETWORK_UNREACHABLE_ERROR; // Best approximation.
1076 case ERR_CONNECTION_TIMED_OUT:
1077 case ERR_TIMED_OUT:
1078 return PR_IO_TIMEOUT_ERROR;
1079 case ERR_CONNECTION_RESET:
1080 return PR_CONNECT_RESET_ERROR;
1081 case ERR_CONNECTION_ABORTED:
1082 return PR_CONNECT_ABORTED_ERROR;
1083 case ERR_CONNECTION_REFUSED:
1084 return PR_CONNECT_REFUSED_ERROR;
1085 case ERR_ADDRESS_UNREACHABLE:
1086 return PR_HOST_UNREACHABLE_ERROR; // Also PR_NETWORK_UNREACHABLE_ERROR.
1087 case ERR_ADDRESS_INVALID:
1088 return PR_ADDRESS_NOT_AVAILABLE_ERROR;
[email protected]4d3040f42010-04-14 02:40:201089 case ERR_NAME_NOT_RESOLVED:
1090 return PR_DIRECTORY_LOOKUP_ERROR;
[email protected]b0735462009-11-04 22:11:261091 default:
1092 LOG(WARNING) << "MapErrorToNSS " << result
1093 << " mapped to PR_UNKNOWN_ERROR";
1094 return PR_UNKNOWN_ERROR;
1095 }
[email protected]b43c97c2008-10-22 19:50:581096}
1097
[email protected]ffeb0882009-04-30 21:51:251098// Do network I/O between the given buffer and the given socket.
[email protected]a3ff5e92009-10-13 04:48:061099// Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING)
1100bool SSLClientSocketNSS::DoTransportIO() {
1101 EnterFunction("");
1102 bool network_moved = false;
1103 if (nss_bufs_ != NULL) {
1104 int nsent = BufferSend();
1105 int nreceived = BufferRecv();
1106 network_moved = (nsent > 0 || nreceived >= 0);
1107 }
1108 LeaveFunction(network_moved);
1109 return network_moved;
1110}
1111
[email protected]ffeb0882009-04-30 21:51:251112// Return 0 for EOF,
1113// > 0 for bytes transferred immediately,
1114// < 0 for error (or the non-error ERR_IO_PENDING).
[email protected]b43c97c2008-10-22 19:50:581115int SSLClientSocketNSS::BufferSend(void) {
[email protected]9ae2ee02010-09-08 16:41:141116 if (transport_send_busy_)
1117 return ERR_IO_PENDING;
[email protected]b43c97c2008-10-22 19:50:581118
[email protected]914286d62009-12-10 23:06:441119 EnterFunction("");
[email protected]9ae2ee02010-09-08 16:41:141120 const char* buf1;
1121 const char* buf2;
1122 unsigned int len1, len2;
1123 memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2);
1124 const unsigned int len = len1 + len2;
[email protected]b43c97c2008-10-22 19:50:581125
[email protected]9ae2ee02010-09-08 16:41:141126 if (corked_ && len < kRecvBufferSize / 2)
1127 return 0;
1128
1129 int rv = 0;
1130 if (len) {
1131 scoped_refptr<IOBuffer> send_buffer = new IOBuffer(len);
1132 memcpy(send_buffer->data(), buf1, len1);
1133 memcpy(send_buffer->data() + len1, buf2, len2);
1134 rv = transport_->socket()->Write(send_buffer, len,
1135 &buffer_send_callback_);
[email protected]914286d62009-12-10 23:06:441136 if (rv == ERR_IO_PENDING) {
[email protected]b43c97c2008-10-22 19:50:581137 transport_send_busy_ = true;
[email protected]914286d62009-12-10 23:06:441138 } else {
[email protected]b43c97c2008-10-22 19:50:581139 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
[email protected]914286d62009-12-10 23:06:441140 }
[email protected]b43c97c2008-10-22 19:50:581141 }
1142
[email protected]9ae2ee02010-09-08 16:41:141143 LeaveFunction(rv);
1144 return rv;
[email protected]b43c97c2008-10-22 19:50:581145}
1146
1147void SSLClientSocketNSS::BufferSendComplete(int result) {
[email protected]e17b4c12008-11-05 22:04:081148 EnterFunction(result);
[email protected]b0735462009-11-04 22:11:261149 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
[email protected]b43c97c2008-10-22 19:50:581150 transport_send_busy_ = false;
[email protected]a3ff5e92009-10-13 04:48:061151 OnSendComplete(result);
[email protected]e17b4c12008-11-05 22:04:081152 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581153}
1154
1155
1156int SSLClientSocketNSS::BufferRecv(void) {
[email protected]b43c97c2008-10-22 19:50:581157 if (transport_recv_busy_) return ERR_IO_PENDING;
1158
1159 char *buf;
1160 int nb = memio_GetReadParams(nss_bufs_, &buf);
[email protected]e17b4c12008-11-05 22:04:081161 EnterFunction(nb);
[email protected]b43c97c2008-10-22 19:50:581162 int rv;
1163 if (!nb) {
1164 // buffer too full to read into, so no I/O possible at moment
1165 rv = ERR_IO_PENDING;
1166 } else {
[email protected]ffeb0882009-04-30 21:51:251167 recv_buffer_ = new IOBuffer(nb);
[email protected]e60e47a2010-07-14 03:37:181168 rv = transport_->socket()->Read(recv_buffer_, nb, &buffer_recv_callback_);
[email protected]ffeb0882009-04-30 21:51:251169 if (rv == ERR_IO_PENDING) {
[email protected]b43c97c2008-10-22 19:50:581170 transport_recv_busy_ = true;
[email protected]ffeb0882009-04-30 21:51:251171 } else {
1172 if (rv > 0)
1173 memcpy(buf, recv_buffer_->data(), rv);
[email protected]b43c97c2008-10-22 19:50:581174 memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
[email protected]ffeb0882009-04-30 21:51:251175 recv_buffer_ = NULL;
1176 }
[email protected]b43c97c2008-10-22 19:50:581177 }
[email protected]e17b4c12008-11-05 22:04:081178 LeaveFunction(rv);
[email protected]b43c97c2008-10-22 19:50:581179 return rv;
1180}
1181
1182void SSLClientSocketNSS::BufferRecvComplete(int result) {
[email protected]e17b4c12008-11-05 22:04:081183 EnterFunction(result);
[email protected]ffeb0882009-04-30 21:51:251184 if (result > 0) {
1185 char *buf;
1186 memio_GetReadParams(nss_bufs_, &buf);
1187 memcpy(buf, recv_buffer_->data(), result);
1188 }
1189 recv_buffer_ = NULL;
[email protected]b0735462009-11-04 22:11:261190 memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
[email protected]b43c97c2008-10-22 19:50:581191 transport_recv_busy_ = false;
[email protected]a3ff5e92009-10-13 04:48:061192 OnRecvComplete(result);
[email protected]e17b4c12008-11-05 22:04:081193 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581194}
1195
[email protected]a3ff5e92009-10-13 04:48:061196int SSLClientSocketNSS::DoHandshakeLoop(int last_io_result) {
[email protected]e17b4c12008-11-05 22:04:081197 EnterFunction(last_io_result);
[email protected]b43c97c2008-10-22 19:50:581198 bool network_moved;
1199 int rv = last_io_result;
1200 do {
[email protected]e17b4c12008-11-05 22:04:081201 // Default to STATE_NONE for next state.
[email protected]ea224582008-12-07 20:25:461202 // (This is a quirk carried over from the windows
[email protected]e17b4c12008-11-05 22:04:081203 // implementation. It makes reading the logs a bit harder.)
[email protected]ea224582008-12-07 20:25:461204 // State handlers can and often do call GotoState just
[email protected]e17b4c12008-11-05 22:04:081205 // to stay in the current state.
[email protected]a3ff5e92009-10-13 04:48:061206 State state = next_handshake_state_;
[email protected]e17b4c12008-11-05 22:04:081207 GotoState(STATE_NONE);
[email protected]b43c97c2008-10-22 19:50:581208 switch (state) {
[email protected]e17b4c12008-11-05 22:04:081209 case STATE_NONE:
1210 // we're just pumping data between the buffer and the network
1211 break;
[email protected]a3ff5e92009-10-13 04:48:061212 case STATE_HANDSHAKE:
1213 rv = DoHandshake();
[email protected]b43c97c2008-10-22 19:50:581214 break;
[email protected]899c3e92010-08-28 15:53:501215 case STATE_VERIFY_DNSSEC:
1216 rv = DoVerifyDNSSEC(rv);
1217 break;
1218 case STATE_VERIFY_DNSSEC_COMPLETE:
1219 rv = DoVerifyDNSSECComplete(rv);
1220 break;
[email protected]2345cc52009-06-04 09:18:471221 case STATE_VERIFY_CERT:
1222 DCHECK(rv == OK);
1223 rv = DoVerifyCert(rv);
1224 break;
1225 case STATE_VERIFY_CERT_COMPLETE:
1226 rv = DoVerifyCertComplete(rv);
1227 break;
[email protected]b43c97c2008-10-22 19:50:581228 default:
1229 rv = ERR_UNEXPECTED;
1230 NOTREACHED() << "unexpected state";
1231 break;
1232 }
1233
1234 // Do the actual network I/O
[email protected]a3ff5e92009-10-13 04:48:061235 network_moved = DoTransportIO();
[email protected]72d1e592009-03-10 17:39:461236 } while ((rv != ERR_IO_PENDING || network_moved) &&
[email protected]a3ff5e92009-10-13 04:48:061237 next_handshake_state_ != STATE_NONE);
1238 LeaveFunction("");
1239 return rv;
1240}
1241
1242int SSLClientSocketNSS::DoReadLoop(int result) {
1243 EnterFunction("");
1244 DCHECK(completed_handshake_);
1245 DCHECK(next_handshake_state_ == STATE_NONE);
1246
1247 if (result < 0)
1248 return result;
1249
1250 if (!nss_bufs_)
1251 return ERR_UNEXPECTED;
1252
1253 bool network_moved;
1254 int rv;
1255 do {
1256 rv = DoPayloadRead();
1257 network_moved = DoTransportIO();
1258 } while (rv == ERR_IO_PENDING && network_moved);
1259
1260 LeaveFunction("");
1261 return rv;
1262}
1263
1264int SSLClientSocketNSS::DoWriteLoop(int result) {
1265 EnterFunction("");
1266 DCHECK(completed_handshake_);
1267 DCHECK(next_handshake_state_ == STATE_NONE);
1268
1269 if (result < 0)
1270 return result;
1271
1272 if (!nss_bufs_)
1273 return ERR_UNEXPECTED;
1274
1275 bool network_moved;
1276 int rv;
1277 do {
1278 rv = DoPayloadWrite();
1279 network_moved = DoTransportIO();
1280 } while (rv == ERR_IO_PENDING && network_moved);
1281
[email protected]e17b4c12008-11-05 22:04:081282 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581283 return rv;
1284}
1285
[email protected]bacff652009-03-31 17:50:331286// static
1287// NSS calls this if an incoming certificate needs to be verified.
[email protected]2345cc52009-06-04 09:18:471288// Do nothing but return SECSuccess.
1289// This is called only in full handshake mode.
1290// Peer certificate is retrieved in HandshakeCallback() later, which is called
1291// in full handshake mode or in resumption handshake mode.
[email protected]bacff652009-03-31 17:50:331292SECStatus SSLClientSocketNSS::OwnAuthCertHandler(void* arg,
1293 PRFileDesc* socket,
1294 PRBool checksig,
1295 PRBool is_server) {
[email protected]9ae2ee02010-09-08 16:41:141296#ifdef SSL_ENABLE_FALSE_START
1297 // In the event that we are False Starting this connection, we wish to send
1298 // out the Finished message and first application data record in the same
1299 // packet. This prevents non-determinism when talking to False Start
1300 // intolerant servers which, otherwise, might see the two messages in
1301 // different reads or not, depending on network conditions.
1302 PRBool false_start = 0;
1303 SECStatus rv = SSL_OptionGet(socket, SSL_ENABLE_FALSE_START, &false_start);
1304 if (rv != SECSuccess)
1305 NOTREACHED();
1306 if (false_start) {
1307 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg);
1308 if (!that->handshake_callback_called_)
1309 that->corked_ = true;
1310 }
1311#endif
1312
[email protected]2345cc52009-06-04 09:18:471313 // Tell NSS to not verify the certificate.
1314 return SECSuccess;
1315}
1316
1317// static
[email protected]d84b3722009-10-15 21:23:371318// NSS calls this if a client certificate is needed.
1319// Based on Mozilla's NSS_GetClientAuthData.
1320SECStatus SSLClientSocketNSS::ClientAuthHandler(
1321 void* arg,
1322 PRFileDesc* socket,
1323 CERTDistNames* ca_names,
1324 CERTCertificate** result_certificate,
1325 SECKEYPrivateKey** result_private_key) {
1326 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg);
1327
1328 that->client_auth_cert_needed_ = !that->ssl_config_.send_client_cert;
1329
[email protected]1d583612010-03-12 17:47:141330#if defined(OS_WIN)
1331 if (that->ssl_config_.send_client_cert) {
1332 // TODO(wtc): SSLClientSocketNSS can't do SSL client authentication using
1333 // CryptoAPI yet (http://crbug.com/37560), so client_cert must be NULL.
1334 DCHECK(!that->ssl_config_.client_cert);
1335 // Send no client certificate.
1336 return SECFailure;
1337 }
1338
1339 that->client_certs_.clear();
1340
1341 std::vector<CERT_NAME_BLOB> issuer_list(ca_names->nnames);
1342 for (int i = 0; i < ca_names->nnames; ++i) {
1343 issuer_list[i].cbData = ca_names->names[i].len;
1344 issuer_list[i].pbData = ca_names->names[i].data;
1345 }
1346
1347 // Client certificates of the user are in the "MY" system certificate store.
1348 HCERTSTORE my_cert_store = CertOpenSystemStore(NULL, L"MY");
1349 if (!my_cert_store) {
1350 LOG(ERROR) << "Could not open the \"MY\" system certificate store: "
1351 << GetLastError();
1352 return SECFailure;
1353 }
1354
1355 // Enumerate the client certificates.
1356 CERT_CHAIN_FIND_BY_ISSUER_PARA find_by_issuer_para;
1357 memset(&find_by_issuer_para, 0, sizeof(find_by_issuer_para));
1358 find_by_issuer_para.cbSize = sizeof(find_by_issuer_para);
1359 find_by_issuer_para.pszUsageIdentifier = szOID_PKIX_KP_CLIENT_AUTH;
1360 find_by_issuer_para.cIssuer = ca_names->nnames;
1361 find_by_issuer_para.rgIssuer = ca_names->nnames ? &issuer_list[0] : NULL;
[email protected]01640f62010-08-10 19:42:121362 find_by_issuer_para.pfnFindCallback = ClientCertFindCallback;
[email protected]1d583612010-03-12 17:47:141363
1364 PCCERT_CHAIN_CONTEXT chain_context = NULL;
1365
[email protected]3dd6f5e2010-06-01 20:28:031366 // TODO(wtc): close cert_store_ at shutdown.
1367 if (!cert_store_)
1368 cert_store_ = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL);
1369
[email protected]1d583612010-03-12 17:47:141370 for (;;) {
1371 // Find a certificate chain.
1372 chain_context = CertFindChainInStore(my_cert_store,
1373 X509_ASN_ENCODING,
1374 0,
1375 CERT_CHAIN_FIND_BY_ISSUER,
1376 &find_by_issuer_para,
1377 chain_context);
1378 if (!chain_context) {
1379 DWORD err = GetLastError();
1380 if (err != CRYPT_E_NOT_FOUND)
1381 DLOG(ERROR) << "CertFindChainInStore failed: " << err;
1382 break;
1383 }
1384
1385 // Get the leaf certificate.
1386 PCCERT_CONTEXT cert_context =
1387 chain_context->rgpChain[0]->rgpElement[0]->pCertContext;
1388 // Copy it to our own certificate store, so that we can close the "MY"
1389 // certificate store before returning from this function.
1390 PCCERT_CONTEXT cert_context2;
1391 BOOL ok = CertAddCertificateContextToStore(cert_store_, cert_context,
1392 CERT_STORE_ADD_USE_EXISTING,
1393 &cert_context2);
1394 if (!ok) {
1395 NOTREACHED();
1396 continue;
1397 }
1398 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle(
1399 cert_context2, X509Certificate::SOURCE_LONE_CERT_IMPORT,
[email protected]1c8857bc2010-06-26 18:44:051400 X509Certificate::OSCertHandles());
1401 X509Certificate::FreeOSCertHandle(cert_context2);
[email protected]1d583612010-03-12 17:47:141402 that->client_certs_.push_back(cert);
1403 }
1404
1405 BOOL ok = CertCloseStore(my_cert_store, CERT_CLOSE_STORE_CHECK_FLAG);
1406 DCHECK(ok);
1407
1408 // Tell NSS to suspend the client authentication. We will then abort the
1409 // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
1410 return SECWouldBlock;
[email protected]3dd6f5e2010-06-01 20:28:031411#elif defined(OS_MACOSX)
[email protected]fd4f139f2010-06-11 17:02:201412 if (that->ssl_config_.send_client_cert) {
1413 // TODO(wtc): SSLClientSocketNSS can't do SSL client authentication using
1414 // CDSA/CSSM yet (http://crbug.com/45369), so client_cert must be NULL.
1415 DCHECK(!that->ssl_config_.client_cert);
1416 // Send no client certificate.
1417 return SECFailure;
1418 }
1419
1420 that->client_certs_.clear();
1421
1422 // First, get the cert issuer names allowed by the server.
1423 std::vector<CertPrincipal> valid_issuers;
1424 int n = ca_names->nnames;
1425 for (int i = 0; i < n; i++) {
1426 // Parse each name into a CertPrincipal object.
1427 CertPrincipal p;
1428 if (p.ParseDistinguishedName(ca_names->names[i].data,
1429 ca_names->names[i].len)) {
1430 valid_issuers.push_back(p);
1431 }
1432 }
1433
1434 // Now get the available client certs whose issuers are allowed by the server.
1435 X509Certificate::GetSSLClientCertificates(that->hostname_,
1436 valid_issuers,
1437 &that->client_certs_);
1438
1439 // Tell NSS to suspend the client authentication. We will then abort the
1440 // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
1441 return SECWouldBlock;
[email protected]1d583612010-03-12 17:47:141442#else
[email protected]b8fee152009-10-24 03:39:311443 void* wincx = SSL_RevealPinArg(socket);
1444
[email protected]d84b3722009-10-15 21:23:371445 // Second pass: a client certificate should have been selected.
1446 if (that->ssl_config_.send_client_cert) {
1447 if (that->ssl_config_.client_cert) {
[email protected]701e8692010-08-17 20:00:431448 CERTCertificate* cert = CERT_DupCertificate(
[email protected]d84b3722009-10-15 21:23:371449 that->ssl_config_.client_cert->os_cert_handle());
[email protected]701e8692010-08-17 20:00:431450 SECKEYPrivateKey* privkey = PK11_FindKeyByAnyCert(cert, wincx);
[email protected]d84b3722009-10-15 21:23:371451 if (privkey) {
1452 // TODO(jsorianopastor): We should wait for server certificate
1453 // verification before sending our credentials. See
1454 // http://crbug.com/13934.
1455 *result_certificate = cert;
1456 *result_private_key = privkey;
1457 return SECSuccess;
1458 }
1459 LOG(WARNING) << "Client cert found without private key";
1460 }
1461 // Send no client certificate.
1462 return SECFailure;
1463 }
1464
[email protected]701e8692010-08-17 20:00:431465 // Iterate over all client certificates.
1466 CERTCertList* client_certs = CERT_FindUserCertsByUsage(
1467 CERT_GetDefaultCertDB(), certUsageSSLClient,
1468 PR_FALSE, PR_FALSE, wincx);
1469 if (client_certs) {
1470 for (CERTCertListNode* node = CERT_LIST_HEAD(client_certs);
1471 !CERT_LIST_END(node, client_certs);
1472 node = CERT_LIST_NEXT(node)) {
1473 // Only offer unexpired certificates.
1474 if (CERT_CheckCertValidTimes(node->cert, PR_Now(), PR_TRUE) !=
1475 secCertTimeValid)
[email protected]b8fee152009-10-24 03:39:311476 continue;
[email protected]701e8692010-08-17 20:00:431477 // Filter by issuer.
1478 //
1479 // TODO(davidben): This does a binary comparison of the DER-encoded
1480 // issuers. We should match according to RFC 5280 sec. 7.1. We should find
1481 // an appropriate NSS function or add one if needbe.
1482 if (ca_names->nnames &&
1483 NSS_CmpCertChainWCANames(node->cert, ca_names) != SECSuccess)
1484 continue;
1485 X509Certificate* x509_cert = X509Certificate::CreateFromHandle(
1486 node->cert, X509Certificate::SOURCE_LONE_CERT_IMPORT,
1487 net::X509Certificate::OSCertHandles());
1488 that->client_certs_.push_back(x509_cert);
[email protected]b8fee152009-10-24 03:39:311489 }
[email protected]701e8692010-08-17 20:00:431490 CERT_DestroyCertList(client_certs);
[email protected]b8fee152009-10-24 03:39:311491 }
[email protected]d84b3722009-10-15 21:23:371492
[email protected]f6ee0a012010-03-05 22:00:241493 // Tell NSS to suspend the client authentication. We will then abort the
1494 // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
1495 return SECWouldBlock;
[email protected]f505a9b2010-01-28 19:44:021496#endif
[email protected]d84b3722009-10-15 21:23:371497}
1498
1499// static
[email protected]2345cc52009-06-04 09:18:471500// NSS calls this when handshake is completed.
1501// After the SSL handshake is finished, use CertVerifier to verify
1502// the saved server certificate.
1503void SSLClientSocketNSS::HandshakeCallback(PRFileDesc* socket,
1504 void* arg) {
[email protected]bacff652009-03-31 17:50:331505 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg);
1506
[email protected]39afe642010-04-29 14:55:181507 that->set_handshake_callback_called();
1508
[email protected]2345cc52009-06-04 09:18:471509 that->UpdateServerCert();
[email protected]1e7cd2c72010-02-27 01:31:191510
1511 that->CheckSecureRenegotiation();
[email protected]2345cc52009-06-04 09:18:471512}
[email protected]bacff652009-03-31 17:50:331513
[email protected]a3ff5e92009-10-13 04:48:061514int SSLClientSocketNSS::DoHandshake() {
[email protected]2345cc52009-06-04 09:18:471515 EnterFunction("");
1516 int net_error = net::OK;
[email protected]d84b3722009-10-15 21:23:371517 SECStatus rv = SSL_ForceHandshake(nss_fd_);
[email protected]2345cc52009-06-04 09:18:471518
[email protected]d84b3722009-10-15 21:23:371519 if (client_auth_cert_needed_) {
1520 net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
1521 // If the handshake already succeeded (because the server requests but
1522 // doesn't require a client cert), we need to invalidate the SSL session
1523 // so that we won't try to resume the non-client-authenticated session in
1524 // the next handshake. This will cause the server to ask for a client
1525 // cert again.
1526 if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess) {
1527 LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError();
1528 }
1529 } else if (rv == SECSuccess) {
[email protected]39afe642010-04-29 14:55:181530 if (handshake_callback_called_) {
1531 // SSL handshake is completed. Let's verify the certificate.
[email protected]899c3e92010-08-28 15:53:501532 GotoState(STATE_VERIFY_DNSSEC);
[email protected]39afe642010-04-29 14:55:181533 // Done!
1534 } else {
1535 // SSL_ForceHandshake returned SECSuccess prematurely.
1536 rv = SECFailure;
1537 net_error = ERR_SSL_PROTOCOL_ERROR;
1538 }
[email protected]2345cc52009-06-04 09:18:471539 } else {
1540 PRErrorCode prerr = PR_GetError();
[email protected]2e9a5b6982010-01-15 22:29:031541 net_error = MapHandshakeError(prerr);
[email protected]2345cc52009-06-04 09:18:471542
1543 // If not done, stay in this state
1544 if (net_error == ERR_IO_PENDING) {
[email protected]a3ff5e92009-10-13 04:48:061545 GotoState(STATE_HANDSHAKE);
[email protected]2345cc52009-06-04 09:18:471546 } else {
1547 LOG(ERROR) << "handshake failed; NSS error code " << prerr
1548 << ", net_error " << net_error;
1549 }
1550 }
1551
1552 LeaveFunction("");
1553 return net_error;
1554}
1555
[email protected]899c3e92010-08-28 15:53:501556// DNSValidationResult enumerates the possible outcomes from processing a
1557// set of DNS records.
1558enum DNSValidationResult {
1559 DNSVR_SUCCESS, // the cert is immediately acceptable.
1560 DNSVR_FAILURE, // the cert is unconditionally rejected.
1561 DNSVR_CONTINUE, // perform CA validation as usual.
1562};
1563
1564// VerifyTXTRecords processes the RRDATA for a number of DNS TXT records and
1565// checks them against the given certificate.
1566// dnssec: if true then the TXT records are DNSSEC validated. In this case,
1567// DNSVR_SUCCESS may be returned.
1568// server_cert_nss: the certificate to validate
1569// rrdatas: the TXT records for the current domain.
1570static DNSValidationResult VerifyTXTRecords(
1571 bool dnssec,
1572 CERTCertificate* server_cert_nss,
1573 const std::vector<base::StringPiece>& rrdatas) {
1574 bool found_well_formed_record = false;
1575 bool matched_record = false;
1576
1577 for (std::vector<base::StringPiece>::const_iterator
1578 i = rrdatas.begin(); i != rrdatas.end(); ++i) {
1579 std::map<std::string, std::string> m(
1580 DNSSECChainVerifier::ParseTLSTXTRecord(*i));
1581 if (m.empty())
1582 continue;
1583
1584 std::map<std::string, std::string>::const_iterator j;
1585 j = m.find("v");
1586 if (j == m.end() || j->second != "tls1")
1587 continue;
1588
1589 j = m.find("ha");
1590
1591 HASH_HashType hash_algorithm;
1592 unsigned hash_length;
1593 if (j == m.end() || j->second == "sha1") {
1594 hash_algorithm = HASH_AlgSHA1;
1595 hash_length = SHA1_LENGTH;
1596 } else if (j->second == "sha256") {
1597 hash_algorithm = HASH_AlgSHA256;
1598 hash_length = SHA256_LENGTH;
1599 } else {
1600 continue;
1601 }
1602
1603 j = m.find("h");
1604 if (j == m.end())
1605 continue;
1606
1607 std::vector<uint8> given_hash;
1608 if (!base::HexStringToBytes(j->second, &given_hash))
1609 continue;
1610
1611 if (given_hash.size() != hash_length)
1612 continue;
1613
1614 uint8 calculated_hash[SHA256_LENGTH]; // SHA256 is the largest.
1615 SECStatus rv;
1616
1617 j = m.find("hr");
[email protected]b40f05a2010-09-09 20:13:231618 if (j == m.end() || j->second == "pubkey") {
[email protected]899c3e92010-08-28 15:53:501619 rv = HASH_HashBuf(hash_algorithm, calculated_hash,
1620 server_cert_nss->derPublicKey.data,
1621 server_cert_nss->derPublicKey.len);
[email protected]b40f05a2010-09-09 20:13:231622 } else if (j->second == "cert") {
1623 rv = HASH_HashBuf(hash_algorithm, calculated_hash,
1624 server_cert_nss->derCert.data,
1625 server_cert_nss->derCert.len);
[email protected]899c3e92010-08-28 15:53:501626 } else {
1627 continue;
1628 }
1629
1630 if (rv != SECSuccess)
1631 NOTREACHED();
1632
1633 found_well_formed_record = true;
1634
1635 if (memcmp(calculated_hash, &given_hash[0], hash_length) == 0) {
1636 matched_record = true;
1637 if (dnssec)
1638 return DNSVR_SUCCESS;
1639 }
1640 }
1641
1642 if (found_well_formed_record && !matched_record)
1643 return DNSVR_FAILURE;
1644
1645 return DNSVR_CONTINUE;
1646}
1647
1648
[email protected]b24713592010-08-11 19:50:021649// CheckDNSSECChain tries to validate a DNSSEC chain embedded in
1650// |server_cert_nss_|. It returns true iff a chain is found that proves the
[email protected]899c3e92010-08-28 15:53:501651// value of a TXT record that contains a valid public key fingerprint.
1652static DNSValidationResult CheckDNSSECChain(
1653 const std::string& hostname,
1654 CERTCertificate* server_cert_nss) {
1655 if (!server_cert_nss)
1656 return DNSVR_CONTINUE;
[email protected]b24713592010-08-11 19:50:021657
[email protected]b24713592010-08-11 19:50:021658 // CERT_FindCertExtensionByOID isn't exported so we have to install an OID,
1659 // get a tag for it and find the extension by using that tag.
1660 static SECOidTag dnssec_chain_tag;
1661 static bool dnssec_chain_tag_valid;
1662 if (!dnssec_chain_tag_valid) {
1663 // It's harmless if multiple threads enter this block concurrently.
1664 static const uint8 kDNSSECChainOID[] =
1665 // 1.3.6.1.4.1.11129.13172
1666 // (iso.org.dod.internet.private.enterprises.google.13172)
1667 {0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0xe6, 0x74};
1668 SECOidData oid_data;
1669 memset(&oid_data, 0, sizeof(oid_data));
1670 oid_data.oid.data = const_cast<uint8*>(kDNSSECChainOID);
1671 oid_data.oid.len = sizeof(kDNSSECChainOID);
1672 oid_data.desc = "DNSSEC chain";
1673 oid_data.supportedExtension = SUPPORTED_CERT_EXTENSION;
1674 dnssec_chain_tag = SECOID_AddEntry(&oid_data);
1675 DCHECK_NE(SEC_OID_UNKNOWN, dnssec_chain_tag);
1676 dnssec_chain_tag_valid = true;
1677 }
1678
1679 SECItem dnssec_embedded_chain;
[email protected]899c3e92010-08-28 15:53:501680 SECStatus rv = CERT_FindCertExtension(server_cert_nss,
[email protected]b24713592010-08-11 19:50:021681 dnssec_chain_tag, &dnssec_embedded_chain);
1682 if (rv != SECSuccess)
[email protected]899c3e92010-08-28 15:53:501683 return DNSVR_CONTINUE;
[email protected]b24713592010-08-11 19:50:021684
1685 base::StringPiece chain(
1686 reinterpret_cast<char*>(dnssec_embedded_chain.data),
1687 dnssec_embedded_chain.len);
1688 std::string dns_hostname;
[email protected]899c3e92010-08-28 15:53:501689 if (!DNSDomainFromDot(hostname, &dns_hostname))
1690 return DNSVR_CONTINUE;
[email protected]b24713592010-08-11 19:50:021691 DNSSECChainVerifier verifier(dns_hostname, chain);
1692 DNSSECChainVerifier::Error err = verifier.Verify();
1693 if (err != DNSSECChainVerifier::OK) {
1694 LOG(ERROR) << "DNSSEC chain verification failed: " << err;
[email protected]899c3e92010-08-28 15:53:501695 return DNSVR_CONTINUE;
[email protected]b24713592010-08-11 19:50:021696 }
1697
[email protected]899c3e92010-08-28 15:53:501698 if (verifier.rrtype() != kDNS_TXT)
1699 return DNSVR_CONTINUE;
[email protected]b24713592010-08-11 19:50:021700
[email protected]899c3e92010-08-28 15:53:501701 DNSValidationResult r = VerifyTXTRecords(
1702 true /* DNSSEC verified */, server_cert_nss, verifier.rrdatas());
1703 SECITEM_FreeItem(&dnssec_embedded_chain, PR_FALSE);
1704 return r;
1705}
[email protected]b24713592010-08-11 19:50:021706
[email protected]899c3e92010-08-28 15:53:501707int SSLClientSocketNSS::DoVerifyDNSSEC(int result) {
1708 if (ssl_config_.dnssec_enabled) {
1709 DNSValidationResult r = CheckDNSSECChain(hostname_, server_cert_nss_);
1710 if (r == DNSVR_SUCCESS) {
1711 GotoState(STATE_VERIFY_CERT_COMPLETE);
1712 return OK;
[email protected]b24713592010-08-11 19:50:021713 }
1714 }
1715
[email protected]899c3e92010-08-28 15:53:501716 if (dnssec_provider_ == NULL) {
1717 GotoState(STATE_VERIFY_CERT);
1718 return OK;
1719 }
1720
1721 GotoState(STATE_VERIFY_DNSSEC_COMPLETE);
1722 RRResponse* response;
1723 dnssec_wait_start_time_ = base::Time::Now();
1724 return dnssec_provider_->GetDNSSECRecords(&response, &handshake_io_callback_);
1725}
1726
1727int SSLClientSocketNSS::DoVerifyDNSSECComplete(int result) {
1728 RRResponse* response;
1729 int err = dnssec_provider_->GetDNSSECRecords(&response, NULL);
1730 DCHECK_EQ(err, OK);
1731
1732 const base::TimeDelta elapsed = base::Time::Now() - dnssec_wait_start_time_;
1733 HISTOGRAM_TIMES("Net.DNSSECWaitTime", elapsed);
1734
1735 GotoState(STATE_VERIFY_CERT);
1736 if (!response || response->rrdatas.empty())
1737 return OK;
1738
1739 std::vector<base::StringPiece> records;
1740 records.resize(response->rrdatas.size());
1741 for (unsigned i = 0; i < response->rrdatas.size(); i++)
1742 records[i] = base::StringPiece(response->rrdatas[i]);
1743 DNSValidationResult r =
1744 VerifyTXTRecords(response->dnssec, server_cert_nss_, records);
1745
1746 if (!ssl_config_.dnssec_enabled) {
1747 // If DNSSEC is not enabled we don't take any action based on the result,
1748 // except to record the latency, above.
1749 GotoState(STATE_VERIFY_CERT);
1750 return OK;
1751 }
1752
1753 switch (r) {
1754 case DNSVR_FAILURE:
1755 GotoState(STATE_VERIFY_CERT_COMPLETE);
1756 return ERR_CERT_NOT_IN_DNS;
1757 case DNSVR_CONTINUE:
1758 GotoState(STATE_VERIFY_CERT);
1759 break;
1760 case DNSVR_SUCCESS:
1761 GotoState(STATE_VERIFY_CERT_COMPLETE);
1762 break;
1763 default:
1764 NOTREACHED();
1765 GotoState(STATE_VERIFY_CERT);
1766 }
1767
1768 return OK;
[email protected]b24713592010-08-11 19:50:021769}
1770
[email protected]2345cc52009-06-04 09:18:471771int SSLClientSocketNSS::DoVerifyCert(int result) {
1772 DCHECK(server_cert_);
1773 GotoState(STATE_VERIFY_CERT_COMPLETE);
[email protected]f6555ad2009-06-23 06:35:051774 int flags = 0;
[email protected]a89eda42010-02-18 01:45:391775
[email protected]dd681aa2010-07-26 20:35:181776 if (ssl_config_.rev_checking_enabled)
[email protected]f6555ad2009-06-23 06:35:051777 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
1778 if (ssl_config_.verify_ev_cert)
1779 flags |= X509Certificate::VERIFY_EV_CERT;
[email protected]92d9cad2009-06-25 23:40:241780 verifier_.reset(new CertVerifier);
1781 return verifier_->Verify(server_cert_, hostname_, flags,
[email protected]a3ff5e92009-10-13 04:48:061782 &server_cert_verify_result_,
1783 &handshake_io_callback_);
[email protected]2345cc52009-06-04 09:18:471784}
1785
1786// Derived from AuthCertificateCallback() in
1787// mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp.
1788int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
[email protected]92d9cad2009-06-25 23:40:241789 verifier_.reset();
1790
[email protected]c07a2eb2009-06-08 04:49:351791 if (result == OK) {
[email protected]bf0136d2009-05-29 05:55:041792 // Remember the intermediate CA certs if the server sends them to us.
[email protected]52f3fad2009-09-21 19:27:361793 //
1794 // We used to remember the intermediate CA certs in the NSS database
1795 // persistently. However, NSS opens a connection to the SQLite database
1796 // during NSS initialization and doesn't close the connection until NSS
1797 // shuts down. If the file system where the database resides is gone,
1798 // the database connection goes bad. What's worse, the connection won't
1799 // recover when the file system comes back. Until this NSS or SQLite bug
1800 // is fixed, we need to avoid using the NSS database for non-essential
1801 // purposes. See https://bugzilla.mozilla.org/show_bug.cgi?id=508081 and
1802 // http://crbug.com/15630 for more info.
[email protected]c07a2eb2009-06-08 04:49:351803 CERTCertList* cert_list = CERT_GetCertChainFromCert(
[email protected]f505a9b2010-01-28 19:44:021804 server_cert_nss_, PR_Now(), certUsageSSLCA);
[email protected]c07a2eb2009-06-08 04:49:351805 if (cert_list) {
1806 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
1807 !CERT_LIST_END(node, cert_list);
1808 node = CERT_LIST_NEXT(node)) {
1809 if (node->cert->slot || node->cert->isRoot || node->cert->isperm ||
[email protected]f505a9b2010-01-28 19:44:021810 node->cert == server_cert_nss_) {
[email protected]c07a2eb2009-06-08 04:49:351811 // Some certs we don't want to remember are:
1812 // - found on a token.
1813 // - the root cert.
1814 // - already stored in perm db.
1815 // - the server cert itself.
1816 continue;
1817 }
[email protected]bf0136d2009-05-29 05:55:041818
[email protected]c07a2eb2009-06-08 04:49:351819 // We have found a CA cert that we want to remember.
[email protected]52f3fad2009-09-21 19:27:361820 // TODO(wtc): Remember the intermediate CA certs in a std::set
1821 // temporarily (http://crbug.com/15630).
[email protected]bf0136d2009-05-29 05:55:041822 }
[email protected]c07a2eb2009-06-08 04:49:351823 CERT_DestroyCertList(cert_list);
[email protected]bf0136d2009-05-29 05:55:041824 }
1825 }
1826
[email protected]2345cc52009-06-04 09:18:471827 // If we have been explicitly told to accept this certificate, override the
1828 // result of verifier_.Verify.
1829 // Eventually, we should cache the cert verification results so that we don't
1830 // need to call verifier_.Verify repeatedly. But for now we need to do this.
[email protected]127017872009-08-13 17:54:421831 // Alternatively, we could use the cert's status that we stored along with
1832 // the cert in the allowed_bad_certs vector.
[email protected]2345cc52009-06-04 09:18:471833 if (IsCertificateError(result) &&
[email protected]127017872009-08-13 17:54:421834 ssl_config_.IsAllowedBadCert(server_cert_)) {
[email protected]bacff652009-03-31 17:50:331835 LOG(INFO) << "accepting bad SSL certificate, as user told us to";
[email protected]2345cc52009-06-04 09:18:471836 result = OK;
[email protected]b43c97c2008-10-22 19:50:581837 }
[email protected]ea224582008-12-07 20:25:461838
[email protected]2345cc52009-06-04 09:18:471839 completed_handshake_ = true;
[email protected]f6ee0a012010-03-05 22:00:241840 // TODO(ukai): we may not need this call because it is now harmless to have a
[email protected]2345cc52009-06-04 09:18:471841 // session with a bad cert.
1842 InvalidateSessionIfBadCertificate();
[email protected]a3ff5e92009-10-13 04:48:061843 // Exit DoHandshakeLoop and return the result to the caller to Connect.
1844 DCHECK(next_handshake_state_ == STATE_NONE);
[email protected]2345cc52009-06-04 09:18:471845 return result;
[email protected]b43c97c2008-10-22 19:50:581846}
[email protected]ea224582008-12-07 20:25:461847
[email protected]b43c97c2008-10-22 19:50:581848int SSLClientSocketNSS::DoPayloadRead() {
[email protected]a3ff5e92009-10-13 04:48:061849 EnterFunction(user_read_buf_len_);
1850 DCHECK(user_read_buf_);
[email protected]1d583612010-03-12 17:47:141851 DCHECK_GT(user_read_buf_len_, 0);
[email protected]a3ff5e92009-10-13 04:48:061852 int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_);
[email protected]d84b3722009-10-15 21:23:371853 if (client_auth_cert_needed_) {
1854 // We don't need to invalidate the non-client-authenticated SSL session
1855 // because the server will renegotiate anyway.
1856 LeaveFunction("");
1857 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
1858 }
[email protected]e17b4c12008-11-05 22:04:081859 if (rv >= 0) {
[email protected]a3ff5e92009-10-13 04:48:061860 LogData(user_read_buf_->data(), rv);
[email protected]e17b4c12008-11-05 22:04:081861 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581862 return rv;
[email protected]e17b4c12008-11-05 22:04:081863 }
[email protected]b43c97c2008-10-22 19:50:581864 PRErrorCode prerr = PR_GetError();
1865 if (prerr == PR_WOULD_BLOCK_ERROR) {
[email protected]e17b4c12008-11-05 22:04:081866 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581867 return ERR_IO_PENDING;
1868 }
[email protected]e17b4c12008-11-05 22:04:081869 LeaveFunction("");
[email protected]2e9a5b6982010-01-15 22:29:031870 return MapNSPRError(prerr);
[email protected]b43c97c2008-10-22 19:50:581871}
1872
1873int SSLClientSocketNSS::DoPayloadWrite() {
[email protected]a3ff5e92009-10-13 04:48:061874 EnterFunction(user_write_buf_len_);
1875 DCHECK(user_write_buf_);
1876 int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
[email protected]e17b4c12008-11-05 22:04:081877 if (rv >= 0) {
[email protected]a3ff5e92009-10-13 04:48:061878 LogData(user_write_buf_->data(), rv);
[email protected]e17b4c12008-11-05 22:04:081879 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581880 return rv;
[email protected]e17b4c12008-11-05 22:04:081881 }
[email protected]b43c97c2008-10-22 19:50:581882 PRErrorCode prerr = PR_GetError();
1883 if (prerr == PR_WOULD_BLOCK_ERROR) {
[email protected]4d3040f42010-04-14 02:40:201884 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581885 return ERR_IO_PENDING;
1886 }
[email protected]e17b4c12008-11-05 22:04:081887 LeaveFunction("");
[email protected]2e9a5b6982010-01-15 22:29:031888 return MapNSPRError(prerr);
[email protected]b43c97c2008-10-22 19:50:581889}
1890
1891} // namespace net