blob: 15c11c182d610c97ca6981205a922a7be6158176 [file] [log] [blame]
[email protected]0b45559b2009-06-12 21:45:111// Copyright (c) 2006-2009 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]d84b3722009-10-15 21:23:3754#include <keyhi.h>
[email protected]b43c97c2008-10-22 19:50:5855#include <nspr.h>
56#include <nss.h>
[email protected]ea224582008-12-07 20:25:4657#include <secerr.h>
[email protected]b43c97c2008-10-22 19:50:5858#include <ssl.h>
[email protected]ea224582008-12-07 20:25:4659#include <sslerr.h>
[email protected]b43c97c2008-10-22 19:50:5860#include <pk11pub.h>
[email protected]b43c97c2008-10-22 19:50:5861
[email protected]bacff652009-03-31 17:50:3362#include "base/compiler_specific.h"
[email protected]b43c97c2008-10-22 19:50:5863#include "base/logging.h"
[email protected]1b1a264a2010-01-14 22:36:3564#include "base/nss_util.h"
[email protected]829296f2010-01-27 02:58:0365#include "base/singleton.h"
[email protected]b43c97c2008-10-22 19:50:5866#include "base/string_util.h"
[email protected]ac9eec62010-02-20 18:50:3867#include "net/base/address_list.h"
[email protected]92d9cad2009-06-25 23:40:2468#include "net/base/cert_verifier.h"
[email protected]597cf6e2009-05-29 09:43:2669#include "net/base/io_buffer.h"
[email protected]9e743cd2010-03-16 07:03:5370#include "net/base/net_log.h"
[email protected]b43c97c2008-10-22 19:50:5871#include "net/base/net_errors.h"
[email protected]d84b3722009-10-15 21:23:3772#include "net/base/ssl_cert_request_info.h"
[email protected]b43c97c2008-10-22 19:50:5873#include "net/base/ssl_info.h"
[email protected]ac9eec62010-02-20 18:50:3874#include "net/base/sys_addrinfo.h"
[email protected]2a0c0a52009-07-31 07:51:3275#include "net/ocsp/nss_ocsp.h"
[email protected]b43c97c2008-10-22 19:50:5876
77static const int kRecvBufferSize = 4096;
78
[email protected]b43c97c2008-10-22 19:50:5879namespace net {
80
[email protected]e17b4c12008-11-05 22:04:0881// State machines are easier to debug if you log state transitions.
82// Enable these if you want to see what's going on.
83#if 1
84#define EnterFunction(x)
85#define LeaveFunction(x)
[email protected]a3ff5e92009-10-13 04:48:0686#define GotoState(s) next_handshake_state_ = s
[email protected]ea224582008-12-07 20:25:4687#define LogData(s, len)
[email protected]e17b4c12008-11-05 22:04:0888#else
89#define EnterFunction(x) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \
[email protected]a3ff5e92009-10-13 04:48:0690 " enter " << x << \
91 "; next_handshake_state " << next_handshake_state_
[email protected]e17b4c12008-11-05 22:04:0892#define LeaveFunction(x) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \
[email protected]a3ff5e92009-10-13 04:48:0693 " leave " << x << \
94 "; next_handshake_state " << next_handshake_state_
[email protected]e17b4c12008-11-05 22:04:0895#define GotoState(s) do { LOG(INFO) << (void *)this << " " << __FUNCTION__ << \
[email protected]a3ff5e92009-10-13 04:48:0696 " jump to state " << s; \
97 next_handshake_state_ = s; } while (0)
[email protected]ea224582008-12-07 20:25:4698#define LogData(s, len) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \
99 " data [" << std::string(s, len) << "]";
100
[email protected]e17b4c12008-11-05 22:04:08101#endif
102
[email protected]ea224582008-12-07 20:25:46103namespace {
104
[email protected]829296f2010-01-27 02:58:03105class NSSSSLInitSingleton {
106 public:
107 NSSSSLInitSingleton() {
108 base::EnsureNSSInit();
109
110 NSS_SetDomesticPolicy();
111
112#if defined(USE_SYSTEM_SSL)
113 // Use late binding to avoid scary but benign warning
114 // "Symbol `SSL_ImplementedCiphers' has different size in shared object,
115 // consider re-linking"
116 const PRUint16* pSSL_ImplementedCiphers = static_cast<const PRUint16*>(
117 dlsym(RTLD_DEFAULT, "SSL_ImplementedCiphers"));
118 if (pSSL_ImplementedCiphers == NULL) {
119 NOTREACHED() << "Can't get list of supported ciphers";
120 return;
121 }
122#else
123#define pSSL_ImplementedCiphers SSL_ImplementedCiphers
124#endif
125
126 // Explicitly enable exactly those ciphers with keys of at least 80 bits
127 for (int i = 0; i < SSL_NumImplementedCiphers; i++) {
128 SSLCipherSuiteInfo info;
129 if (SSL_GetCipherSuiteInfo(pSSL_ImplementedCiphers[i], &info,
130 sizeof(info)) == SECSuccess) {
131 SSL_CipherPrefSetDefault(pSSL_ImplementedCiphers[i],
132 (info.effectiveKeyBits >= 80));
133 }
134 }
135
136 // Enable SSL.
137 SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE);
138
139 // All other SSL options are set per-session by SSLClientSocket.
140 }
141
142 ~NSSSSLInitSingleton() {
143 // Have to clear the cache, or NSS_Shutdown fails with SEC_ERROR_BUSY.
144 SSL_ClearSessionCache();
145 }
146};
147
148// Initialize the NSS SSL library if it isn't already initialized. This must
149// be called before any other NSS SSL functions. This function is
150// thread-safe, and the NSS SSL library will only ever be initialized once.
151// The NSS SSL library will be properly shut down on program exit.
152void EnsureNSSSSLInit() {
153 Singleton<NSSSSLInitSingleton>::get();
154}
155
[email protected]2e9a5b6982010-01-15 22:29:03156// The default error mapping function.
157// Maps an NSPR error code to a network error code.
158int MapNSPRError(PRErrorCode err) {
[email protected]ea224582008-12-07 20:25:46159 // TODO(port): fill this out as we learn what's important
160 switch (err) {
161 case PR_WOULD_BLOCK_ERROR:
162 return ERR_IO_PENDING;
[email protected]b0735462009-11-04 22:11:26163 case PR_ADDRESS_NOT_SUPPORTED_ERROR: // For connect.
164 case PR_NO_ACCESS_RIGHTS_ERROR:
165 return ERR_ACCESS_DENIED;
166 case PR_IO_TIMEOUT_ERROR:
167 return ERR_TIMED_OUT;
168 case PR_CONNECT_RESET_ERROR:
169 return ERR_CONNECTION_RESET;
170 case PR_CONNECT_ABORTED_ERROR:
171 return ERR_CONNECTION_ABORTED;
172 case PR_CONNECT_REFUSED_ERROR:
173 return ERR_CONNECTION_REFUSED;
174 case PR_HOST_UNREACHABLE_ERROR:
175 case PR_NETWORK_UNREACHABLE_ERROR:
176 return ERR_ADDRESS_UNREACHABLE;
177 case PR_ADDRESS_NOT_AVAILABLE_ERROR:
178 return ERR_ADDRESS_INVALID;
179
[email protected]ea224582008-12-07 20:25:46180 case SSL_ERROR_NO_CYPHER_OVERLAP:
[email protected]2e9a5b6982010-01-15 22:29:03181 case SSL_ERROR_UNSUPPORTED_VERSION:
[email protected]ea224582008-12-07 20:25:46182 return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
[email protected]d84b3722009-10-15 21:23:37183 case SSL_ERROR_HANDSHAKE_FAILURE_ALERT:
184 return ERR_SSL_PROTOCOL_ERROR;
[email protected]ea224582008-12-07 20:25:46185
186 default: {
187 if (IS_SSL_ERROR(err)) {
188 LOG(WARNING) << "Unknown SSL error " << err <<
189 " mapped to net::ERR_SSL_PROTOCOL_ERROR";
190 return ERR_SSL_PROTOCOL_ERROR;
191 }
[email protected]ea224582008-12-07 20:25:46192 LOG(WARNING) << "Unknown error " << err <<
193 " mapped to net::ERR_FAILED";
194 return ERR_FAILED;
195 }
196 }
197}
198
[email protected]2e9a5b6982010-01-15 22:29:03199// Context-sensitive error mapping functions.
200
201int MapHandshakeError(PRErrorCode err) {
202 switch (err) {
203 // If the server closed on us, it is a protocol error.
204 // Some TLS-intolerant servers do this when we request TLS.
205 case PR_END_OF_FILE_ERROR:
206 // The handshake may fail because some signature (for example, the
207 // signature in the ServerKeyExchange message for an ephemeral
208 // Diffie-Hellman cipher suite) is invalid.
209 case SEC_ERROR_BAD_SIGNATURE:
210 return ERR_SSL_PROTOCOL_ERROR;
211 default:
212 return MapNSPRError(err);
213 }
214}
215
[email protected]ea224582008-12-07 20:25:46216} // namespace
217
[email protected]f505a9b2010-01-28 19:44:02218#if defined(OS_WIN)
219// static
220HCERTSTORE SSLClientSocketNSS::cert_store_ = NULL;
221#endif
[email protected]b43c97c2008-10-22 19:50:58222
223SSLClientSocketNSS::SSLClientSocketNSS(ClientSocket* transport_socket,
224 const std::string& hostname,
225 const SSLConfig& ssl_config)
[email protected]f505a9b2010-01-28 19:44:02226 : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_(
227 this, &SSLClientSocketNSS::BufferSendComplete)),
228 ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_(
229 this, &SSLClientSocketNSS::BufferRecvComplete)),
[email protected]b43c97c2008-10-22 19:50:58230 transport_send_busy_(false),
231 transport_recv_busy_(false),
[email protected]f505a9b2010-01-28 19:44:02232 ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_(
233 this, &SSLClientSocketNSS::OnHandshakeIOComplete)),
[email protected]b43c97c2008-10-22 19:50:58234 transport_(transport_socket),
235 hostname_(hostname),
236 ssl_config_(ssl_config),
[email protected]a6eb576292009-06-30 16:19:00237 user_connect_callback_(NULL),
[email protected]a3ff5e92009-10-13 04:48:06238 user_read_callback_(NULL),
239 user_write_callback_(NULL),
240 user_read_buf_len_(0),
241 user_write_buf_len_(0),
[email protected]f505a9b2010-01-28 19:44:02242 server_cert_nss_(NULL),
[email protected]d84b3722009-10-15 21:23:37243 client_auth_cert_needed_(false),
[email protected]b43c97c2008-10-22 19:50:58244 completed_handshake_(false),
[email protected]a3ff5e92009-10-13 04:48:06245 next_handshake_state_(STATE_NONE),
[email protected]b43c97c2008-10-22 19:50:58246 nss_fd_(NULL),
247 nss_bufs_(NULL) {
[email protected]e17b4c12008-11-05 22:04:08248 EnterFunction("");
[email protected]b43c97c2008-10-22 19:50:58249}
250
251SSLClientSocketNSS::~SSLClientSocketNSS() {
[email protected]e17b4c12008-11-05 22:04:08252 EnterFunction("");
[email protected]b43c97c2008-10-22 19:50:58253 Disconnect();
[email protected]e17b4c12008-11-05 22:04:08254 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:58255}
256
257int SSLClientSocketNSS::Init() {
[email protected]e17b4c12008-11-05 22:04:08258 EnterFunction("");
[email protected]829296f2010-01-27 02:58:03259 // Initialize the NSS SSL library in a threadsafe way. This also
260 // initializes the NSS base library.
261 EnsureNSSSSLInit();
[email protected]f505a9b2010-01-28 19:44:02262#if !defined(OS_WIN)
[email protected]2a0c0a52009-07-31 07:51:32263 // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop
264 // by MessageLoopForIO::current().
265 // X509Certificate::Verify() runs on a worker thread of CertVerifier.
266 EnsureOCSPInit();
[email protected]f505a9b2010-01-28 19:44:02267#endif
[email protected]b43c97c2008-10-22 19:50:58268
[email protected]e17b4c12008-11-05 22:04:08269 LeaveFunction("");
270 return OK;
[email protected]b43c97c2008-10-22 19:50:58271}
272
[email protected]5a05c47a2009-11-02 23:25:19273int SSLClientSocketNSS::Connect(CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53274 const BoundNetLog& net_log) {
[email protected]e17b4c12008-11-05 22:04:08275 EnterFunction("");
[email protected]b43c97c2008-10-22 19:50:58276 DCHECK(transport_.get());
[email protected]a3ff5e92009-10-13 04:48:06277 DCHECK(next_handshake_state_ == STATE_NONE);
278 DCHECK(!user_read_callback_);
279 DCHECK(!user_write_callback_);
[email protected]a6eb576292009-06-30 16:19:00280 DCHECK(!user_connect_callback_);
[email protected]a3ff5e92009-10-13 04:48:06281 DCHECK(!user_read_buf_);
282 DCHECK(!user_write_buf_);
[email protected]b43c97c2008-10-22 19:50:58283
[email protected]9e743cd2010-03-16 07:03:53284 net_log.BeginEvent(NetLog::TYPE_SSL_CONNECT);
[email protected]5a05c47a2009-11-02 23:25:19285
[email protected]0ef0bcf2009-04-03 20:39:43286 if (Init() != OK) {
287 NOTREACHED() << "Couldn't initialize nss";
288 }
289
[email protected]5a05c47a2009-11-02 23:25:19290 int rv = InitializeSSLOptions();
291 if (rv != OK) {
[email protected]9e743cd2010-03-16 07:03:53292 net_log.EndEvent(NetLog::TYPE_SSL_CONNECT);
[email protected]5a05c47a2009-11-02 23:25:19293 return rv;
294 }
295
296 GotoState(STATE_HANDSHAKE);
297 rv = DoHandshakeLoop(OK);
298 if (rv == ERR_IO_PENDING) {
299 user_connect_callback_ = callback;
[email protected]9e743cd2010-03-16 07:03:53300 net_log_ = net_log;
[email protected]5a05c47a2009-11-02 23:25:19301 } else {
[email protected]9e743cd2010-03-16 07:03:53302 net_log.EndEvent(NetLog::TYPE_SSL_CONNECT);
[email protected]5a05c47a2009-11-02 23:25:19303 }
304
305 LeaveFunction("");
306 return rv > OK ? OK : rv;
307}
308
309int SSLClientSocketNSS::InitializeSSLOptions() {
[email protected]0ef0bcf2009-04-03 20:39:43310 // Transport connected, now hook it up to nss
311 // TODO(port): specify rx and tx buffer sizes separately
312 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize);
313 if (nss_fd_ == NULL) {
[email protected]38a18722009-12-04 00:09:04314 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code.
[email protected]0ef0bcf2009-04-03 20:39:43315 }
316
317 // Tell NSS who we're connected to
[email protected]ac9eec62010-02-20 18:50:38318 AddressList peer_address;
319 int err = transport_->GetPeerAddress(&peer_address);
320 if (err != OK)
321 return err;
[email protected]f32c1732010-03-31 05:12:02322
[email protected]ac9eec62010-02-20 18:50:38323 const struct addrinfo* ai = peer_address.head();
[email protected]f32c1732010-03-31 05:12:02324
325 PRNetAddr peername;
326 memset(&peername, 0, sizeof(peername));
327 DCHECK_LE(ai->ai_addrlen, sizeof(peername));
328 size_t len = std::min(static_cast<size_t>(ai->ai_addrlen), sizeof(peername));
329 memcpy(&peername, ai->ai_addr, len);
330
331 // Adjust the address family field for BSD, whose sockaddr
332 // structure has a one-byte length and one-byte address family
333 // field at the beginning. PRNetAddr has a two-byte address
334 // family field at the beginning.
335 peername.raw.family = ai->ai_addr->sa_family;
336
337 memio_SetPeerName(nss_fd_, &peername);
[email protected]0ef0bcf2009-04-03 20:39:43338
339 // Grab pointer to buffers
340 nss_bufs_ = memio_GetSecret(nss_fd_);
341
342 /* Create SSL state machine */
343 /* Push SSL onto our fake I/O socket */
344 nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
345 if (nss_fd_ == NULL) {
[email protected]38a18722009-12-04 00:09:04346 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR/NSS error code.
[email protected]0ef0bcf2009-04-03 20:39:43347 }
348 // TODO(port): set more ssl options! Check errors!
349
350 int rv;
351
352 rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
353 if (rv != SECSuccess)
354 return ERR_UNEXPECTED;
355
356 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, ssl_config_.ssl2_enabled);
357 if (rv != SECSuccess)
358 return ERR_UNEXPECTED;
359
360 // SNI is enabled automatically if TLS is enabled -- as long as
361 // SSL_V2_COMPATIBLE_HELLO isn't.
362 // So don't do V2 compatible hellos unless we're really using SSL2,
363 // to avoid errors like
364 // "common name `mail.google.com' != requested host name `gmail.com'"
365 rv = SSL_OptionSet(nss_fd_, SSL_V2_COMPATIBLE_HELLO,
366 ssl_config_.ssl2_enabled);
367 if (rv != SECSuccess)
368 return ERR_UNEXPECTED;
369
370 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL3, ssl_config_.ssl3_enabled);
371 if (rv != SECSuccess)
372 return ERR_UNEXPECTED;
373
374 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_TLS, ssl_config_.tls1_enabled);
375 if (rv != SECSuccess)
376 return ERR_UNEXPECTED;
377
378#ifdef SSL_ENABLE_SESSION_TICKETS
379 // Support RFC 5077
380 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
381 if (rv != SECSuccess)
382 LOG(INFO) << "SSL_ENABLE_SESSION_TICKETS failed. Old system nss?";
383#else
384 #error "You need to install NSS-3.12 or later to build chromium"
385#endif
386
[email protected]7e52ed72009-11-17 00:40:12387#ifdef SSL_ENABLE_DEFLATE
[email protected]074c1582010-01-08 21:38:28388 // Some web servers have been found to break if TLS is used *or* if DEFLATE
389 // is advertised. Thus, if TLS is disabled (probably because we are doing
390 // SSLv3 fallback), we disable DEFLATE also.
391 // See http://crbug.com/31628
392 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_DEFLATE, ssl_config_.tls1_enabled);
[email protected]7e52ed72009-11-17 00:40:12393 if (rv != SECSuccess)
394 LOG(INFO) << "SSL_ENABLE_DEFLATE failed. Old system nss?";
395#endif
396
[email protected]c2def1c2010-03-02 21:40:34397#ifdef SSL_ENABLE_FALSE_START
398 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_FALSE_START, PR_TRUE);
399 if (rv != SECSuccess)
400 LOG(INFO) << "SSL_ENABLE_FALSE_START failed. Old system nss?";
401#endif
402
[email protected]33b3eb92010-01-06 01:35:04403#ifdef SSL_ENABLE_RENEGOTIATION
404 // We allow servers to request renegotiation. Since we're a client,
405 // prohibiting this is rather a waste of time. Only servers are in a position
406 // to prevent renegotiation attacks.
407 // http://extendedsubset.com/?p=8
408 //
409 // This should be changed when NSS 3.12.6 comes out with support for the
410 // renegotiation info extension.
411 // http://code.google.com/p/chromium/issues/detail?id=31647
412 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_RENEGOTIATION,
413 SSL_RENEGOTIATE_UNRESTRICTED);
414 if (rv != SECSuccess)
415 LOG(INFO) << "SSL_ENABLE_RENEGOTIATION failed.";
416#endif
417
[email protected]644bdca2009-11-30 20:40:53418#ifdef SSL_NEXT_PROTO_NEGOTIATED
419 if (!ssl_config_.next_protos.empty()) {
420 rv = SSL_SetNextProtoNego(
421 nss_fd_,
422 reinterpret_cast<const unsigned char *>(ssl_config_.next_protos.data()),
423 ssl_config_.next_protos.size());
424 if (rv != SECSuccess)
425 LOG(INFO) << "SSL_SetNextProtoNego failed.";
426 }
427#endif
428
[email protected]0ef0bcf2009-04-03 20:39:43429 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
430 if (rv != SECSuccess)
431 return ERR_UNEXPECTED;
432
433 rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
434 if (rv != SECSuccess)
435 return ERR_UNEXPECTED;
436
[email protected]d84b3722009-10-15 21:23:37437 rv = SSL_GetClientAuthDataHook(nss_fd_, ClientAuthHandler, this);
438 if (rv != SECSuccess)
439 return ERR_UNEXPECTED;
440
[email protected]2345cc52009-06-04 09:18:47441 rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
[email protected]0ef0bcf2009-04-03 20:39:43442 if (rv != SECSuccess)
[email protected]2345cc52009-06-04 09:18:47443 return ERR_UNEXPECTED;
[email protected]0ef0bcf2009-04-03 20:39:43444
445 // Tell SSL the hostname we're trying to connect to.
446 SSL_SetURL(nss_fd_, hostname_.c_str());
447
[email protected]52c27fb2009-11-30 22:40:23448 // Set the peer ID for session reuse. This is necessary when we create an
449 // SSL tunnel through a proxy -- GetPeerName returns the proxy's address
450 // rather than the destination server's address in that case.
[email protected]ac9eec62010-02-20 18:50:38451 // TODO(wtc): port in |peer_address| is not the server's port when a proxy is
452 // used.
[email protected]52c27fb2009-11-30 22:40:23453 std::string peer_id = StringPrintf("%s:%d", hostname_.c_str(),
[email protected]ac9eec62010-02-20 18:50:38454 peer_address.GetPort());
[email protected]52c27fb2009-11-30 22:40:23455 rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str()));
456 if (rv != SECSuccess)
457 LOG(INFO) << "SSL_SetSockPeerID failed: peer_id=" << peer_id;
458
[email protected]0ef0bcf2009-04-03 20:39:43459 // Tell SSL we're a client; needed if not letting NSPR do socket I/O
460 SSL_ResetHandshake(nss_fd_, 0);
461
[email protected]5a05c47a2009-11-02 23:25:19462 return OK;
[email protected]b43c97c2008-10-22 19:50:58463}
464
[email protected]bacff652009-03-31 17:50:33465void SSLClientSocketNSS::InvalidateSessionIfBadCertificate() {
466 if (UpdateServerCert() != NULL &&
[email protected]127017872009-08-13 17:54:42467 ssl_config_.IsAllowedBadCert(server_cert_)) {
[email protected]bacff652009-03-31 17:50:33468 SSL_InvalidateSession(nss_fd_);
469 }
[email protected]b43c97c2008-10-22 19:50:58470}
471
472void SSLClientSocketNSS::Disconnect() {
[email protected]e17b4c12008-11-05 22:04:08473 EnterFunction("");
[email protected]bacff652009-03-31 17:50:33474
[email protected]b43c97c2008-10-22 19:50:58475 // TODO(wtc): Send SSL close_notify alert.
476 if (nss_fd_ != NULL) {
[email protected]bacff652009-03-31 17:50:33477 InvalidateSessionIfBadCertificate();
[email protected]b43c97c2008-10-22 19:50:58478 PR_Close(nss_fd_);
479 nss_fd_ = NULL;
480 }
[email protected]bacff652009-03-31 17:50:33481
[email protected]92d9cad2009-06-25 23:40:24482 // Shut down anything that may call us back (through buffer_send_callback_,
[email protected]a3ff5e92009-10-13 04:48:06483 // buffer_recv_callback, or handshake_io_callback_).
[email protected]92d9cad2009-06-25 23:40:24484 verifier_.reset();
[email protected]b43c97c2008-10-22 19:50:58485 transport_->Disconnect();
[email protected]bf0136d2009-05-29 05:55:04486
487 // Reset object state
[email protected]a6eb576292009-06-30 16:19:00488 transport_send_busy_ = false;
489 transport_recv_busy_ = false;
490 user_connect_callback_ = NULL;
[email protected]a3ff5e92009-10-13 04:48:06491 user_read_callback_ = NULL;
492 user_write_callback_ = NULL;
493 user_read_buf_ = NULL;
494 user_read_buf_len_ = 0;
495 user_write_buf_ = NULL;
496 user_write_buf_len_ = 0;
[email protected]a6eb576292009-06-30 16:19:00497 server_cert_ = NULL;
[email protected]f505a9b2010-01-28 19:44:02498 if (server_cert_nss_) {
499 CERT_DestroyCertificate(server_cert_nss_);
500 server_cert_nss_ = NULL;
501 }
[email protected]2345cc52009-06-04 09:18:47502 server_cert_verify_result_.Reset();
[email protected]a6eb576292009-06-30 16:19:00503 completed_handshake_ = false;
504 nss_bufs_ = NULL;
[email protected]b8fee152009-10-24 03:39:31505 client_certs_.clear();
[email protected]d84b3722009-10-15 21:23:37506 client_auth_cert_needed_ = false;
[email protected]bf0136d2009-05-29 05:55:04507
[email protected]e17b4c12008-11-05 22:04:08508 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:58509}
510
511bool SSLClientSocketNSS::IsConnected() const {
[email protected]b2197852009-02-19 23:27:33512 // Ideally, we should also check if we have received the close_notify alert
513 // message from the server, and return false in that case. We're not doing
514 // that, so this function may return a false positive. Since the upper
515 // layer (HttpNetworkTransaction) needs to handle a persistent connection
516 // closed by the server when we send a request anyway, a false positive in
517 // exchange for simpler code is a good trade-off.
[email protected]e17b4c12008-11-05 22:04:08518 EnterFunction("");
519 bool ret = completed_handshake_ && transport_->IsConnected();
520 LeaveFunction("");
521 return ret;
[email protected]b43c97c2008-10-22 19:50:58522}
523
[email protected]b2197852009-02-19 23:27:33524bool SSLClientSocketNSS::IsConnectedAndIdle() const {
525 // Unlike IsConnected, this method doesn't return a false positive.
526 //
527 // Strictly speaking, we should check if we have received the close_notify
528 // alert message from the server, and return false in that case. Although
529 // the close_notify alert message means EOF in the SSL layer, it is just
530 // bytes to the transport layer below, so transport_->IsConnectedAndIdle()
531 // returns the desired false when we receive close_notify.
532 EnterFunction("");
533 bool ret = completed_handshake_ && transport_->IsConnectedAndIdle();
534 LeaveFunction("");
535 return ret;
536}
537
[email protected]ac9eec62010-02-20 18:50:38538int SSLClientSocketNSS::GetPeerAddress(AddressList* address) const {
539 return transport_->GetPeerAddress(address);
[email protected]9f864b32010-01-20 15:01:16540}
541
[email protected]ffeb0882009-04-30 21:51:25542int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len,
[email protected]ea224582008-12-07 20:25:46543 CompletionCallback* callback) {
[email protected]e17b4c12008-11-05 22:04:08544 EnterFunction(buf_len);
[email protected]b43c97c2008-10-22 19:50:58545 DCHECK(completed_handshake_);
[email protected]a3ff5e92009-10-13 04:48:06546 DCHECK(next_handshake_state_ == STATE_NONE);
547 DCHECK(!user_read_callback_);
[email protected]a6eb576292009-06-30 16:19:00548 DCHECK(!user_connect_callback_);
[email protected]a3ff5e92009-10-13 04:48:06549 DCHECK(!user_read_buf_);
550 DCHECK(nss_bufs_);
[email protected]b43c97c2008-10-22 19:50:58551
[email protected]a3ff5e92009-10-13 04:48:06552 user_read_buf_ = buf;
553 user_read_buf_len_ = buf_len;
[email protected]b43c97c2008-10-22 19:50:58554
[email protected]a3ff5e92009-10-13 04:48:06555 int rv = DoReadLoop(OK);
556
[email protected]1d583612010-03-12 17:47:14557 if (rv == ERR_IO_PENDING) {
[email protected]a3ff5e92009-10-13 04:48:06558 user_read_callback_ = callback;
[email protected]1d583612010-03-12 17:47:14559 } else {
[email protected]a3ff5e92009-10-13 04:48:06560 user_read_buf_ = NULL;
561 user_read_buf_len_ = 0;
562 }
[email protected]ea224582008-12-07 20:25:46563 LeaveFunction(rv);
[email protected]b43c97c2008-10-22 19:50:58564 return rv;
565}
566
[email protected]ffeb0882009-04-30 21:51:25567int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len,
[email protected]a3ff5e92009-10-13 04:48:06568 CompletionCallback* callback) {
[email protected]e17b4c12008-11-05 22:04:08569 EnterFunction(buf_len);
[email protected]b43c97c2008-10-22 19:50:58570 DCHECK(completed_handshake_);
[email protected]a3ff5e92009-10-13 04:48:06571 DCHECK(next_handshake_state_ == STATE_NONE);
572 DCHECK(!user_write_callback_);
[email protected]a6eb576292009-06-30 16:19:00573 DCHECK(!user_connect_callback_);
[email protected]a3ff5e92009-10-13 04:48:06574 DCHECK(!user_write_buf_);
575 DCHECK(nss_bufs_);
[email protected]b43c97c2008-10-22 19:50:58576
[email protected]a3ff5e92009-10-13 04:48:06577 user_write_buf_ = buf;
578 user_write_buf_len_ = buf_len;
[email protected]b43c97c2008-10-22 19:50:58579
[email protected]a3ff5e92009-10-13 04:48:06580 int rv = DoWriteLoop(OK);
581
[email protected]1d583612010-03-12 17:47:14582 if (rv == ERR_IO_PENDING) {
[email protected]a3ff5e92009-10-13 04:48:06583 user_write_callback_ = callback;
[email protected]1d583612010-03-12 17:47:14584 } else {
[email protected]a3ff5e92009-10-13 04:48:06585 user_write_buf_ = NULL;
586 user_write_buf_len_ = 0;
587 }
[email protected]ea224582008-12-07 20:25:46588 LeaveFunction(rv);
[email protected]b43c97c2008-10-22 19:50:58589 return rv;
590}
591
[email protected]d3f66572009-09-09 22:38:04592bool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) {
593 return transport_->SetReceiveBufferSize(size);
594}
595
596bool SSLClientSocketNSS::SetSendBufferSize(int32 size) {
597 return transport_->SetSendBufferSize(size);
598}
599
[email protected]bacff652009-03-31 17:50:33600X509Certificate *SSLClientSocketNSS::UpdateServerCert() {
601 // We set the server_cert_ from OwnAuthCertHandler(), but this handler
602 // does not necessarily get called if we are continuing a cached SSL
603 // session.
604 if (server_cert_ == NULL) {
[email protected]f505a9b2010-01-28 19:44:02605 server_cert_nss_ = SSL_PeerCertificate(nss_fd_);
606 if (server_cert_nss_) {
607#if defined(OS_WIN)
608 // TODO(wtc): close cert_store_ at shutdown.
609 if (!cert_store_)
610 cert_store_ = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL);
611
[email protected]4bee851c2010-03-05 23:44:45612 // Get each of the intermediate certificates in the server's chain.
613 // These will be added to the server's X509Certificate object, making
614 // them available to X509Certificate::Verify() for chain building.
615 X509Certificate::OSCertHandles intermediate_ca_certs;
[email protected]f505a9b2010-01-28 19:44:02616 PCCERT_CONTEXT cert_context = NULL;
[email protected]4bee851c2010-03-05 23:44:45617 CERTCertList* cert_list = CERT_GetCertChainFromCert(
618 server_cert_nss_, PR_Now(), certUsageSSLCA);
619 if (cert_list) {
620 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
621 !CERT_LIST_END(node, cert_list);
622 node = CERT_LIST_NEXT(node)) {
623 cert_context = NULL;
624 BOOL ok = CertAddEncodedCertificateToStore(
625 cert_store_,
626 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
627 node->cert->derCert.data,
628 node->cert->derCert.len,
629 CERT_STORE_ADD_USE_EXISTING,
630 &cert_context);
631 DCHECK(ok);
632 if (node->cert != server_cert_nss_)
633 intermediate_ca_certs.push_back(cert_context);
634 }
635 CERT_DestroyCertList(cert_list);
636 }
637
638 // Finally create the X509Certificate object.
[email protected]f505a9b2010-01-28 19:44:02639 BOOL ok = CertAddEncodedCertificateToStore(
640 cert_store_,
641 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
642 server_cert_nss_->derCert.data,
643 server_cert_nss_->derCert.len,
644 CERT_STORE_ADD_USE_EXISTING,
645 &cert_context);
646 DCHECK(ok);
[email protected]bacff652009-03-31 17:50:33647 server_cert_ = X509Certificate::CreateFromHandle(
[email protected]4bee851c2010-03-05 23:44:45648 cert_context,
649 X509Certificate::SOURCE_FROM_NETWORK,
650 intermediate_ca_certs);
651 for (size_t i = 0; i < intermediate_ca_certs.size(); ++i)
652 CertFreeCertificateContext(intermediate_ca_certs[i]);
[email protected]f505a9b2010-01-28 19:44:02653#else
654 server_cert_ = X509Certificate::CreateFromHandle(
655 CERT_DupCertificate(server_cert_nss_),
[email protected]4bee851c2010-03-05 23:44:45656 X509Certificate::SOURCE_FROM_NETWORK,
657 X509Certificate::OSCertHandles());
[email protected]f505a9b2010-01-28 19:44:02658#endif
[email protected]bacff652009-03-31 17:50:33659 }
660 }
661 return server_cert_;
662}
663
[email protected]1e7cd2c72010-02-27 01:31:19664// Log an informational message if the server does not support secure
665// renegotiation (RFC 5746).
666void SSLClientSocketNSS::CheckSecureRenegotiation() const {
667 // SSL_HandshakeNegotiatedExtension was added in NSS 3.12.6.
668 // Since SSL_MAX_EXTENSIONS was added at the same time, we can test
669 // SSL_MAX_EXTENSIONS for the presence of SSL_HandshakeNegotiatedExtension.
670#if defined(SSL_MAX_EXTENSIONS)
671 PRBool received_renego_info;
672 if (SSL_HandshakeNegotiatedExtension(nss_fd_, ssl_renegotiation_info_xtn,
673 &received_renego_info) == SECSuccess &&
674 !received_renego_info) {
675 LOG(INFO) << "The server " << hostname_
[email protected]d48fd7b2010-03-03 22:46:13676 << " does not support the TLS renegotiation_info extension.";
[email protected]1e7cd2c72010-02-27 01:31:19677 }
678#endif
679}
680
[email protected]b43c97c2008-10-22 19:50:58681void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
[email protected]e17b4c12008-11-05 22:04:08682 EnterFunction("");
[email protected]b43c97c2008-10-22 19:50:58683 ssl_info->Reset();
[email protected]2345cc52009-06-04 09:18:47684 if (!server_cert_)
685 return;
686
[email protected]ea224582008-12-07 20:25:46687 SSLChannelInfo channel_info;
688 SECStatus ok = SSL_GetChannelInfo(nss_fd_,
689 &channel_info, sizeof(channel_info));
[email protected]9f8821ed2008-12-09 18:02:37690 if (ok == SECSuccess &&
691 channel_info.length == sizeof(channel_info) &&
692 channel_info.cipherSuite) {
[email protected]ea224582008-12-07 20:25:46693 SSLCipherSuiteInfo cipher_info;
694 ok = SSL_GetCipherSuiteInfo(channel_info.cipherSuite,
695 &cipher_info, sizeof(cipher_info));
696 if (ok == SECSuccess) {
697 ssl_info->security_bits = cipher_info.effectiveKeyBits;
698 } else {
699 ssl_info->security_bits = -1;
[email protected]9f8821ed2008-12-09 18:02:37700 LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError()
701 << " for cipherSuite " << channel_info.cipherSuite;
[email protected]ea224582008-12-07 20:25:46702 }
[email protected]bacff652009-03-31 17:50:33703 UpdateServerCert();
[email protected]ea224582008-12-07 20:25:46704 }
[email protected]2345cc52009-06-04 09:18:47705 ssl_info->cert_status = server_cert_verify_result_.cert_status;
[email protected]bacff652009-03-31 17:50:33706 DCHECK(server_cert_ != NULL);
707 ssl_info->cert = server_cert_;
[email protected]644bdca2009-11-30 20:40:53708
[email protected]e17b4c12008-11-05 22:04:08709 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:58710}
711
[email protected]0b45559b2009-06-12 21:45:11712void SSLClientSocketNSS::GetSSLCertRequestInfo(
713 SSLCertRequestInfo* cert_request_info) {
[email protected]d84b3722009-10-15 21:23:37714 EnterFunction("");
[email protected]1d583612010-03-12 17:47:14715 cert_request_info->host_and_port = hostname_; // TODO(wtc): no port!
[email protected]b8fee152009-10-24 03:39:31716 cert_request_info->client_certs = client_certs_;
[email protected]d84b3722009-10-15 21:23:37717 LeaveFunction(cert_request_info->client_certs.size());
[email protected]0b45559b2009-06-12 21:45:11718}
719
[email protected]b28f19d72009-12-10 21:52:27720SSLClientSocket::NextProtoStatus
[email protected]f49ea7d2009-12-11 20:03:50721SSLClientSocketNSS::GetNextProto(std::string* proto) {
722#if defined(SSL_NEXT_PROTO_NEGOTIATED)
723 unsigned char buf[255];
[email protected]b28f19d72009-12-10 21:52:27724 int state;
725 unsigned len;
726 SECStatus rv = SSL_GetNextProto(nss_fd_, &state, buf, &len, sizeof(buf));
727 if (rv != SECSuccess) {
728 NOTREACHED() << "Error return from SSL_GetNextProto: " << rv;
729 proto->clear();
730 return kNextProtoUnsupported;
731 }
[email protected]f49ea7d2009-12-11 20:03:50732 // We don't check for truncation because sizeof(buf) is large enough to hold
733 // the maximum protocol size.
[email protected]829296f2010-01-27 02:58:03734 switch (state) {
[email protected]f49ea7d2009-12-11 20:03:50735 case SSL_NEXT_PROTO_NO_SUPPORT:
736 proto->clear();
737 return kNextProtoUnsupported;
738 case SSL_NEXT_PROTO_NEGOTIATED:
739 *proto = std::string(reinterpret_cast<char*>(buf), len);
740 return kNextProtoNegotiated;
741 case SSL_NEXT_PROTO_NO_OVERLAP:
742 *proto = std::string(reinterpret_cast<char*>(buf), len);
743 return kNextProtoNoOverlap;
744 default:
745 NOTREACHED() << "Unknown status from SSL_GetNextProto: " << state;
746 proto->clear();
747 return kNextProtoUnsupported;
[email protected]b28f19d72009-12-10 21:52:27748 }
[email protected]f49ea7d2009-12-11 20:03:50749#else
750 // No NPN support in the libssl that we are building with.
751 proto->clear();
752 return kNextProtoUnsupported;
[email protected]b28f19d72009-12-10 21:52:27753#endif
754}
755
[email protected]a3ff5e92009-10-13 04:48:06756void SSLClientSocketNSS::DoReadCallback(int rv) {
[email protected]e17b4c12008-11-05 22:04:08757 EnterFunction(rv);
[email protected]b43c97c2008-10-22 19:50:58758 DCHECK(rv != ERR_IO_PENDING);
[email protected]a3ff5e92009-10-13 04:48:06759 DCHECK(user_read_callback_);
[email protected]b43c97c2008-10-22 19:50:58760
[email protected]a3ff5e92009-10-13 04:48:06761 // Since Run may result in Read being called, clear |user_read_callback_|
762 // up front.
763 CompletionCallback* c = user_read_callback_;
764 user_read_callback_ = NULL;
765 user_read_buf_ = NULL;
766 user_read_buf_len_ = 0;
767 c->Run(rv);
768 LeaveFunction("");
769}
770
771void SSLClientSocketNSS::DoWriteCallback(int rv) {
772 EnterFunction(rv);
773 DCHECK(rv != ERR_IO_PENDING);
774 DCHECK(user_write_callback_);
775
776 // Since Run may result in Write being called, clear |user_write_callback_|
777 // up front.
778 CompletionCallback* c = user_write_callback_;
779 user_write_callback_ = NULL;
780 user_write_buf_ = NULL;
781 user_write_buf_len_ = 0;
[email protected]b43c97c2008-10-22 19:50:58782 c->Run(rv);
[email protected]e17b4c12008-11-05 22:04:08783 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:58784}
785
[email protected]a6eb576292009-06-30 16:19:00786// As part of Connect(), the SSLClientSocketNSS object performs an SSL
787// handshake. This requires network IO, which in turn calls
788// BufferRecvComplete() with a non-zero byte count. This byte count eventually
789// winds its way through the state machine and ends up being passed to the
790// callback. For Read() and Write(), that's what we want. But for Connect(),
791// the caller expects OK (i.e. 0) for success.
792//
793void SSLClientSocketNSS::DoConnectCallback(int rv) {
794 EnterFunction(rv);
795 DCHECK_NE(rv, ERR_IO_PENDING);
796 DCHECK(user_connect_callback_);
797
[email protected]a6eb576292009-06-30 16:19:00798 CompletionCallback* c = user_connect_callback_;
799 user_connect_callback_ = NULL;
800 c->Run(rv > OK ? OK : rv);
801 LeaveFunction("");
802}
803
[email protected]a3ff5e92009-10-13 04:48:06804void SSLClientSocketNSS::OnHandshakeIOComplete(int result) {
[email protected]e17b4c12008-11-05 22:04:08805 EnterFunction(result);
[email protected]a3ff5e92009-10-13 04:48:06806 int rv = DoHandshakeLoop(result);
[email protected]5a05c47a2009-11-02 23:25:19807 if (rv != ERR_IO_PENDING) {
[email protected]9e743cd2010-03-16 07:03:53808 net_log_.EndEvent(net::NetLog::TYPE_SSL_CONNECT);
809 net_log_ = BoundNetLog();
[email protected]a3ff5e92009-10-13 04:48:06810 DoConnectCallback(rv);
[email protected]5a05c47a2009-11-02 23:25:19811 }
[email protected]a3ff5e92009-10-13 04:48:06812 LeaveFunction("");
813}
814
815void SSLClientSocketNSS::OnSendComplete(int result) {
816 EnterFunction(result);
[email protected]45965de2010-02-25 23:23:31817 if (next_handshake_state_ == STATE_HANDSHAKE) {
[email protected]a3ff5e92009-10-13 04:48:06818 // In handshake phase.
819 OnHandshakeIOComplete(result);
820 LeaveFunction("");
821 return;
[email protected]a6eb576292009-06-30 16:19:00822 }
[email protected]a3ff5e92009-10-13 04:48:06823
824 // OnSendComplete may need to call DoPayloadRead while the renegotiation
825 // handshake is in progress.
826 int rv_read = ERR_IO_PENDING;
827 int rv_write = ERR_IO_PENDING;
828 bool network_moved;
829 do {
830 if (user_read_buf_)
831 rv_read = DoPayloadRead();
832 if (user_write_buf_)
833 rv_write = DoPayloadWrite();
834 network_moved = DoTransportIO();
835 } while (rv_read == ERR_IO_PENDING &&
836 rv_write == ERR_IO_PENDING &&
837 network_moved);
838
839 if (user_read_buf_ && rv_read != ERR_IO_PENDING)
840 DoReadCallback(rv_read);
841 if (user_write_buf_ && rv_write != ERR_IO_PENDING)
842 DoWriteCallback(rv_write);
843
844 LeaveFunction("");
845}
846
847void SSLClientSocketNSS::OnRecvComplete(int result) {
848 EnterFunction(result);
[email protected]45965de2010-02-25 23:23:31849 if (next_handshake_state_ == STATE_HANDSHAKE) {
[email protected]a3ff5e92009-10-13 04:48:06850 // In handshake phase.
851 OnHandshakeIOComplete(result);
852 LeaveFunction("");
853 return;
854 }
855
856 // Network layer received some data, check if client requested to read
857 // decrypted data.
858 if (!user_read_buf_) {
859 LeaveFunction("");
860 return;
861 }
862
863 int rv = DoReadLoop(result);
864 if (rv != ERR_IO_PENDING)
865 DoReadCallback(rv);
[email protected]e17b4c12008-11-05 22:04:08866 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:58867}
868
[email protected]b0735462009-11-04 22:11:26869// Map a Chromium net error code to an NSS error code.
[email protected]b43c97c2008-10-22 19:50:58870// See _MD_unix_map_default_error in the NSS source
871// tree for inspiration.
872static PRErrorCode MapErrorToNSS(int result) {
873 if (result >=0)
874 return result;
[email protected]b0735462009-11-04 22:11:26875
876 switch (result) {
877 case ERR_IO_PENDING:
878 return PR_WOULD_BLOCK_ERROR;
879 case ERR_ACCESS_DENIED:
880 // For connect, this could be mapped to PR_ADDRESS_NOT_SUPPORTED_ERROR.
881 return PR_NO_ACCESS_RIGHTS_ERROR;
882 case ERR_INTERNET_DISCONNECTED: // Equivalent to ENETDOWN.
883 return PR_NETWORK_UNREACHABLE_ERROR; // Best approximation.
884 case ERR_CONNECTION_TIMED_OUT:
885 case ERR_TIMED_OUT:
886 return PR_IO_TIMEOUT_ERROR;
887 case ERR_CONNECTION_RESET:
888 return PR_CONNECT_RESET_ERROR;
889 case ERR_CONNECTION_ABORTED:
890 return PR_CONNECT_ABORTED_ERROR;
891 case ERR_CONNECTION_REFUSED:
892 return PR_CONNECT_REFUSED_ERROR;
893 case ERR_ADDRESS_UNREACHABLE:
894 return PR_HOST_UNREACHABLE_ERROR; // Also PR_NETWORK_UNREACHABLE_ERROR.
895 case ERR_ADDRESS_INVALID:
896 return PR_ADDRESS_NOT_AVAILABLE_ERROR;
897 default:
898 LOG(WARNING) << "MapErrorToNSS " << result
899 << " mapped to PR_UNKNOWN_ERROR";
900 return PR_UNKNOWN_ERROR;
901 }
[email protected]b43c97c2008-10-22 19:50:58902}
903
[email protected]ffeb0882009-04-30 21:51:25904// Do network I/O between the given buffer and the given socket.
[email protected]a3ff5e92009-10-13 04:48:06905// Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING)
906bool SSLClientSocketNSS::DoTransportIO() {
907 EnterFunction("");
908 bool network_moved = false;
909 if (nss_bufs_ != NULL) {
910 int nsent = BufferSend();
911 int nreceived = BufferRecv();
912 network_moved = (nsent > 0 || nreceived >= 0);
913 }
914 LeaveFunction(network_moved);
915 return network_moved;
916}
917
[email protected]ffeb0882009-04-30 21:51:25918// Return 0 for EOF,
919// > 0 for bytes transferred immediately,
920// < 0 for error (or the non-error ERR_IO_PENDING).
[email protected]b43c97c2008-10-22 19:50:58921int SSLClientSocketNSS::BufferSend(void) {
922 if (transport_send_busy_) return ERR_IO_PENDING;
923
[email protected]914286d62009-12-10 23:06:44924 int nsent = 0;
925 EnterFunction("");
926 // nss_bufs_ is a circular buffer. It may have two contiguous parts
927 // (before and after the wrap). So this for loop needs two iterations.
928 for (int i = 0; i < 2; ++i) {
929 const char* buf;
930 int nb = memio_GetWriteParams(nss_bufs_, &buf);
931 if (!nb)
932 break;
[email protected]b43c97c2008-10-22 19:50:58933
[email protected]ffeb0882009-04-30 21:51:25934 scoped_refptr<IOBuffer> send_buffer = new IOBuffer(nb);
935 memcpy(send_buffer->data(), buf, nb);
[email protected]914286d62009-12-10 23:06:44936 int rv = transport_->Write(send_buffer, nb, &buffer_send_callback_);
937 if (rv == ERR_IO_PENDING) {
[email protected]b43c97c2008-10-22 19:50:58938 transport_send_busy_ = true;
[email protected]914286d62009-12-10 23:06:44939 break;
940 } else {
[email protected]b43c97c2008-10-22 19:50:58941 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
[email protected]914286d62009-12-10 23:06:44942 if (rv < 0) {
943 // Return the error even if the previous Write succeeded.
944 nsent = rv;
945 break;
946 }
947 nsent += rv;
948 }
[email protected]b43c97c2008-10-22 19:50:58949 }
950
[email protected]914286d62009-12-10 23:06:44951 LeaveFunction(nsent);
952 return nsent;
[email protected]b43c97c2008-10-22 19:50:58953}
954
955void SSLClientSocketNSS::BufferSendComplete(int result) {
[email protected]e17b4c12008-11-05 22:04:08956 EnterFunction(result);
[email protected]b0735462009-11-04 22:11:26957 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
[email protected]b43c97c2008-10-22 19:50:58958 transport_send_busy_ = false;
[email protected]a3ff5e92009-10-13 04:48:06959 OnSendComplete(result);
[email protected]e17b4c12008-11-05 22:04:08960 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:58961}
962
963
964int SSLClientSocketNSS::BufferRecv(void) {
[email protected]b43c97c2008-10-22 19:50:58965 if (transport_recv_busy_) return ERR_IO_PENDING;
966
967 char *buf;
968 int nb = memio_GetReadParams(nss_bufs_, &buf);
[email protected]e17b4c12008-11-05 22:04:08969 EnterFunction(nb);
[email protected]b43c97c2008-10-22 19:50:58970 int rv;
971 if (!nb) {
972 // buffer too full to read into, so no I/O possible at moment
973 rv = ERR_IO_PENDING;
974 } else {
[email protected]ffeb0882009-04-30 21:51:25975 recv_buffer_ = new IOBuffer(nb);
976 rv = transport_->Read(recv_buffer_, nb, &buffer_recv_callback_);
977 if (rv == ERR_IO_PENDING) {
[email protected]b43c97c2008-10-22 19:50:58978 transport_recv_busy_ = true;
[email protected]ffeb0882009-04-30 21:51:25979 } else {
980 if (rv > 0)
981 memcpy(buf, recv_buffer_->data(), rv);
[email protected]b43c97c2008-10-22 19:50:58982 memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
[email protected]ffeb0882009-04-30 21:51:25983 recv_buffer_ = NULL;
984 }
[email protected]b43c97c2008-10-22 19:50:58985 }
[email protected]e17b4c12008-11-05 22:04:08986 LeaveFunction(rv);
[email protected]b43c97c2008-10-22 19:50:58987 return rv;
988}
989
990void SSLClientSocketNSS::BufferRecvComplete(int result) {
[email protected]e17b4c12008-11-05 22:04:08991 EnterFunction(result);
[email protected]ffeb0882009-04-30 21:51:25992 if (result > 0) {
993 char *buf;
994 memio_GetReadParams(nss_bufs_, &buf);
995 memcpy(buf, recv_buffer_->data(), result);
996 }
997 recv_buffer_ = NULL;
[email protected]b0735462009-11-04 22:11:26998 memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
[email protected]b43c97c2008-10-22 19:50:58999 transport_recv_busy_ = false;
[email protected]a3ff5e92009-10-13 04:48:061000 OnRecvComplete(result);
[email protected]e17b4c12008-11-05 22:04:081001 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581002}
1003
[email protected]a3ff5e92009-10-13 04:48:061004int SSLClientSocketNSS::DoHandshakeLoop(int last_io_result) {
[email protected]e17b4c12008-11-05 22:04:081005 EnterFunction(last_io_result);
[email protected]b43c97c2008-10-22 19:50:581006 bool network_moved;
1007 int rv = last_io_result;
1008 do {
[email protected]e17b4c12008-11-05 22:04:081009 // Default to STATE_NONE for next state.
[email protected]ea224582008-12-07 20:25:461010 // (This is a quirk carried over from the windows
[email protected]e17b4c12008-11-05 22:04:081011 // implementation. It makes reading the logs a bit harder.)
[email protected]ea224582008-12-07 20:25:461012 // State handlers can and often do call GotoState just
[email protected]e17b4c12008-11-05 22:04:081013 // to stay in the current state.
[email protected]a3ff5e92009-10-13 04:48:061014 State state = next_handshake_state_;
[email protected]e17b4c12008-11-05 22:04:081015 GotoState(STATE_NONE);
[email protected]b43c97c2008-10-22 19:50:581016 switch (state) {
[email protected]e17b4c12008-11-05 22:04:081017 case STATE_NONE:
1018 // we're just pumping data between the buffer and the network
1019 break;
[email protected]a3ff5e92009-10-13 04:48:061020 case STATE_HANDSHAKE:
1021 rv = DoHandshake();
[email protected]b43c97c2008-10-22 19:50:581022 break;
[email protected]2345cc52009-06-04 09:18:471023 case STATE_VERIFY_CERT:
1024 DCHECK(rv == OK);
1025 rv = DoVerifyCert(rv);
1026 break;
1027 case STATE_VERIFY_CERT_COMPLETE:
1028 rv = DoVerifyCertComplete(rv);
1029 break;
[email protected]b43c97c2008-10-22 19:50:581030 default:
1031 rv = ERR_UNEXPECTED;
1032 NOTREACHED() << "unexpected state";
1033 break;
1034 }
1035
1036 // Do the actual network I/O
[email protected]a3ff5e92009-10-13 04:48:061037 network_moved = DoTransportIO();
[email protected]72d1e592009-03-10 17:39:461038 } while ((rv != ERR_IO_PENDING || network_moved) &&
[email protected]a3ff5e92009-10-13 04:48:061039 next_handshake_state_ != STATE_NONE);
1040 LeaveFunction("");
1041 return rv;
1042}
1043
1044int SSLClientSocketNSS::DoReadLoop(int result) {
1045 EnterFunction("");
1046 DCHECK(completed_handshake_);
1047 DCHECK(next_handshake_state_ == STATE_NONE);
1048
1049 if (result < 0)
1050 return result;
1051
1052 if (!nss_bufs_)
1053 return ERR_UNEXPECTED;
1054
1055 bool network_moved;
1056 int rv;
1057 do {
1058 rv = DoPayloadRead();
1059 network_moved = DoTransportIO();
1060 } while (rv == ERR_IO_PENDING && network_moved);
1061
1062 LeaveFunction("");
1063 return rv;
1064}
1065
1066int SSLClientSocketNSS::DoWriteLoop(int result) {
1067 EnterFunction("");
1068 DCHECK(completed_handshake_);
1069 DCHECK(next_handshake_state_ == STATE_NONE);
1070
1071 if (result < 0)
1072 return result;
1073
1074 if (!nss_bufs_)
1075 return ERR_UNEXPECTED;
1076
1077 bool network_moved;
1078 int rv;
1079 do {
1080 rv = DoPayloadWrite();
1081 network_moved = DoTransportIO();
1082 } while (rv == ERR_IO_PENDING && network_moved);
1083
[email protected]e17b4c12008-11-05 22:04:081084 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581085 return rv;
1086}
1087
[email protected]bacff652009-03-31 17:50:331088// static
1089// NSS calls this if an incoming certificate needs to be verified.
[email protected]2345cc52009-06-04 09:18:471090// Do nothing but return SECSuccess.
1091// This is called only in full handshake mode.
1092// Peer certificate is retrieved in HandshakeCallback() later, which is called
1093// in full handshake mode or in resumption handshake mode.
[email protected]bacff652009-03-31 17:50:331094SECStatus SSLClientSocketNSS::OwnAuthCertHandler(void* arg,
1095 PRFileDesc* socket,
1096 PRBool checksig,
1097 PRBool is_server) {
[email protected]2345cc52009-06-04 09:18:471098 // Tell NSS to not verify the certificate.
1099 return SECSuccess;
1100}
1101
1102// static
[email protected]d84b3722009-10-15 21:23:371103// NSS calls this if a client certificate is needed.
1104// Based on Mozilla's NSS_GetClientAuthData.
1105SECStatus SSLClientSocketNSS::ClientAuthHandler(
1106 void* arg,
1107 PRFileDesc* socket,
1108 CERTDistNames* ca_names,
1109 CERTCertificate** result_certificate,
1110 SECKEYPrivateKey** result_private_key) {
[email protected]d84b3722009-10-15 21:23:371111 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg);
1112
1113 that->client_auth_cert_needed_ = !that->ssl_config_.send_client_cert;
1114
[email protected]1d583612010-03-12 17:47:141115#if defined(OS_WIN)
1116 if (that->ssl_config_.send_client_cert) {
1117 // TODO(wtc): SSLClientSocketNSS can't do SSL client authentication using
1118 // CryptoAPI yet (http://crbug.com/37560), so client_cert must be NULL.
1119 DCHECK(!that->ssl_config_.client_cert);
1120 // Send no client certificate.
1121 return SECFailure;
1122 }
1123
1124 that->client_certs_.clear();
1125
1126 std::vector<CERT_NAME_BLOB> issuer_list(ca_names->nnames);
1127 for (int i = 0; i < ca_names->nnames; ++i) {
1128 issuer_list[i].cbData = ca_names->names[i].len;
1129 issuer_list[i].pbData = ca_names->names[i].data;
1130 }
1131
1132 // Client certificates of the user are in the "MY" system certificate store.
1133 HCERTSTORE my_cert_store = CertOpenSystemStore(NULL, L"MY");
1134 if (!my_cert_store) {
1135 LOG(ERROR) << "Could not open the \"MY\" system certificate store: "
1136 << GetLastError();
1137 return SECFailure;
1138 }
1139
1140 // Enumerate the client certificates.
1141 CERT_CHAIN_FIND_BY_ISSUER_PARA find_by_issuer_para;
1142 memset(&find_by_issuer_para, 0, sizeof(find_by_issuer_para));
1143 find_by_issuer_para.cbSize = sizeof(find_by_issuer_para);
1144 find_by_issuer_para.pszUsageIdentifier = szOID_PKIX_KP_CLIENT_AUTH;
1145 find_by_issuer_para.cIssuer = ca_names->nnames;
1146 find_by_issuer_para.rgIssuer = ca_names->nnames ? &issuer_list[0] : NULL;
1147
1148 PCCERT_CHAIN_CONTEXT chain_context = NULL;
1149
1150 for (;;) {
1151 // Find a certificate chain.
1152 chain_context = CertFindChainInStore(my_cert_store,
1153 X509_ASN_ENCODING,
1154 0,
1155 CERT_CHAIN_FIND_BY_ISSUER,
1156 &find_by_issuer_para,
1157 chain_context);
1158 if (!chain_context) {
1159 DWORD err = GetLastError();
1160 if (err != CRYPT_E_NOT_FOUND)
1161 DLOG(ERROR) << "CertFindChainInStore failed: " << err;
1162 break;
1163 }
1164
1165 // Get the leaf certificate.
1166 PCCERT_CONTEXT cert_context =
1167 chain_context->rgpChain[0]->rgpElement[0]->pCertContext;
1168 // Copy it to our own certificate store, so that we can close the "MY"
1169 // certificate store before returning from this function.
1170 PCCERT_CONTEXT cert_context2;
1171 BOOL ok = CertAddCertificateContextToStore(cert_store_, cert_context,
1172 CERT_STORE_ADD_USE_EXISTING,
1173 &cert_context2);
1174 if (!ok) {
1175 NOTREACHED();
1176 continue;
1177 }
1178 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle(
1179 cert_context2, X509Certificate::SOURCE_LONE_CERT_IMPORT,
1180 net::X509Certificate::OSCertHandles());
1181 that->client_certs_.push_back(cert);
1182 }
1183
1184 BOOL ok = CertCloseStore(my_cert_store, CERT_CLOSE_STORE_CHECK_FLAG);
1185 DCHECK(ok);
1186
1187 // Tell NSS to suspend the client authentication. We will then abort the
1188 // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
1189 return SECWouldBlock;
1190#else
[email protected]b8fee152009-10-24 03:39:311191 CERTCertificate* cert = NULL;
1192 SECKEYPrivateKey* privkey = NULL;
1193 void* wincx = SSL_RevealPinArg(socket);
1194
[email protected]d84b3722009-10-15 21:23:371195 // Second pass: a client certificate should have been selected.
1196 if (that->ssl_config_.send_client_cert) {
1197 if (that->ssl_config_.client_cert) {
[email protected]b8fee152009-10-24 03:39:311198 cert = CERT_DupCertificate(
[email protected]d84b3722009-10-15 21:23:371199 that->ssl_config_.client_cert->os_cert_handle());
[email protected]b8fee152009-10-24 03:39:311200 privkey = PK11_FindKeyByAnyCert(cert, wincx);
[email protected]d84b3722009-10-15 21:23:371201 if (privkey) {
1202 // TODO(jsorianopastor): We should wait for server certificate
1203 // verification before sending our credentials. See
1204 // http://crbug.com/13934.
1205 *result_certificate = cert;
1206 *result_private_key = privkey;
1207 return SECSuccess;
1208 }
1209 LOG(WARNING) << "Client cert found without private key";
1210 }
1211 // Send no client certificate.
1212 return SECFailure;
1213 }
1214
[email protected]b8fee152009-10-24 03:39:311215 CERTCertNicknames* names = CERT_GetCertNicknames(
1216 CERT_GetDefaultCertDB(), SEC_CERT_NICKNAMES_USER, wincx);
1217 if (names) {
1218 for (int i = 0; i < names->numnicknames; ++i) {
1219 cert = CERT_FindUserCertByUsage(
1220 CERT_GetDefaultCertDB(), names->nicknames[i],
1221 certUsageSSLClient, PR_FALSE, wincx);
1222 if (!cert)
1223 continue;
1224 // Only check unexpired certs.
1225 if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_TRUE) ==
1226 secCertTimeValid &&
1227 NSS_CmpCertChainWCANames(cert, ca_names) == SECSuccess) {
1228 privkey = PK11_FindKeyByAnyCert(cert, wincx);
1229 if (privkey) {
1230 X509Certificate* x509_cert = X509Certificate::CreateFromHandle(
[email protected]4bee851c2010-03-05 23:44:451231 cert, X509Certificate::SOURCE_LONE_CERT_IMPORT,
1232 net::X509Certificate::OSCertHandles());
[email protected]b8fee152009-10-24 03:39:311233 that->client_certs_.push_back(x509_cert);
1234 SECKEY_DestroyPrivateKey(privkey);
1235 continue;
1236 }
1237 }
1238 CERT_DestroyCertificate(cert);
1239 }
1240 CERT_FreeNicknames(names);
1241 }
[email protected]d84b3722009-10-15 21:23:371242
[email protected]f6ee0a012010-03-05 22:00:241243 // Tell NSS to suspend the client authentication. We will then abort the
1244 // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
1245 return SECWouldBlock;
[email protected]f505a9b2010-01-28 19:44:021246#endif
[email protected]d84b3722009-10-15 21:23:371247}
1248
1249// static
[email protected]2345cc52009-06-04 09:18:471250// NSS calls this when handshake is completed.
1251// After the SSL handshake is finished, use CertVerifier to verify
1252// the saved server certificate.
1253void SSLClientSocketNSS::HandshakeCallback(PRFileDesc* socket,
1254 void* arg) {
[email protected]bacff652009-03-31 17:50:331255 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg);
1256
[email protected]2345cc52009-06-04 09:18:471257 that->UpdateServerCert();
[email protected]1e7cd2c72010-02-27 01:31:191258
1259 that->CheckSecureRenegotiation();
[email protected]2345cc52009-06-04 09:18:471260}
[email protected]bacff652009-03-31 17:50:331261
[email protected]a3ff5e92009-10-13 04:48:061262int SSLClientSocketNSS::DoHandshake() {
[email protected]2345cc52009-06-04 09:18:471263 EnterFunction("");
1264 int net_error = net::OK;
[email protected]d84b3722009-10-15 21:23:371265 SECStatus rv = SSL_ForceHandshake(nss_fd_);
[email protected]2345cc52009-06-04 09:18:471266
[email protected]d84b3722009-10-15 21:23:371267 if (client_auth_cert_needed_) {
1268 net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
1269 // If the handshake already succeeded (because the server requests but
1270 // doesn't require a client cert), we need to invalidate the SSL session
1271 // so that we won't try to resume the non-client-authenticated session in
1272 // the next handshake. This will cause the server to ask for a client
1273 // cert again.
1274 if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess) {
1275 LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError();
1276 }
1277 } else if (rv == SECSuccess) {
[email protected]2345cc52009-06-04 09:18:471278 // SSL handshake is completed. Let's verify the certificate.
1279 GotoState(STATE_VERIFY_CERT);
1280 // Done!
1281 } else {
1282 PRErrorCode prerr = PR_GetError();
[email protected]2e9a5b6982010-01-15 22:29:031283 net_error = MapHandshakeError(prerr);
[email protected]2345cc52009-06-04 09:18:471284
1285 // If not done, stay in this state
1286 if (net_error == ERR_IO_PENDING) {
[email protected]a3ff5e92009-10-13 04:48:061287 GotoState(STATE_HANDSHAKE);
[email protected]2345cc52009-06-04 09:18:471288 } else {
1289 LOG(ERROR) << "handshake failed; NSS error code " << prerr
1290 << ", net_error " << net_error;
1291 }
1292 }
1293
1294 LeaveFunction("");
1295 return net_error;
1296}
1297
1298int SSLClientSocketNSS::DoVerifyCert(int result) {
1299 DCHECK(server_cert_);
1300 GotoState(STATE_VERIFY_CERT_COMPLETE);
[email protected]f6555ad2009-06-23 06:35:051301 int flags = 0;
[email protected]a89eda42010-02-18 01:45:391302
1303 /* Disable revocation checking for SPDY. This is a hack, but we ignore
1304 * certificate errors for SPDY anyway so it's no loss in security. This lets
1305 * us benchmark as if we had OCSP stapling.
1306 *
1307 * http://crbug.com/32020
1308 */
1309 unsigned char buf[255];
1310 int state;
1311 unsigned int len;
1312 SECStatus rv = SSL_GetNextProto(nss_fd_, &state, buf, &len, sizeof(buf));
1313 bool spdy = (rv == SECSuccess && state == SSL_NEXT_PROTO_NEGOTIATED &&
1314 len == 4 && memcmp(buf, "spdy", 4) == 0);
1315
1316 if (ssl_config_.rev_checking_enabled && !spdy)
[email protected]f6555ad2009-06-23 06:35:051317 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
1318 if (ssl_config_.verify_ev_cert)
1319 flags |= X509Certificate::VERIFY_EV_CERT;
[email protected]92d9cad2009-06-25 23:40:241320 verifier_.reset(new CertVerifier);
1321 return verifier_->Verify(server_cert_, hostname_, flags,
[email protected]a3ff5e92009-10-13 04:48:061322 &server_cert_verify_result_,
1323 &handshake_io_callback_);
[email protected]2345cc52009-06-04 09:18:471324}
1325
1326// Derived from AuthCertificateCallback() in
1327// mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp.
1328int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
[email protected]92d9cad2009-06-25 23:40:241329 DCHECK(verifier_.get());
1330 verifier_.reset();
1331
[email protected]c07a2eb2009-06-08 04:49:351332 if (result == OK) {
[email protected]bf0136d2009-05-29 05:55:041333 // Remember the intermediate CA certs if the server sends them to us.
[email protected]52f3fad2009-09-21 19:27:361334 //
1335 // We used to remember the intermediate CA certs in the NSS database
1336 // persistently. However, NSS opens a connection to the SQLite database
1337 // during NSS initialization and doesn't close the connection until NSS
1338 // shuts down. If the file system where the database resides is gone,
1339 // the database connection goes bad. What's worse, the connection won't
1340 // recover when the file system comes back. Until this NSS or SQLite bug
1341 // is fixed, we need to avoid using the NSS database for non-essential
1342 // purposes. See https://bugzilla.mozilla.org/show_bug.cgi?id=508081 and
1343 // http://crbug.com/15630 for more info.
[email protected]c07a2eb2009-06-08 04:49:351344 CERTCertList* cert_list = CERT_GetCertChainFromCert(
[email protected]f505a9b2010-01-28 19:44:021345 server_cert_nss_, PR_Now(), certUsageSSLCA);
[email protected]c07a2eb2009-06-08 04:49:351346 if (cert_list) {
1347 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
1348 !CERT_LIST_END(node, cert_list);
1349 node = CERT_LIST_NEXT(node)) {
1350 if (node->cert->slot || node->cert->isRoot || node->cert->isperm ||
[email protected]f505a9b2010-01-28 19:44:021351 node->cert == server_cert_nss_) {
[email protected]c07a2eb2009-06-08 04:49:351352 // Some certs we don't want to remember are:
1353 // - found on a token.
1354 // - the root cert.
1355 // - already stored in perm db.
1356 // - the server cert itself.
1357 continue;
1358 }
[email protected]bf0136d2009-05-29 05:55:041359
[email protected]c07a2eb2009-06-08 04:49:351360 // We have found a CA cert that we want to remember.
[email protected]52f3fad2009-09-21 19:27:361361 // TODO(wtc): Remember the intermediate CA certs in a std::set
1362 // temporarily (http://crbug.com/15630).
[email protected]bf0136d2009-05-29 05:55:041363 }
[email protected]c07a2eb2009-06-08 04:49:351364 CERT_DestroyCertList(cert_list);
[email protected]bf0136d2009-05-29 05:55:041365 }
1366 }
1367
[email protected]2345cc52009-06-04 09:18:471368 // If we have been explicitly told to accept this certificate, override the
1369 // result of verifier_.Verify.
1370 // Eventually, we should cache the cert verification results so that we don't
1371 // need to call verifier_.Verify repeatedly. But for now we need to do this.
[email protected]127017872009-08-13 17:54:421372 // Alternatively, we could use the cert's status that we stored along with
1373 // the cert in the allowed_bad_certs vector.
[email protected]2345cc52009-06-04 09:18:471374 if (IsCertificateError(result) &&
[email protected]127017872009-08-13 17:54:421375 ssl_config_.IsAllowedBadCert(server_cert_)) {
[email protected]bacff652009-03-31 17:50:331376 LOG(INFO) << "accepting bad SSL certificate, as user told us to";
[email protected]2345cc52009-06-04 09:18:471377 result = OK;
[email protected]b43c97c2008-10-22 19:50:581378 }
[email protected]ea224582008-12-07 20:25:461379
[email protected]2345cc52009-06-04 09:18:471380 completed_handshake_ = true;
[email protected]f6ee0a012010-03-05 22:00:241381 // TODO(ukai): we may not need this call because it is now harmless to have a
[email protected]2345cc52009-06-04 09:18:471382 // session with a bad cert.
1383 InvalidateSessionIfBadCertificate();
[email protected]a3ff5e92009-10-13 04:48:061384 // Exit DoHandshakeLoop and return the result to the caller to Connect.
1385 DCHECK(next_handshake_state_ == STATE_NONE);
[email protected]2345cc52009-06-04 09:18:471386 return result;
[email protected]b43c97c2008-10-22 19:50:581387}
[email protected]ea224582008-12-07 20:25:461388
[email protected]b43c97c2008-10-22 19:50:581389int SSLClientSocketNSS::DoPayloadRead() {
[email protected]a3ff5e92009-10-13 04:48:061390 EnterFunction(user_read_buf_len_);
1391 DCHECK(user_read_buf_);
[email protected]1d583612010-03-12 17:47:141392 DCHECK_GT(user_read_buf_len_, 0);
[email protected]a3ff5e92009-10-13 04:48:061393 int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_);
[email protected]d84b3722009-10-15 21:23:371394 if (client_auth_cert_needed_) {
1395 // We don't need to invalidate the non-client-authenticated SSL session
1396 // because the server will renegotiate anyway.
1397 LeaveFunction("");
1398 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
1399 }
[email protected]e17b4c12008-11-05 22:04:081400 if (rv >= 0) {
[email protected]a3ff5e92009-10-13 04:48:061401 LogData(user_read_buf_->data(), rv);
[email protected]e17b4c12008-11-05 22:04:081402 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581403 return rv;
[email protected]e17b4c12008-11-05 22:04:081404 }
[email protected]b43c97c2008-10-22 19:50:581405 PRErrorCode prerr = PR_GetError();
1406 if (prerr == PR_WOULD_BLOCK_ERROR) {
[email protected]e17b4c12008-11-05 22:04:081407 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581408 return ERR_IO_PENDING;
1409 }
[email protected]e17b4c12008-11-05 22:04:081410 LeaveFunction("");
[email protected]2e9a5b6982010-01-15 22:29:031411 return MapNSPRError(prerr);
[email protected]b43c97c2008-10-22 19:50:581412}
1413
1414int SSLClientSocketNSS::DoPayloadWrite() {
[email protected]a3ff5e92009-10-13 04:48:061415 EnterFunction(user_write_buf_len_);
1416 DCHECK(user_write_buf_);
1417 int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
[email protected]e17b4c12008-11-05 22:04:081418 if (rv >= 0) {
[email protected]a3ff5e92009-10-13 04:48:061419 LogData(user_write_buf_->data(), rv);
[email protected]e17b4c12008-11-05 22:04:081420 LeaveFunction("");
[email protected]b43c97c2008-10-22 19:50:581421 return rv;
[email protected]e17b4c12008-11-05 22:04:081422 }
[email protected]b43c97c2008-10-22 19:50:581423 PRErrorCode prerr = PR_GetError();
1424 if (prerr == PR_WOULD_BLOCK_ERROR) {
[email protected]b43c97c2008-10-22 19:50:581425 return ERR_IO_PENDING;
1426 }
[email protected]e17b4c12008-11-05 22:04:081427 LeaveFunction("");
[email protected]2e9a5b6982010-01-15 22:29:031428 return MapNSPRError(prerr);
[email protected]b43c97c2008-10-22 19:50:581429}
1430
1431} // namespace net