172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// from AuthCertificateCallback() in 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp. 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* ***** BEGIN LICENSE BLOCK ***** 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Version: MPL 1.1/GPL 2.0/LGPL 2.1 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The contents of this file are subject to the Mozilla Public License Version 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 1.1 (the "License"); you may not use this file except in compliance with 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the License. You may obtain a copy of the License at 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * http://www.mozilla.org/MPL/ 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Software distributed under the License is distributed on an "AS IS" basis, 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * for the specific language governing rights and limitations under the 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * License. 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The Original Code is the Netscape security libraries. 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The Initial Developer of the Original Code is 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Netscape Communications Corporation. 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Portions created by the Initial Developer are Copyright (C) 2000 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the Initial Developer. All Rights Reserved. 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Contributor(s): 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Ian McGreer <mcgreer@netscape.com> 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Javier Delgadillo <javi@netscape.com> 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Kai Engert <kengert@redhat.com> 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Alternatively, the contents of this file may be used under the terms of 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * either the GNU General Public License Version 2 or later (the "GPL"), or 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * in which case the provisions of the GPL or the LGPL are applicable instead 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * of those above. If you wish to allow use of your version of this file only 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * under the terms of either the GPL or the LGPL, and not to allow others to 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * use your version of this file under the terms of the MPL, indicate your 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * decision by deleting the provisions above and replace them with the notice 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * and other provisions required by the GPL or the LGPL. If you do not delete 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the provisions above, a recipient may use your version of this file under 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the terms of any one of the MPL, the GPL or the LGPL. 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * ***** END LICENSE BLOCK ***** */ 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/ssl_client_socket_nss.h" 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <certdb.h> 513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <hasht.h> 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <keyhi.h> 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <nspr.h> 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <nss.h> 553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include <ocsp.h> 563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <pk11pub.h> 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <secerr.h> 583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <sechash.h> 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <ssl.h> 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sslerr.h> 61513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <sslproto.h> 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 6372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <algorithm> 64731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include <limits> 6572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <map> 66731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/compiler_specific.h" 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/singleton.h" 7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/metrics/histogram.h" 713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h" 733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/stringprintf.h" 743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread_restrictions.h" 75731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/values.h" 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/address_list.h" 773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/cert_status_flags.h" 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/cert_verifier.h" 79513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "net/base/connection_type_histograms.h" 803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/dns_util.h" 813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/dnsrr_resolver.h" 823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/dnssec_chain_verifier.h" 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/io_buffer.h" 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h" 853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/net_log.h" 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/ssl_cert_request_info.h" 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/ssl_connection_status_flags.h" 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/ssl_info.h" 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/sys_addrinfo.h" 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/ocsp/nss_ocsp.h" 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/socket/client_socket_handle.h" 92201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "net/socket/dns_cert_provenance_checker.h" 9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/socket/nss_ssl_util.h" 944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "net/socket/ssl_error_params.h" 95731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/socket/ssl_host_info.h" 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 97201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#if defined(OS_WIN) 98201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include <windows.h> 99201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include <wincrypt.h> 100201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#elif defined(OS_MACOSX) 101201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include <Security/SecBase.h> 102201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include <Security/SecCertificate.h> 103201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include <Security/SecIdentity.h> 10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#elif defined(USE_NSS) 10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <dlfcn.h> 106201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#endif 107201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int kRecvBufferSize = 4096; 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 110731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// kCorkTimeoutMs is the number of milliseconds for which we'll wait for a 111731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Write to an SSL socket which we're False Starting. Since corking stops the 112731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Finished message from being sent, the server sees an incomplete handshake 113731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// and some will time out such sockets quite aggressively. 114731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstatic const int kCorkTimeoutMs = 200; 115731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_WIN) 11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// CERT_OCSP_RESPONSE_PROP_ID is only implemented on Vista+, but it can be 11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// set on Windows XP without error. There is some overhead from the server 11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// sending the OCSP response if it supports the extension, for the subset of 12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// XP clients who will request it but be unable to use it, but this is an 12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// acceptable trade-off for simplicity of implementation. 12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic bool IsOCSPStaplingSupported() { 12372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return true; 12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 12572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#elif defined(USE_NSS) 12672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsentypedef SECStatus 12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen(*CacheOCSPResponseFromSideChannelFunction)( 12872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERTCertDBHandle *handle, CERTCertificate *cert, PRTime time, 12972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SECItem *encodedResponse, void *pwArg); 13072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 1313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// On Linux, we dynamically link against the system version of libnss3.so. In 1323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// order to continue working on systems without up-to-date versions of NSS we 13372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// lookup CERT_CacheOCSPResponseFromSideChannel with dlsym. 13472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// RuntimeLibNSSFunctionPointers is a singleton which caches the results of any 13672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// runtime symbol resolution that we need. 13772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenclass RuntimeLibNSSFunctionPointers { 13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen public: 13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CacheOCSPResponseFromSideChannelFunction 14072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GetCacheOCSPResponseFromSideChannelFunction() { 14172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return cache_ocsp_response_from_side_channel_; 14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 14472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen static RuntimeLibNSSFunctionPointers* GetInstance() { 14572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return Singleton<RuntimeLibNSSFunctionPointers>::get(); 14672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 1473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen private: 14972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen friend struct DefaultSingletonTraits<RuntimeLibNSSFunctionPointers>; 15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 15172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen RuntimeLibNSSFunctionPointers() { 15272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen cache_ocsp_response_from_side_channel_ = 15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen (CacheOCSPResponseFromSideChannelFunction) 15472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel"); 15572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 15672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 15772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CacheOCSPResponseFromSideChannelFunction 15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen cache_ocsp_response_from_side_channel_; 15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}; 16072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 16172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic CacheOCSPResponseFromSideChannelFunction 16272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenGetCacheOCSPResponseFromSideChannelFunction() { 16372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return RuntimeLibNSSFunctionPointers::GetInstance() 16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ->GetCacheOCSPResponseFromSideChannelFunction(); 16572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 16672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 16772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic bool IsOCSPStaplingSupported() { 16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return GetCacheOCSPResponseFromSideChannelFunction() != NULL; 1693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 1703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#else 17172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// TODO(agl): Figure out if we can plumb the OCSP response into Mac's system 17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// certificate validation functions. 17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic bool IsOCSPStaplingSupported() { 1743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return false; 1753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 1763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#endif 1773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net { 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// State machines are easier to debug if you log state transitions. 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Enable these if you want to see what's going on. 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if 1 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define EnterFunction(x) 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define LeaveFunction(x) 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define GotoState(s) next_handshake_state_ = s 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define LogData(s, len) 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else 188731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#define EnterFunction(x)\ 189731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << (void *)this << " " << __FUNCTION__ << " enter " << x\ 190731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << "; next_handshake_state " << next_handshake_state_ 191731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#define LeaveFunction(x)\ 192731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << (void *)this << " " << __FUNCTION__ << " leave " << x\ 193731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << "; next_handshake_state " << next_handshake_state_ 194731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#define GotoState(s)\ 195731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick do {\ 196731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << (void *)this << " " << __FUNCTION__ << " jump to state " << s;\ 197731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_handshake_state_ = s;\ 198731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } while (0) 199731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#define LogData(s, len)\ 200731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << (void *)this << " " << __FUNCTION__\ 201731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << " data [" << std::string(s, len) << "]" 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// This callback is intended to be used with CertFindChainInStore. In addition 2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// to filtering by extended/enhanced key usage, we do not show expired 2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// certificates and require digital signature usage in the key usage 2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// extension. 2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// 2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// This matches our behavior on Mac OS X and that of NSS. It also matches the 2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// default behavior of IE8. See http://support.microsoft.com/kb/890326 and 2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// 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 2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickBOOL WINAPI ClientCertFindCallback(PCCERT_CONTEXT cert_context, 2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void* find_arg) { 218731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Calling ClientCertFindCallback from _nss"; 2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Verify the certificate's KU is good. 2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick BYTE key_usage; 2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (CertGetIntendedKeyUsage(X509_ASN_ENCODING, cert_context->pCertInfo, 2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick &key_usage, 1)) { 2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!(key_usage & CERT_DIGITAL_SIGNATURE_KEY_USAGE)) 2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return FALSE; 2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DWORD err = GetLastError(); 2273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If |err| is non-zero, it's an actual error. Otherwise the extension 2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // just isn't present, and we treat it as if everything was allowed. 2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (err) { 2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DLOG(ERROR) << "CertGetIntendedKeyUsage failed: " << err; 2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return FALSE; 2323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Verify the current time is within the certificate's validity period. 2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (CertVerifyTimeValidity(NULL, cert_context->pCertInfo) != 0) 2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return FALSE; 2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 239dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Verify private key metadata is associated with this certificate. 240dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DWORD size = 0; 241dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!CertGetCertificateContextProperty( 242dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen cert_context, CERT_KEY_PROV_INFO_PROP_ID, NULL, &size)) { 243dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return FALSE; 244dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 245dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return TRUE; 2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 251513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// PeerCertificateChain is a helper object which extracts the certificate 252513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// chain, as given by the server, from an NSS socket and performs the needed 253513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// resource management. The first element of the chain is the leaf certificate 254513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// and the other elements are in the order given by the server. 255513209b27ff55e2841eac0e4120199c23acce758Ben Murdochclass PeerCertificateChain { 256513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch public: 257513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch explicit PeerCertificateChain(PRFileDesc* nss_fd) 258513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : num_certs_(0), 259513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch certs_(NULL) { 260513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SECStatus rv = SSL_PeerCertificateChain(nss_fd, NULL, &num_certs_); 261513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK_EQ(rv, SECSuccess); 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 263513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch certs_ = new CERTCertificate*[num_certs_]; 264513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const unsigned expected_num_certs = num_certs_; 265513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch rv = SSL_PeerCertificateChain(nss_fd, certs_, &num_certs_); 266513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK_EQ(rv, SECSuccess); 267513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK_EQ(num_certs_, expected_num_certs); 268513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 269513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 270513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ~PeerCertificateChain() { 271513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (unsigned i = 0; i < num_certs_; i++) 272513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch CERT_DestroyCertificate(certs_[i]); 273513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch delete[] certs_; 274513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 275513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 276513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch unsigned size() const { return num_certs_; } 277513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 278513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch CERTCertificate* operator[](unsigned i) { 279513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK_LT(i, num_certs_); 280513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return certs_[i]; 281513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 282513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 283513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::vector<base::StringPiece> AsStringPieceVector() const { 284513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::vector<base::StringPiece> v(size()); 285513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (unsigned i = 0; i < size(); i++) { 286513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch v[i] = base::StringPiece( 287513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch reinterpret_cast<const char*>(certs_[i]->derCert.data), 288513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch certs_[i]->derCert.len); 289513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 290513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 291513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return v; 292513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 293513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 294513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch private: 295513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch unsigned num_certs_; 296513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch CERTCertificate** certs_; 297513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}; 298513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 29972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid DestroyCertificates(CERTCertificate** certs, unsigned len) { 30072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (unsigned i = 0; i < len; i++) 30172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_DestroyCertificate(certs[i]); 30272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 30372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 30472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// DNSValidationResult enumerates the possible outcomes from processing a 30572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// set of DNS records. 30672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenenum DNSValidationResult { 30772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DNSVR_SUCCESS, // the cert is immediately acceptable. 30872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DNSVR_FAILURE, // the cert is unconditionally rejected. 30972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DNSVR_CONTINUE, // perform CA validation as usual. 31072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}; 31172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 31272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// VerifyTXTRecords processes the RRDATA for a number of DNS TXT records and 31372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// checks them against the given certificate. 31472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// dnssec: if true then the TXT records are DNSSEC validated. In this case, 31572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// DNSVR_SUCCESS may be returned. 31672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// server_cert_nss: the certificate to validate 31772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// rrdatas: the TXT records for the current domain. 31872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenDNSValidationResult VerifyTXTRecords( 31972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool dnssec, 32072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERTCertificate* server_cert_nss, 32172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::vector<base::StringPiece>& rrdatas) { 32272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool found_well_formed_record = false; 32372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool matched_record = false; 32472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 32572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (std::vector<base::StringPiece>::const_iterator 32672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen i = rrdatas.begin(); i != rrdatas.end(); ++i) { 32772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::map<std::string, std::string> m( 32872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DNSSECChainVerifier::ParseTLSTXTRecord(*i)); 32972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (m.empty()) 33072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen continue; 33172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 33272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::map<std::string, std::string>::const_iterator j; 33372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen j = m.find("v"); 33472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (j == m.end() || j->second != "tls1") 33572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen continue; 33672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 33772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen j = m.find("ha"); 33872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 33972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen HASH_HashType hash_algorithm; 34072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen unsigned hash_length; 34172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (j == m.end() || j->second == "sha1") { 34272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen hash_algorithm = HASH_AlgSHA1; 34372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen hash_length = SHA1_LENGTH; 34472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else if (j->second == "sha256") { 34572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen hash_algorithm = HASH_AlgSHA256; 34672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen hash_length = SHA256_LENGTH; 34772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 34872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen continue; 34972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 35072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 35172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen j = m.find("h"); 35272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (j == m.end()) 35372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen continue; 35472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 35572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::vector<uint8> given_hash; 35672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!base::HexStringToBytes(j->second, &given_hash)) 35772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen continue; 35872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 35972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (given_hash.size() != hash_length) 36072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen continue; 36172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 36272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen uint8 calculated_hash[SHA256_LENGTH]; // SHA256 is the largest. 36372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SECStatus rv; 36472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 36572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen j = m.find("hr"); 36672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (j == m.end() || j->second == "pubkey") { 36772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = HASH_HashBuf(hash_algorithm, calculated_hash, 36872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_cert_nss->derPublicKey.data, 36972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_cert_nss->derPublicKey.len); 37072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else if (j->second == "cert") { 37172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = HASH_HashBuf(hash_algorithm, calculated_hash, 37272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_cert_nss->derCert.data, 37372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_cert_nss->derCert.len); 37472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 37572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen continue; 37672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 37772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 37872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv != SECSuccess) 37972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NOTREACHED(); 38072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 38172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen found_well_formed_record = true; 38272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 38372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (memcmp(calculated_hash, &given_hash[0], hash_length) == 0) { 38472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen matched_record = true; 38572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (dnssec) 38672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return DNSVR_SUCCESS; 38772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 38872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 38972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 39072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (found_well_formed_record && !matched_record) 39172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return DNSVR_FAILURE; 39272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 39372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return DNSVR_CONTINUE; 39472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 39572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 39672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// CheckDNSSECChain tries to validate a DNSSEC chain embedded in 39772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// |server_cert_nss_|. It returns true iff a chain is found that proves the 39872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// value of a TXT record that contains a valid public key fingerprint. 39972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenDNSValidationResult CheckDNSSECChain( 40072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& hostname, 40172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERTCertificate* server_cert_nss) { 40272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!server_cert_nss) 40372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return DNSVR_CONTINUE; 40472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 40572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // CERT_FindCertExtensionByOID isn't exported so we have to install an OID, 40672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // get a tag for it and find the extension by using that tag. 40772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen static SECOidTag dnssec_chain_tag; 40872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen static bool dnssec_chain_tag_valid; 40972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!dnssec_chain_tag_valid) { 41072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // It's harmless if multiple threads enter this block concurrently. 41172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen static const uint8 kDNSSECChainOID[] = 41272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // 1.3.6.1.4.1.11129.2.1.4 41372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // (iso.org.dod.internet.private.enterprises.google.googleSecurity. 41472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // certificateExtensions.dnssecEmbeddedChain) 41572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen {0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x04}; 41672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SECOidData oid_data; 41772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memset(&oid_data, 0, sizeof(oid_data)); 41872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen oid_data.oid.data = const_cast<uint8*>(kDNSSECChainOID); 41972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen oid_data.oid.len = sizeof(kDNSSECChainOID); 42072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen oid_data.desc = "DNSSEC chain"; 42172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen oid_data.supportedExtension = SUPPORTED_CERT_EXTENSION; 42272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen dnssec_chain_tag = SECOID_AddEntry(&oid_data); 42372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_NE(SEC_OID_UNKNOWN, dnssec_chain_tag); 42472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen dnssec_chain_tag_valid = true; 42572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 42672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 42772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SECItem dnssec_embedded_chain; 42872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SECStatus rv = CERT_FindCertExtension(server_cert_nss, 42972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen dnssec_chain_tag, &dnssec_embedded_chain); 43072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv != SECSuccess) 43172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return DNSVR_CONTINUE; 43272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 43372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::StringPiece chain( 43472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen reinterpret_cast<char*>(dnssec_embedded_chain.data), 43572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen dnssec_embedded_chain.len); 43672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string dns_hostname; 43772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!DNSDomainFromDot(hostname, &dns_hostname)) 43872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return DNSVR_CONTINUE; 43972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DNSSECChainVerifier verifier(dns_hostname, chain); 44072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DNSSECChainVerifier::Error err = verifier.Verify(); 44172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (err != DNSSECChainVerifier::OK) { 44272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LOG(ERROR) << "DNSSEC chain verification failed: " << err; 44372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return DNSVR_CONTINUE; 44472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 44572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 44672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (verifier.rrtype() != kDNS_TXT) 44772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return DNSVR_CONTINUE; 44872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 44972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DNSValidationResult r = VerifyTXTRecords( 45072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen true /* DNSSEC verified */, server_cert_nss, verifier.rrdatas()); 45172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SECITEM_FreeItem(&dnssec_embedded_chain, PR_FALSE); 45272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return r; 45372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 45472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 455513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} // namespace 456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket, 4584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const HostPortPair& host_and_port, 459731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const SSLConfig& ssl_config, 460513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SSLHostInfo* ssl_host_info, 46121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifier* cert_verifier, 462201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DnsCertProvenanceChecker* dns_ctx) 463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_( 464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott this, &SSLClientSocketNSS::BufferSendComplete)), 465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_( 466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott this, &SSLClientSocketNSS::BufferRecvComplete)), 467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transport_send_busy_(false), 468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transport_recv_busy_(false), 4693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick corked_(false), 470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_( 471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott this, &SSLClientSocketNSS::OnHandshakeIOComplete)), 472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transport_(transport_socket), 4734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch host_and_port_(host_and_port), 474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssl_config_(ssl_config), 475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_connect_callback_(NULL), 476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_callback_(NULL), 477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_write_callback_(NULL), 478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_len_(0), 479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_write_buf_len_(0), 480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott server_cert_nss_(NULL), 481513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch server_cert_verify_result_(NULL), 482513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ssl_connection_status_(0), 483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott client_auth_cert_needed_(false), 48421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cert_verifier_(cert_verifier), 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch handshake_callback_called_(false), 486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott completed_handshake_(false), 487731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick eset_mitm_detected_(false), 488513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch predicted_cert_chain_correct_(false), 489513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch peername_initialized_(false), 4903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick dnssec_provider_(NULL), 491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_handshake_state_(STATE_NONE), 492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott nss_fd_(NULL), 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nss_bufs_(NULL), 494731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick net_log_(transport_socket->socket()->NetLog()), 495513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ssl_host_info_(ssl_host_info), 49672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen dns_cert_checker_(dns_ctx), 49772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen valid_thread_id_(base::kInvalidThreadId) { 498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnterFunction(""); 499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSSLClientSocketNSS::~SSLClientSocketNSS() { 502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnterFunction(""); 503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Disconnect(); 504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LeaveFunction(""); 505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 50772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static 50872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLClientSocketNSS::ClearSessionCache() { 50972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSL_ClearSessionCache(); 510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 51272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) { 51372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(""); 51472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ssl_info->Reset(); 51521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 516ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!server_cert_) 517731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 518731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 51972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ssl_info->cert_status = server_cert_verify_result_->cert_status; 52072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(server_cert_ != NULL); 52172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ssl_info->cert = server_cert_; 52272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ssl_info->connection_status = ssl_connection_status_; 523ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ssl_info->public_key_hashes = server_cert_verify_result_->public_key_hashes; 524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ssl_info->is_issued_by_known_root = 525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen server_cert_verify_result_->is_issued_by_known_root; 526731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 52772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PRUint16 cipher_suite = 52872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSLConnectionStatusToCipherSuite(ssl_connection_status_); 52972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSLCipherSuiteInfo cipher_info; 53072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SECStatus ok = SSL_GetCipherSuiteInfo(cipher_suite, 53172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &cipher_info, sizeof(cipher_info)); 53272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (ok == SECSuccess) { 53372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ssl_info->security_bits = cipher_info.effectiveKeyBits; 534513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else { 53572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ssl_info->security_bits = -1; 53672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LOG(DFATAL) << "SSL_GetCipherSuiteInfo returned " << PR_GetError() 53772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen << " for cipherSuite " << cipher_suite; 538513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 53972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(""); 54072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 541731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 54272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLClientSocketNSS::GetSSLCertRequestInfo( 54372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSLCertRequestInfo* cert_request_info) { 54472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(""); 54572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TODO(rch): switch SSLCertRequestInfo.host_and_port to a HostPortPair 54672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen cert_request_info->host_and_port = host_and_port_.ToString(); 54772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen cert_request_info->client_certs = client_certs_; 54872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(cert_request_info->client_certs.size()); 549731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 550731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 55172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSSLClientSocket::NextProtoStatus 55272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSSLClientSocketNSS::GetNextProto(std::string* proto) { 55372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(SSL_NEXT_PROTO_NEGOTIATED) 55472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen unsigned char buf[255]; 55572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int state; 55672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen unsigned len; 55772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SECStatus rv = SSL_GetNextProto(nss_fd_, &state, buf, &len, sizeof(buf)); 55872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv != SECSuccess) { 55972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NOTREACHED() << "Error return from SSL_GetNextProto: " << rv; 56072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen proto->clear(); 56172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return kNextProtoUnsupported; 562731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 56372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // We don't check for truncation because sizeof(buf) is large enough to hold 56472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // the maximum protocol size. 56572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen switch (state) { 56672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SSL_NEXT_PROTO_NO_SUPPORT: 56772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen proto->clear(); 56872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return kNextProtoUnsupported; 56972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SSL_NEXT_PROTO_NEGOTIATED: 57072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *proto = std::string(reinterpret_cast<char*>(buf), len); 57172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return kNextProtoNegotiated; 57272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SSL_NEXT_PROTO_NO_OVERLAP: 57372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *proto = std::string(reinterpret_cast<char*>(buf), len); 57472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return kNextProtoNoOverlap; 57572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen default: 57672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NOTREACHED() << "Unknown status from SSL_GetNextProto: " << state; 57772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen proto->clear(); 57872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return kNextProtoUnsupported; 579731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 58072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#else 58172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // No NPN support in the libssl that we are building with. 58272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen proto->clear(); 58372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return kNextProtoUnsupported; 58472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif 585731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 586731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 58772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLClientSocketNSS::UseDNSSEC(DNSSECProvider* provider) { 58872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen dnssec_provider_ = provider; 589731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 590731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 5917b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID 5927b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen// TODO(kristianm): handle the case when wait_for_connect is true 5937b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen// (sync requests) 5947b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif 5957b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsenint SSLClientSocketNSS::Connect(CompletionCallback* callback 5967b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID 5977b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen , bool wait_for_connect 5987b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif 5997b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen ) { 600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnterFunction(""); 601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(transport_.get()); 602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(next_handshake_state_ == STATE_NONE); 603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_read_callback_); 604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_write_callback_); 605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_connect_callback_); 606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_read_buf_); 607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_write_buf_); 608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 60972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnsureThreadIdAssigned(); 61072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT, NULL); 612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv = Init(); 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv != OK) { 61572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); 616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rv; 617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = InitializeSSLOptions(); 620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != OK) { 62172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); 622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 625513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Attempt to initialize the peer name. In the case of TCP FastOpen, 626513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // we don't have the peer yet. 627513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!UsingTCPFastOpen()) { 628513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch rv = InitializeSSLPeerName(); 629513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (rv != OK) { 63072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); 631513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return rv; 632513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 633513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 634513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 635ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GotoState(STATE_HANDSHAKE); 636731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoHandshakeLoop(OK); 638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv == ERR_IO_PENDING) { 639ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen user_connect_callback_ = callback; 640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 64172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); 642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LeaveFunction(""); 645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv > OK ? OK : rv; 646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 64872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLClientSocketNSS::Disconnect() { 64972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(""); 650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 651ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CHECK(CalledOnValidThread()); 652ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 65372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Shut down anything that may call us back (through buffer_send_callback_, 65472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // buffer_recv_callback, or handshake_io_callback_). 65572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen verifier_.reset(); 65672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen transport_->socket()->Disconnect(); 657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 65872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TODO(wtc): Send SSL close_notify alert. 65972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (nss_fd_ != NULL) { 66072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PR_Close(nss_fd_); 66172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen nss_fd_ = NULL; 662731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 66472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Reset object state 66572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen transport_send_busy_ = false; 66672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen transport_recv_busy_ = false; 66772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_connect_callback_ = NULL; 66872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_read_callback_ = NULL; 66972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_write_callback_ = NULL; 67072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_read_buf_ = NULL; 67172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_read_buf_len_ = 0; 67272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_write_buf_ = NULL; 67372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_write_buf_len_ = 0; 67472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_cert_ = NULL; 67572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (server_cert_nss_) { 67672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_DestroyCertificate(server_cert_nss_); 67772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_cert_nss_ = NULL; 678731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 67972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen local_server_cert_verify_result_.Reset(); 68072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_cert_verify_result_ = NULL; 68172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ssl_connection_status_ = 0; 68272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen completed_handshake_ = false; 68372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen eset_mitm_detected_ = false; 68472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen start_cert_verification_time_ = base::TimeTicks(); 68572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen predicted_cert_chain_correct_ = false; 68672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen peername_initialized_ = false; 68772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen nss_bufs_ = NULL; 68872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen client_certs_.clear(); 68972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen client_auth_cert_needed_ = false; 690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 69172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(""); 69272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 69472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SSLClientSocketNSS::IsConnected() const { 69572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Ideally, we should also check if we have received the close_notify alert 69672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // message from the server, and return false in that case. We're not doing 69772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // that, so this function may return a false positive. Since the upper 69872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // layer (HttpNetworkTransaction) needs to handle a persistent connection 69972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // closed by the server when we send a request anyway, a false positive in 70072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // exchange for simpler code is a good trade-off. 70172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(""); 702ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool ret = completed_handshake_ && transport_->socket()->IsConnected(); 70372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(""); 70472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ret; 70572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 70772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SSLClientSocketNSS::IsConnectedAndIdle() const { 70872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Unlike IsConnected, this method doesn't return a false positive. 70972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // 71072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Strictly speaking, we should check if we have received the close_notify 71172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // alert message from the server, and return false in that case. Although 71272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // the close_notify alert message means EOF in the SSL layer, it is just 71372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // bytes to the transport layer below, so 71472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // transport_->socket()->IsConnectedAndIdle() returns the desired false 71572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // when we receive close_notify. 71672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(""); 717ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool ret = completed_handshake_ && transport_->socket()->IsConnectedAndIdle(); 71872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(""); 71972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ret; 72072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 72172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 72272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint SSLClientSocketNSS::GetPeerAddress(AddressList* address) const { 72372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return transport_->socket()->GetPeerAddress(address); 72472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 72572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 726ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint SSLClientSocketNSS::GetLocalAddress(IPEndPoint* address) const { 727ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return transport_->socket()->GetLocalAddress(address); 728ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 729ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 73072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst BoundNetLog& SSLClientSocketNSS::NetLog() const { 73172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return net_log_; 73272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 73372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 73472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLClientSocketNSS::SetSubresourceSpeculation() { 73572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (transport_.get() && transport_->socket()) { 73672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen transport_->socket()->SetSubresourceSpeculation(); 73772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 73872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NOTREACHED(); 739731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 74072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 74272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLClientSocketNSS::SetOmniboxSpeculation() { 74372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (transport_.get() && transport_->socket()) { 74472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen transport_->socket()->SetOmniboxSpeculation(); 74572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 74672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NOTREACHED(); 74772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 74872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 74972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 75072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SSLClientSocketNSS::WasEverUsed() const { 75172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (transport_.get() && transport_->socket()) { 75272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return transport_->socket()->WasEverUsed(); 75372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 75472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NOTREACHED(); 75572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 75672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 75772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 75872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SSLClientSocketNSS::UsingTCPFastOpen() const { 75972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (transport_.get() && transport_->socket()) { 76072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return transport_->socket()->UsingTCPFastOpen(); 76172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 76272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NOTREACHED(); 76372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 76472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 76572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 76672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len, 76772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CompletionCallback* callback) { 76872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(buf_len); 769ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(completed_handshake_); 770ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(next_handshake_state_ == STATE_NONE); 77172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(!user_read_callback_); 77272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(!user_connect_callback_); 77372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(!user_read_buf_); 77472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(nss_bufs_); 77572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 77672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_read_buf_ = buf; 77772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_read_buf_len_ = buf_len; 77872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 77972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int rv = DoReadLoop(OK); 78072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 78172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv == ERR_IO_PENDING) { 78272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_read_callback_ = callback; 78372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 78472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_read_buf_ = NULL; 78572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_read_buf_len_ = 0; 78672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 78772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(rv); 78872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return rv; 78972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 79072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 79172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len, 79272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CompletionCallback* callback) { 79372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(buf_len); 794ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(completed_handshake_); 795ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(next_handshake_state_ == STATE_NONE); 79672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(!user_write_callback_); 797ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!user_connect_callback_); 79872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(!user_write_buf_); 79972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(nss_bufs_); 80072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 80172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_write_buf_ = buf; 80272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_write_buf_len_ = buf_len; 80372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 80472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (corked_) { 80572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen corked_ = false; 80672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen uncork_timer_.Reset(); 80772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 80872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int rv = DoWriteLoop(OK); 80972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 81072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv == ERR_IO_PENDING) { 81172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_write_callback_ = callback; 81272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 81372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_write_buf_ = NULL; 81472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_write_buf_len_ = 0; 81572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 81672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(rv); 81772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return rv; 81872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 81972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 82072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) { 82172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return transport_->socket()->SetReceiveBufferSize(size); 82272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 82372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 82472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SSLClientSocketNSS::SetSendBufferSize(int32 size) { 82572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return transport_->socket()->SetSendBufferSize(size); 82672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 82772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 82872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint SSLClientSocketNSS::Init() { 82972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(""); 83072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Initialize the NSS SSL library in a threadsafe way. This also 83172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // initializes the NSS base library. 83272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnsureNSSSSLInit(); 83372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!NSS_IsInitialized()) 83472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ERR_UNEXPECTED; 83572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if !defined(OS_MACOSX) && !defined(OS_WIN) 83672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop 83772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // by MessageLoopForIO::current(). 83872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // X509Certificate::Verify() runs on a worker thread of CertVerifier. 83972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnsureOCSPInit(); 84072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif 84172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 84272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(""); 84372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return OK; 84472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 84572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 84672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint SSLClientSocketNSS::InitializeSSLOptions() { 84772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Transport connected, now hook it up to nss 84872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TODO(port): specify rx and tx buffer sizes separately 84972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen nss_fd_ = memio_CreateIOLayer(kRecvBufferSize); 85072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (nss_fd_ == NULL) { 85172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code. 85272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 85372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 85472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Grab pointer to buffers 85572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen nss_bufs_ = memio_GetSecret(nss_fd_); 85672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 85772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen /* Create SSL state machine */ 85872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen /* Push SSL onto our fake I/O socket */ 85972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen nss_fd_ = SSL_ImportFD(NULL, nss_fd_); 86072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (nss_fd_ == NULL) { 86172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LogFailedNSSFunction(net_log_, "SSL_ImportFD", ""); 86272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR/NSS error code. 86372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 86472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TODO(port): set more ssl options! Check errors! 86572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 86672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int rv; 86772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 86872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE); 86972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv != SECSuccess) { 87072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY"); 87172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ERR_UNEXPECTED; 87272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 87372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 87472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE); 87572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv != SECSuccess) { 87672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2"); 87772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ERR_UNEXPECTED; 87872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 87972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 88072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Don't do V2 compatible hellos because they don't support TLS extensions. 88172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = SSL_OptionSet(nss_fd_, SSL_V2_COMPATIBLE_HELLO, PR_FALSE); 88272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv != SECSuccess) { 88372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_V2_COMPATIBLE_HELLO"); 88472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ERR_UNEXPECTED; 88572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 88672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 88772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL3, ssl_config_.ssl3_enabled); 88872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv != SECSuccess) { 88972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL3"); 89072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ERR_UNEXPECTED; 89172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 89272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 89372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_TLS, ssl_config_.tls1_enabled); 89472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv != SECSuccess) { 89572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_TLS"); 89672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ERR_UNEXPECTED; 89772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 89872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 89972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (std::vector<uint16>::const_iterator it = 90072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ssl_config_.disabled_cipher_suites.begin(); 90172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen it != ssl_config_.disabled_cipher_suites.end(); ++it) { 90272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // This will fail if the specified cipher is not implemented by NSS, but 90372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // the failure is harmless. 90472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE); 9054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 9064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef SSL_ENABLE_SESSION_TICKETS 908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Support RFC 5077 909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE); 910731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (rv != SECSuccess) { 911731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LogFailedNSSFunction( 912731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS"); 913731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else 915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott #error "You need to install NSS-3.12 or later to build chromium" 916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 917c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef SSL_ENABLE_DEFLATE 919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Some web servers have been found to break if TLS is used *or* if DEFLATE 920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // is advertised. Thus, if TLS is disabled (probably because we are doing 921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // SSLv3 fallback), we disable DEFLATE also. 922c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // See http://crbug.com/31628 923c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_DEFLATE, ssl_config_.tls1_enabled); 924c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != SECSuccess) 925731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_DEFLATE"); 926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifdef SSL_ENABLE_FALSE_START 9293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick rv = SSL_OptionSet( 9303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick nss_fd_, SSL_ENABLE_FALSE_START, 9313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ssl_config_.false_start_enabled && 9324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch !SSLConfigService::IsKnownFalseStartIncompatibleServer( 9334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch host_and_port_.host())); 934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv != SECSuccess) 935731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_FALSE_START"); 936731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#endif 937731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef SSL_ENABLE_RENEGOTIATION 939ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We allow servers to request renegotiation. Since we're a client, 940ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // prohibiting this is rather a waste of time. Only servers are in a 941ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // position to prevent renegotiation attacks. 942ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // http://extendedsubset.com/?p=8 943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 944ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_RENEGOTIATION, 945ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SSL_RENEGOTIATE_TRANSITIONAL); 946731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (rv != SECSuccess) { 947731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LogFailedNSSFunction( 948731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick net_log_, "SSL_OptionSet", "SSL_ENABLE_RENEGOTIATION"); 949731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // SSL_ENABLE_RENEGOTIATION 951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef SSL_NEXT_PROTO_NEGOTIATED 953c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!ssl_config_.next_protos.empty()) { 954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = SSL_SetNextProtoNego( 955c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott nss_fd_, 956c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott reinterpret_cast<const unsigned char *>(ssl_config_.next_protos.data()), 957c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssl_config_.next_protos.size()); 958c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != SECSuccess) 959731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LogFailedNSSFunction(net_log_, "SSL_SetNextProtoNego", ""); 960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 962c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#ifdef SSL_ENABLE_OCSP_STAPLING 964ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsOCSPStaplingSupported()) { 9653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, PR_TRUE); 9663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (rv != SECSuccess) 9673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen LogFailedNSSFunction(net_log_, "SSL_OptionSet (OCSP stapling)", ""); 9683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 9693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#endif 9703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); 972731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (rv != SECSuccess) { 973731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT"); 974731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_UNEXPECTED; 975731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this); 978731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (rv != SECSuccess) { 979731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", ""); 980731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_UNEXPECTED; 981731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 983513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#if defined(NSS_PLATFORM_CLIENT_AUTH) 984513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch rv = SSL_GetPlatformClientAuthDataHook(nss_fd_, PlatformClientAuthHandler, 985513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch this); 986513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#else 987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = SSL_GetClientAuthDataHook(nss_fd_, ClientAuthHandler, this); 988513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif 989731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (rv != SECSuccess) { 990731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LogFailedNSSFunction(net_log_, "SSL_GetClientAuthDataHook", ""); 991731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_UNEXPECTED; 992731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 994c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this); 995731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (rv != SECSuccess) { 996731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", ""); 997c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_UNEXPECTED; 998731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 999c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1000c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Tell SSL the hostname we're trying to connect to. 10014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch SSL_SetURL(nss_fd_, host_and_port_.host().c_str()); 1002c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1003513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Tell SSL we're a client; needed if not letting NSPR do socket I/O 1004513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SSL_ResetHandshake(nss_fd_, 0); 1005513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 1006513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return OK; 1007513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 1008513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 1009513209b27ff55e2841eac0e4120199c23acce758Ben Murdochint SSLClientSocketNSS::InitializeSSLPeerName() { 1010513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Tell NSS who we're connected to 1011513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch AddressList peer_address; 1012513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int err = transport_->socket()->GetPeerAddress(&peer_address); 1013513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (err != OK) 1014513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return err; 1015513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 1016513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const struct addrinfo* ai = peer_address.head(); 1017513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 1018513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch PRNetAddr peername; 1019513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch memset(&peername, 0, sizeof(peername)); 1020513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK_LE(ai->ai_addrlen, sizeof(peername)); 1021513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch size_t len = std::min(static_cast<size_t>(ai->ai_addrlen), 1022513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch sizeof(peername)); 1023513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch memcpy(&peername, ai->ai_addr, len); 1024513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 1025513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Adjust the address family field for BSD, whose sockaddr 1026513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // structure has a one-byte length and one-byte address family 1027513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // field at the beginning. PRNetAddr has a two-byte address 1028513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // family field at the beginning. 1029513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch peername.raw.family = ai->ai_addr->sa_family; 1030513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 1031513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch memio_SetPeerName(nss_fd_, &peername); 1032513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 1033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Set the peer ID for session reuse. This is necessary when we create an 1034c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // SSL tunnel through a proxy -- GetPeerName returns the proxy's address 1035c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // rather than the destination server's address in that case. 10364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string peer_id = host_and_port_.ToString(); 1037513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SECStatus rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str())); 1038c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != SECSuccess) 1039731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LogFailedNSSFunction(net_log_, "SSL_SetSockPeerID", peer_id.c_str()); 1040c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1041513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch peername_initialized_ = true; 1042c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 1043c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1044c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1045c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 104672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Sets server_cert_ and server_cert_nss_ if not yet set. 104772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Returns server_cert_. 104872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenX509Certificate *SSLClientSocketNSS::UpdateServerCert() { 104972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // We set the server_cert_ from HandshakeCallback(). 105072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (server_cert_ == NULL) { 105172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_cert_nss_ = SSL_PeerCertificate(nss_fd_); 105272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (server_cert_nss_) { 105372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PeerCertificateChain certs(nss_fd_); 105472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_cert_ = X509Certificate::CreateFromDERCertChain( 105572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen certs.AsStringPieceVector()); 105672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 1057c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 105872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return server_cert_; 105972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 1060c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 106172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Sets ssl_connection_status_. 106272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLClientSocketNSS::UpdateConnectionStatus() { 106372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSLChannelInfo channel_info; 106472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SECStatus ok = SSL_GetChannelInfo(nss_fd_, 106572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &channel_info, sizeof(channel_info)); 106672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (ok == SECSuccess && 106772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen channel_info.length == sizeof(channel_info) && 106872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen channel_info.cipherSuite) { 106972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ssl_connection_status_ |= 107072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen (static_cast<int>(channel_info.cipherSuite) & 107172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSL_CONNECTION_CIPHERSUITE_MASK) << 107272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSL_CONNECTION_CIPHERSUITE_SHIFT; 1073c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 107472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ssl_connection_status_ |= 107572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen (static_cast<int>(channel_info.compressionMethod) & 107672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSL_CONNECTION_COMPRESSION_MASK) << 107772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSL_CONNECTION_COMPRESSION_SHIFT; 1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1079513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // NSS 3.12.x doesn't have version macros for TLS 1.1 and 1.2 (because NSS 1080513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // doesn't support them yet), so we use 0x0302 and 0x0303 directly. 1081513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int version = SSL_CONNECTION_VERSION_UNKNOWN; 1082513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (channel_info.protocolVersion < SSL_LIBRARY_VERSION_3_0) { 1083513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // All versions less than SSL_LIBRARY_VERSION_3_0 are treated as SSL 1084513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // version 2. 1085513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch version = SSL_CONNECTION_VERSION_SSL2; 1086513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_0) { 1087513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch version = SSL_CONNECTION_VERSION_SSL3; 1088513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_1_TLS) { 1089513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch version = SSL_CONNECTION_VERSION_TLS1; 1090513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else if (channel_info.protocolVersion == 0x0302) { 1091513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch version = SSL_CONNECTION_VERSION_TLS1_1; 1092513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else if (channel_info.protocolVersion == 0x0303) { 1093513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch version = SSL_CONNECTION_VERSION_TLS1_2; 1094513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 1095513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ssl_connection_status_ |= 1096513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (version & SSL_CONNECTION_VERSION_MASK) << 1097513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SSL_CONNECTION_VERSION_SHIFT; 1098c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1099c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // SSL_HandshakeNegotiatedExtension was added in NSS 3.12.6. 1101513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Since SSL_MAX_EXTENSIONS was added at the same time, we can test 1102513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // SSL_MAX_EXTENSIONS for the presence of SSL_HandshakeNegotiatedExtension. 1103513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#if defined(SSL_MAX_EXTENSIONS) 1104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PRBool peer_supports_renego_ext; 1105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ok = SSL_HandshakeNegotiatedExtension(nss_fd_, ssl_renegotiation_info_xtn, 1106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &peer_supports_renego_ext); 1107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ok == SECSuccess) { 1108513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!peer_supports_renego_ext) { 1109513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ssl_connection_status_ |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION; 1110513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Log an informational message if the server does not support secure 1111513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // renegotiation (RFC 5746). 11124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch VLOG(1) << "The server " << host_and_port_.ToString() 1113513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << " does not support the TLS renegotiation_info extension."; 1114513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 1115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported", 1116513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch peer_supports_renego_ext, 2); 1117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1118513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif 1119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ssl_config_.ssl3_fallback) 1121513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ssl_connection_status_ |= SSL_CONNECTION_SSL3_FALLBACK; 1122513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 1123513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 112472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLClientSocketNSS::DoReadCallback(int rv) { 112572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(rv); 112672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(rv != ERR_IO_PENDING); 112772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(user_read_callback_); 1128513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 112972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Since Run may result in Read being called, clear |user_read_callback_| 113072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // up front. 113172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CompletionCallback* c = user_read_callback_; 113272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_read_callback_ = NULL; 113372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_read_buf_ = NULL; 113472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_read_buf_len_ = 0; 113572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen c->Run(rv); 1136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LeaveFunction(""); 1137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 113972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLClientSocketNSS::DoWriteCallback(int rv) { 114072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(rv); 114172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(rv != ERR_IO_PENDING); 114272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(user_write_callback_); 114372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 114472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Since Run may result in Write being called, clear |user_write_callback_| 114572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // up front. 114672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CompletionCallback* c = user_write_callback_; 114772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_write_callback_ = NULL; 114872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_write_buf_ = NULL; 114972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_write_buf_len_ = 0; 115072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen c->Run(rv); 115172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(""); 1152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// As part of Connect(), the SSLClientSocketNSS object performs an SSL 1155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// handshake. This requires network IO, which in turn calls 1156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// BufferRecvComplete() with a non-zero byte count. This byte count eventually 1157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// winds its way through the state machine and ends up being passed to the 1158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// callback. For Read() and Write(), that's what we want. But for Connect(), 1159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the caller expects OK (i.e. 0) for success. 1160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 1161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SSLClientSocketNSS::DoConnectCallback(int rv) { 1162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnterFunction(rv); 1163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(rv, ERR_IO_PENDING); 1164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(user_connect_callback_); 1165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* c = user_connect_callback_; 1167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_connect_callback_ = NULL; 1168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott c->Run(rv > OK ? OK : rv); 1169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LeaveFunction(""); 1170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SSLClientSocketNSS::OnHandshakeIOComplete(int result) { 1173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnterFunction(result); 1174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = DoHandshakeLoop(result); 1175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != ERR_IO_PENDING) { 117672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEventWithNetErrorCode(net::NetLog::TYPE_SSL_CONNECT, rv); 1177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DoConnectCallback(rv); 1178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LeaveFunction(""); 1180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SSLClientSocketNSS::OnSendComplete(int result) { 1183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnterFunction(result); 1184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (next_handshake_state_ == STATE_HANDSHAKE) { 1185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // In handshake phase. 1186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OnHandshakeIOComplete(result); 1187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LeaveFunction(""); 1188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 1189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // OnSendComplete may need to call DoPayloadRead while the renegotiation 1192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // handshake is in progress. 1193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv_read = ERR_IO_PENDING; 1194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv_write = ERR_IO_PENDING; 1195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool network_moved; 1196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 1197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (user_read_buf_) 1198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv_read = DoPayloadRead(); 1199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (user_write_buf_) 1200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv_write = DoPayloadWrite(); 1201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott network_moved = DoTransportIO(); 1202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while (rv_read == ERR_IO_PENDING && 1203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv_write == ERR_IO_PENDING && 1204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott network_moved); 1205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (user_read_buf_ && rv_read != ERR_IO_PENDING) 1207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoReadCallback(rv_read); 1208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (user_write_buf_ && rv_write != ERR_IO_PENDING) 1209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoWriteCallback(rv_write); 1210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LeaveFunction(""); 1212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SSLClientSocketNSS::OnRecvComplete(int result) { 1215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnterFunction(result); 1216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (next_handshake_state_ == STATE_HANDSHAKE) { 1217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // In handshake phase. 1218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OnHandshakeIOComplete(result); 1219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LeaveFunction(""); 1220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 1221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Network layer received some data, check if client requested to read 1224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // decrypted data. 1225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!user_read_buf_) { 1226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LeaveFunction(""); 1227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 1228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = DoReadLoop(result); 1231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != ERR_IO_PENDING) 1232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoReadCallback(rv); 1233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LeaveFunction(""); 1234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SSLClientSocketNSS::DoHandshakeLoop(int last_io_result) { 1237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnterFunction(last_io_result); 1238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool network_moved; 1239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = last_io_result; 1240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 1241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Default to STATE_NONE for next state. 1242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // (This is a quirk carried over from the windows 1243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // implementation. It makes reading the logs a bit harder.) 1244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // State handlers can and often do call GotoState just 1245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // to stay in the current state. 1246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott State state = next_handshake_state_; 1247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GotoState(STATE_NONE); 1248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (state) { 1249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_NONE: 1250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // we're just pumping data between the buffer and the network 1251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 1252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_HANDSHAKE: 1253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoHandshake(); 1254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 12553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case STATE_VERIFY_DNSSEC: 12563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick rv = DoVerifyDNSSEC(rv); 12573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 12583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case STATE_VERIFY_DNSSEC_COMPLETE: 12593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick rv = DoVerifyDNSSECComplete(rv); 12603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 1261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_VERIFY_CERT: 1262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(rv == OK); 1263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoVerifyCert(rv); 1264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 1265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_VERIFY_CERT_COMPLETE: 1266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoVerifyCertComplete(rv); 1267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 1268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 1269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = ERR_UNEXPECTED; 12703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG(DFATAL) << "unexpected state " << state; 1271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 1272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Do the actual network I/O 1275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott network_moved = DoTransportIO(); 1276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while ((rv != ERR_IO_PENDING || network_moved) && 1277731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_handshake_state_ != STATE_NONE); 1278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LeaveFunction(""); 1279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 1280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SSLClientSocketNSS::DoReadLoop(int result) { 1283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnterFunction(""); 1284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(completed_handshake_); 1285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(next_handshake_state_ == STATE_NONE); 1286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0) 1288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 1289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!nss_bufs_) { 12913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG(DFATAL) << "!nss_bufs_"; 1292731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int rv = ERR_UNEXPECTED; 1293513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR, 1294513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch make_scoped_refptr(new SSLErrorParams(rv, 0))); 1295731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return rv; 12963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool network_moved; 1299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv; 1300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 1301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoPayloadRead(); 1302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott network_moved = DoTransportIO(); 1303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while (rv == ERR_IO_PENDING && network_moved); 1304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LeaveFunction(""); 1306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 1307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SSLClientSocketNSS::DoWriteLoop(int result) { 1310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnterFunction(""); 1311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(completed_handshake_); 1312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(next_handshake_state_ == STATE_NONE); 1313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0) 1315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 1316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!nss_bufs_) { 13183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG(DFATAL) << "!nss_bufs_"; 1319731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int rv = ERR_UNEXPECTED; 1320513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR, 1321513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch make_scoped_refptr(new SSLErrorParams(rv, 0))); 1322731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return rv; 13233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool network_moved; 1326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv; 1327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 1328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoPayloadWrite(); 1329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott network_moved = DoTransportIO(); 1330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while (rv == ERR_IO_PENDING && network_moved); 1331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LeaveFunction(""); 1333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 1334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 133672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint SSLClientSocketNSS::DoHandshake() { 133772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(""); 133872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int net_error = net::OK; 133972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SECStatus rv = SSL_ForceHandshake(nss_fd_); 1340513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 134172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (client_auth_cert_needed_) { 134272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; 134372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR, 134472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen make_scoped_refptr(new SSLErrorParams(net_error, 0))); 134572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If the handshake already succeeded (because the server requests but 134672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // doesn't require a client cert), we need to invalidate the SSL session 134772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // so that we won't try to resume the non-client-authenticated session in 134872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // the next handshake. This will cause the server to ask for a client 134972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // cert again. 135072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv == SECSuccess && SSL_InvalidateSession(nss_fd_) != SECSuccess) { 135172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError(); 135272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 135372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else if (rv == SECSuccess) { 135472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (handshake_callback_called_) { 135572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (eset_mitm_detected_) { 135672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_error = ERR_ESET_ANTI_VIRUS_SSL_INTERCEPTION; 135772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 135872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // We need to see if the predicted certificate chain (in 135972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // |ssl_host_info_->state().certs) matches the actual certificate chain 1360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // before we try to save it before we update |ssl_host_info_|. 136172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty()) { 136272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PeerCertificateChain certs(nss_fd_); 136372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const SSLHostInfo::State& state = ssl_host_info_->state(); 136472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen predicted_cert_chain_correct_ = certs.size() == state.certs.size(); 136572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (predicted_cert_chain_correct_) { 136672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (unsigned i = 0; i < certs.size(); i++) { 136772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (certs[i]->derCert.len != state.certs[i].size() || 136872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memcmp(certs[i]->derCert.data, state.certs[i].data(), 136972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen certs[i]->derCert.len) != 0) { 137072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen predicted_cert_chain_correct_ = false; 137172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 137272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 137372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 137472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 137572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 137672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 137772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(SSL_ENABLE_OCSP_STAPLING) 137872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TODO(agl): figure out how to plumb an OCSP response into the Mac 137972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // system library and update IsOCSPStaplingSupported for Mac. 138072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!predicted_cert_chain_correct_ && IsOCSPStaplingSupported()) { 138172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen unsigned int len = 0; 138272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSL_GetStapledOCSPResponse(nss_fd_, NULL, &len); 138372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (len) { 138472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const unsigned int orig_len = len; 138572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_array<uint8> ocsp_response(new uint8[orig_len]); 138672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSL_GetStapledOCSPResponse(nss_fd_, ocsp_response.get(), &len); 138772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_EQ(orig_len, len); 138872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 138972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_WIN) 139072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CRYPT_DATA_BLOB ocsp_response_blob; 139172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ocsp_response_blob.cbData = len; 139272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ocsp_response_blob.pbData = ocsp_response.get(); 139372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BOOL ok = CertSetCertificateContextProperty( 139472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_cert_->os_cert_handle(), 139572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_OCSP_RESPONSE_PROP_ID, 139672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG, 139772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &ocsp_response_blob); 139872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!ok) { 139972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen VLOG(1) << "Failed to set OCSP response property: " 140072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen << GetLastError(); 140172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 140272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#elif defined(USE_NSS) 140372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CacheOCSPResponseFromSideChannelFunction cache_ocsp_response = 140472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GetCacheOCSPResponseFromSideChannelFunction(); 140572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SECItem ocsp_response_item; 140672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ocsp_response_item.type = siBuffer; 140772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ocsp_response_item.data = ocsp_response.get(); 140872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ocsp_response_item.len = len; 140972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 141072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen cache_ocsp_response( 141172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_GetDefaultCertDB(), server_cert_nss_, PR_Now(), 141272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &ocsp_response_item, NULL); 141372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif 141472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 141572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 141672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif 141772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 1418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SaveSSLHostInfo(); 1419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // SSL handshake is completed. Let's verify the certificate. 1420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GotoState(STATE_VERIFY_DNSSEC); 1421513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 142272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Done! 142372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 142472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=562434 - 142572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // SSL_ForceHandshake returned SECSuccess prematurely. 142672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = SECFailure; 142772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_error = ERR_SSL_PROTOCOL_ERROR; 142872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR, 142972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen make_scoped_refptr(new SSLErrorParams(net_error, 0))); 143072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 143172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 143272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PRErrorCode prerr = PR_GetError(); 143372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_error = HandleNSSError(prerr, true); 143472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 143572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If not done, stay in this state 143672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (net_error == ERR_IO_PENDING) { 143772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GotoState(STATE_HANDSHAKE); 143872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 143972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LOG(ERROR) << "handshake failed; NSS error code " << prerr 144072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen << ", net_error " << net_error; 144172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.AddEvent( 144272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NetLog::TYPE_SSL_HANDSHAKE_ERROR, 144372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen make_scoped_refptr(new SSLErrorParams(net_error, prerr))); 1444513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 1445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 144772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(""); 144872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return net_error; 144972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 1450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 145172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint SSLClientSocketNSS::DoVerifyDNSSEC(int result) { 145272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (ssl_config_.dns_cert_provenance_checking_enabled && 145372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen dns_cert_checker_) { 145472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PeerCertificateChain certs(nss_fd_); 145572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen dns_cert_checker_->DoAsyncVerification( 145672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen host_and_port_.host(), certs.AsStringPieceVector()); 1457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 145972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (ssl_config_.dnssec_enabled) { 146072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DNSValidationResult r = CheckDNSSECChain(host_and_port_.host(), 146172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_cert_nss_); 146272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (r == DNSVR_SUCCESS) { 146372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen local_server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC; 146472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_cert_verify_result_ = &local_server_cert_verify_result_; 146572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GotoState(STATE_VERIFY_CERT_COMPLETE); 146672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return OK; 146772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 1468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 147072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (dnssec_provider_ == NULL) { 147172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GotoState(STATE_VERIFY_CERT); 147272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return OK; 147372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 1474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 147572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GotoState(STATE_VERIFY_DNSSEC_COMPLETE); 147672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen RRResponse* response; 147772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen dnssec_wait_start_time_ = base::Time::Now(); 147872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return dnssec_provider_->GetDNSSECRecords(&response, &handshake_io_callback_); 147972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 1480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 148172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint SSLClientSocketNSS::DoVerifyDNSSECComplete(int result) { 148272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen RRResponse* response; 148372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int err = dnssec_provider_->GetDNSSECRecords(&response, NULL); 148472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_EQ(err, OK); 1485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 148672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const base::TimeDelta elapsed = base::Time::Now() - dnssec_wait_start_time_; 148772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen HISTOGRAM_TIMES("Net.DNSSECWaitTime", elapsed); 148872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 148972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GotoState(STATE_VERIFY_CERT); 149072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!response || response->rrdatas.empty()) 149172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return OK; 149272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 149372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::vector<base::StringPiece> records; 149472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen records.resize(response->rrdatas.size()); 149572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (unsigned i = 0; i < response->rrdatas.size(); i++) 149672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen records[i] = base::StringPiece(response->rrdatas[i]); 149772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DNSValidationResult r = 149872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen VerifyTXTRecords(response->dnssec, server_cert_nss_, records); 149972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 150072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!ssl_config_.dnssec_enabled) { 150172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If DNSSEC is not enabled we don't take any action based on the result, 150272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // except to record the latency, above. 150372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return OK; 150472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 150572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 150672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen switch (r) { 150772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case DNSVR_FAILURE: 150872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GotoState(STATE_VERIFY_CERT_COMPLETE); 150972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen local_server_cert_verify_result_.cert_status |= CERT_STATUS_NOT_IN_DNS; 151072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_cert_verify_result_ = &local_server_cert_verify_result_; 151172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ERR_CERT_NOT_IN_DNS; 151272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case DNSVR_CONTINUE: 151372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GotoState(STATE_VERIFY_CERT); 151472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 151572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case DNSVR_SUCCESS: 151672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen local_server_cert_verify_result_.cert_status |= CERT_STATUS_IS_DNSSEC; 151772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_cert_verify_result_ = &local_server_cert_verify_result_; 151872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GotoState(STATE_VERIFY_CERT_COMPLETE); 151972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 152072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen default: 1521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 152272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GotoState(STATE_VERIFY_CERT); 152372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 1524513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 152572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return OK; 152672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 1527513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 152872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint SSLClientSocketNSS::DoVerifyCert(int result) { 152972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(server_cert_); 1530513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 153172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GotoState(STATE_VERIFY_CERT_COMPLETE); 153272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen start_cert_verification_time_ = base::TimeTicks::Now(); 153372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 153472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (ssl_host_info_.get() && !ssl_host_info_->state().certs.empty() && 153572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen predicted_cert_chain_correct_) { 153672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If the SSLHostInfo had a prediction for the certificate chain of this 153772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // server then it will have optimistically started a verification of that 153872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // chain. So, if the prediction was correct, we should wait for that 153972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // verification to finish rather than start our own. 154072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.AddEvent(NetLog::TYPE_SSL_VERIFICATION_MERGED, NULL); 154172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UMA_HISTOGRAM_ENUMERATION("Net.SSLVerificationMerged", 1 /* true */, 2); 154272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::TimeTicks end_time = ssl_host_info_->verification_end_time(); 154372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (end_time.is_null()) 154472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen end_time = base::TimeTicks::Now(); 154572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UMA_HISTOGRAM_TIMES("Net.SSLVerificationMergedMsSaved", 154672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen end_time - ssl_host_info_->verification_start_time()); 154772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_cert_verify_result_ = &ssl_host_info_->cert_verify_result(); 154872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ssl_host_info_->WaitForCertVerification(&handshake_io_callback_); 154972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 155072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UMA_HISTOGRAM_ENUMERATION("Net.SSLVerificationMerged", 0 /* false */, 2); 1551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 155372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int flags = 0; 155472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (ssl_config_.rev_checking_enabled) 155572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; 155672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (ssl_config_.verify_ev_cert) 155772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen flags |= X509Certificate::VERIFY_EV_CERT; 155872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen verifier_.reset(new SingleRequestCertVerifier(cert_verifier_)); 155972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen server_cert_verify_result_ = &local_server_cert_verify_result_; 156072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return verifier_->Verify(server_cert_, host_and_port_.host(), flags, 156172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &local_server_cert_verify_result_, 156272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &handshake_io_callback_); 156372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 1564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 156572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Derived from AuthCertificateCallback() in 156672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp. 156772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint SSLClientSocketNSS::DoVerifyCertComplete(int result) { 156872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen verifier_.reset(); 1569513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 157072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!start_cert_verification_time_.is_null()) { 157172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::TimeDelta verify_time = 157272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::TimeTicks::Now() - start_cert_verification_time_; 157372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (result == OK) 157472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTime", verify_time); 157572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen else 157672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UMA_HISTOGRAM_TIMES("Net.SSLCertVerificationTimeError", verify_time); 157772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 1578513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 157972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // We used to remember the intermediate CA certs in the NSS database 158072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // persistently. However, NSS opens a connection to the SQLite database 158172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // during NSS initialization and doesn't close the connection until NSS 158272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // shuts down. If the file system where the database resides is gone, 158372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // the database connection goes bad. What's worse, the connection won't 158472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // recover when the file system comes back. Until this NSS or SQLite bug 158572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // is fixed, we need to avoid using the NSS database for non-essential 158672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // purposes. See https://bugzilla.mozilla.org/show_bug.cgi?id=508081 and 158772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // http://crbug.com/15630 for more info. 1588513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 158972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If we have been explicitly told to accept this certificate, override the 159072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // result of verifier_.Verify. 159172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Eventually, we should cache the cert verification results so that we don't 159272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // need to call verifier_.Verify repeatedly. But for now we need to do this. 159372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Alternatively, we could use the cert's status that we stored along with 159472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // the cert in the allowed_bad_certs vector. 159572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (IsCertificateError(result) && 159672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ssl_config_.IsAllowedBadCert(server_cert_)) { 159772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen VLOG(1) << "accepting bad SSL certificate, as user told us to"; 159872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen result = OK; 1599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 160172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (result == OK) 160272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LogConnectionTypeMetrics(); 1603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 160472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen completed_handshake_ = true; 160572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 160672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (user_read_callback_) { 160772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int rv = DoReadLoop(OK); 160872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv != ERR_IO_PENDING) 160972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DoReadCallback(rv); 161072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 1611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 161272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Exit DoHandshakeLoop and return the result to the caller to Connect. 161372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(next_handshake_state_ == STATE_NONE); 161472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return result; 1615513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 1616513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 161772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint SSLClientSocketNSS::DoPayloadRead() { 161872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(user_read_buf_len_); 161972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(user_read_buf_); 162072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_GT(user_read_buf_len_, 0); 162172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_); 162272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (client_auth_cert_needed_) { 162372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // We don't need to invalidate the non-client-authenticated SSL session 162472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // because the server will renegotiate anyway. 162572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(""); 162672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; 162772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR, 162872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen make_scoped_refptr(new SSLErrorParams(rv, 0))); 162972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return rv; 163072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 163172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv >= 0) { 163272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LogData(user_read_buf_->data(), rv); 163372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(""); 163472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return rv; 163572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 163672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PRErrorCode prerr = PR_GetError(); 163772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (prerr == PR_WOULD_BLOCK_ERROR) { 163872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(""); 163972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ERR_IO_PENDING; 164072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 164172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(""); 164272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = HandleNSSError(prerr, false); 164372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR, 164472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen make_scoped_refptr(new SSLErrorParams(rv, prerr))); 164572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return rv; 164672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 1647513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 164872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint SSLClientSocketNSS::DoPayloadWrite() { 164972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(user_write_buf_len_); 165072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(user_write_buf_); 165172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_); 165272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv >= 0) { 165372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LogData(user_write_buf_->data(), rv); 165472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(""); 165572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return rv; 165672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 165772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PRErrorCode prerr = PR_GetError(); 165872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (prerr == PR_WOULD_BLOCK_ERROR) { 165972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(""); 166072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ERR_IO_PENDING; 166172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 166272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(""); 166372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = HandleNSSError(prerr, false); 166472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR, 166572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen make_scoped_refptr(new SSLErrorParams(rv, prerr))); 166672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return rv; 166772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 1668513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 166972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLClientSocketNSS::LogConnectionTypeMetrics() const { 167072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UpdateConnectionTypeHistograms(CONNECTION_SSL); 167172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (server_cert_verify_result_->has_md5) 167272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5); 167372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (server_cert_verify_result_->has_md2) 167472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2); 167572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (server_cert_verify_result_->has_md4) 167672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UpdateConnectionTypeHistograms(CONNECTION_SSL_MD4); 167772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (server_cert_verify_result_->has_md5_ca) 167872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5_CA); 167972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (server_cert_verify_result_->has_md2_ca) 168072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA); 168172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int ssl_version = SSLConnectionStatusToVersion(ssl_connection_status_); 168272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen switch (ssl_version) { 168372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SSL_CONNECTION_VERSION_SSL2: 168472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL2); 168572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 168672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SSL_CONNECTION_VERSION_SSL3: 168772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL3); 168872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 168972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SSL_CONNECTION_VERSION_TLS1: 169072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1); 169172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 169272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SSL_CONNECTION_VERSION_TLS1_1: 169372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_1); 169472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 169572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SSL_CONNECTION_VERSION_TLS1_2: 169672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_2); 169772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 169872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }; 169972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 1700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1701ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// SaveSSLHostInfo saves the certificate chain of the connection so that we can 1702ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// start verification faster in the future. 1703ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SSLClientSocketNSS::SaveSSLHostInfo() { 170472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!ssl_host_info_.get()) 170572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 170672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 170772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If the SSLHostInfo hasn't managed to load from disk yet then we can't save 170872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // anything. 170972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (ssl_host_info_->WaitForDataReady(NULL) != OK) 171072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 171172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 171272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSLHostInfo::State* state = ssl_host_info_->mutable_state(); 1713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 171472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen state->certs.clear(); 171572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PeerCertificateChain certs(nss_fd_); 171672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (unsigned i = 0; i < certs.size(); i++) { 171772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (certs[i]->derCert.len > std::numeric_limits<uint16>::max()) 171872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 1719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 172072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen state->certs.push_back(std::string( 172172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen reinterpret_cast<char*>(certs[i]->derCert.data), 172272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen certs[i]->derCert.len)); 172372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 1724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 172572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ssl_host_info_->Persist(); 1726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 172872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLClientSocketNSS::UncorkAfterTimeout() { 172972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen corked_ = false; 173072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int nsent; 173172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen do { 173272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen nsent = BufferSend(); 173372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } while (nsent > 0); 173472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 1735513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 173672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Do network I/O between the given buffer and the given socket. 173772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING) 173872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SSLClientSocketNSS::DoTransportIO() { 173972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(""); 174072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool network_moved = false; 174172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (nss_bufs_ != NULL) { 174272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int nsent = BufferSend(); 174372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int nreceived = BufferRecv(); 174472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen network_moved = (nsent > 0 || nreceived >= 0); 174572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 174672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(network_moved); 174772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return network_moved; 174872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 17493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 175072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Return 0 for EOF, 175172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// > 0 for bytes transferred immediately, 175272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// < 0 for error (or the non-error ERR_IO_PENDING). 175372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint SSLClientSocketNSS::BufferSend(void) { 175472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (transport_send_busy_) 175572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ERR_IO_PENDING; 17563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 175772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(""); 175872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const char* buf1; 175972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const char* buf2; 176072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen unsigned int len1, len2; 176172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2); 176272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const unsigned int len = len1 + len2; 17633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 176472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (corked_ && len < kRecvBufferSize / 2) 176572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return 0; 1766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 176772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int rv = 0; 176872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (len) { 176972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len)); 177072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memcpy(send_buffer->data(), buf1, len1); 177172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memcpy(send_buffer->data() + len1, buf2, len2); 177272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = transport_->socket()->Write(send_buffer, len, 177372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &buffer_send_callback_); 177472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv == ERR_IO_PENDING) { 177572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen transport_send_busy_ = true; 1776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 177772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv)); 1778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 178172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(rv); 178272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return rv; 1783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 178572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLClientSocketNSS::BufferSendComplete(int result) { 178672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(result); 17873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 178872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // In the case of TCP FastOpen, connect is now finished. 178972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!peername_initialized_ && UsingTCPFastOpen()) 179072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen InitializeSSLPeerName(); 17913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 179272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result)); 179372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen transport_send_busy_ = false; 179472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnSendComplete(result); 179572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(""); 179672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 17973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 179872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint SSLClientSocketNSS::BufferRecv(void) { 179972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (transport_recv_busy_) return ERR_IO_PENDING; 18003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 180172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen char *buf; 180272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int nb = memio_GetReadParams(nss_bufs_, &buf); 180372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(nb); 180472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int rv; 180572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!nb) { 180672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // buffer too full to read into, so no I/O possible at moment 180772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = ERR_IO_PENDING; 180872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 180972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen recv_buffer_ = new IOBuffer(nb); 181072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = transport_->socket()->Read(recv_buffer_, nb, &buffer_recv_callback_); 181172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv == ERR_IO_PENDING) { 181272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen transport_recv_busy_ = true; 18133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 181472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv > 0) 181572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memcpy(buf, recv_buffer_->data(), rv); 181672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv)); 181772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen recv_buffer_ = NULL; 18183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 181972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 182072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(rv); 182172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return rv; 182272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 18233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 182472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLClientSocketNSS::BufferRecvComplete(int result) { 182572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnterFunction(result); 182672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (result > 0) { 182772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen char *buf; 182872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memio_GetReadParams(nss_bufs_, &buf); 182972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memcpy(buf, recv_buffer_->data(), result); 183072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 183172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen recv_buffer_ = NULL; 183272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memio_PutReadResult(nss_bufs_, MapErrorToNSS(result)); 183372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen transport_recv_busy_ = false; 183472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnRecvComplete(result); 183572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LeaveFunction(""); 183672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 18373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 183872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint SSLClientSocketNSS::HandleNSSError(PRErrorCode nss_error, 183972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool handshake_error) { 184072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int net_error = handshake_error ? MapNSSHandshakeError(nss_error) : 184172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen MapNSSError(nss_error); 18423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 184372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_WIN) 184472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // On Windows, a handle to the HCRYPTPROV is cached in the X509Certificate 184572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // os_cert_handle() as an optimization. However, if the certificate 184672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // private key is stored on a smart card, and the smart card is removed, 184772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // the cached HCRYPTPROV will not be able to obtain the HCRYPTKEY again, 184872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // preventing client certificate authentication. Because the 184972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // X509Certificate may outlive the individual SSLClientSocketNSS, due to 185072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // caching in X509Certificate, this failure ends up preventing client 185172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // certificate authentication with the same certificate for all future 185272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // attempts, even after the smart card has been re-inserted. By setting 185372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // the CERT_KEY_PROV_HANDLE_PROP_ID to NULL, the cached HCRYPTPROV will 185472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // typically be freed. This allows a new HCRYPTPROV to be obtained from 185572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // the certificate on the next attempt, which should succeed if the smart 185672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // card has been re-inserted, or will typically prompt the user to 185772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // re-insert the smart card if not. 185872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if ((net_error == ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY || 185972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_error == ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED) && 186072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ssl_config_.send_client_cert && ssl_config_.client_cert) { 186172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CertSetCertificateContextProperty( 186272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ssl_config_.client_cert->os_cert_handle(), 186372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL); 186472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 186572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif 18663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 186772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return net_error; 186872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 18693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 187072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static 187172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// NSS calls this if an incoming certificate needs to be verified. 187272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Do nothing but return SECSuccess. 187372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// This is called only in full handshake mode. 187472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Peer certificate is retrieved in HandshakeCallback() later, which is called 187572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// in full handshake mode or in resumption handshake mode. 187672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSECStatus SSLClientSocketNSS::OwnAuthCertHandler(void* arg, 187772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PRFileDesc* socket, 187872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PRBool checksig, 187972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PRBool is_server) { 188072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#ifdef SSL_ENABLE_FALSE_START 188172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // In the event that we are False Starting this connection, we wish to send 188272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // out the Finished message and first application data record in the same 188372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // packet. This prevents non-determinism when talking to False Start 188472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // intolerant servers which, otherwise, might see the two messages in 188572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // different reads or not, depending on network conditions. 188672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PRBool false_start = 0; 188772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SECStatus rv = SSL_OptionGet(socket, SSL_ENABLE_FALSE_START, &false_start); 188872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_EQ(SECSuccess, rv); 18893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 189072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (false_start) { 189172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); 18923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 189372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // ESET anti-virus is capable of intercepting HTTPS connections on Windows. 189472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // However, it is False Start intolerant and causes the connections to hang 189572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // forever. We detect ESET by the issuer of the leaf certificate and set a 189672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // flag to return a specific error, giving the user instructions for 189772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // reconfiguring ESET. 189872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERTCertificate* cert = SSL_PeerCertificate(that->nss_fd_); 189972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (cert) { 190072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen char* common_name = CERT_GetCommonName(&cert->issuer); 190172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (common_name) { 190272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (strcmp(common_name, "ESET_RootSslCert") == 0) 190372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen that->eset_mitm_detected_ = true; 190472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (strcmp(common_name, 190572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "ContentWatch Root Certificate Authority") == 0) { 190672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // This is NetNanny. NetNanny are updating their product so we 190772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // silently disable False Start for now. 190872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = SSL_OptionSet(socket, SSL_ENABLE_FALSE_START, PR_FALSE); 190972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_EQ(SECSuccess, rv); 191072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen false_start = 0; 191172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 191272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PORT_Free(common_name); 191372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 191472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_DestroyCertificate(cert); 191572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 19163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 191772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (false_start && !that->handshake_callback_called_) { 191872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen that->corked_ = true; 191972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen that->uncork_timer_.Start( 192072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::TimeDelta::FromMilliseconds(kCorkTimeoutMs), 192172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen that, &SSLClientSocketNSS::UncorkAfterTimeout); 19223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 19233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 192472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif 19253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 192672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Tell NSS to not verify the certificate. 192772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return SECSuccess; 19283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 19293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 193072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(NSS_PLATFORM_CLIENT_AUTH) 193172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static 193272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// NSS calls this if a client certificate is needed. 193372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSECStatus SSLClientSocketNSS::PlatformClientAuthHandler( 193472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void* arg, 193572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PRFileDesc* socket, 193672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERTDistNames* ca_names, 193772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERTCertList** result_certs, 193872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void** result_private_key) { 193972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); 19403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 194172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen that->client_auth_cert_needed_ = !that->ssl_config_.send_client_cert; 194272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_WIN) 194372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (that->ssl_config_.send_client_cert) { 194472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (that->ssl_config_.client_cert) { 194572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PCCERT_CONTEXT cert_context = 194672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen that->ssl_config_.client_cert->os_cert_handle(); 194772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PCERT_KEY_CONTEXT key_context = reinterpret_cast<PCERT_KEY_CONTEXT>( 194872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PORT_ZAlloc(sizeof(CERT_KEY_CONTEXT))); 194972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!key_context) 195072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return SECFailure; 195172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen key_context->cbSize = sizeof(*key_context); 19523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 195372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BOOL must_free = FALSE; 195472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BOOL acquired_key = CryptAcquireCertificatePrivateKey( 195572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen cert_context, CRYPT_ACQUIRE_CACHE_FLAG, NULL, 195672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &key_context->hCryptProv, &key_context->dwKeySpec, &must_free); 195772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (acquired_key && key_context->hCryptProv) { 195872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_NE(key_context->dwKeySpec, CERT_NCRYPT_KEY_SPEC); 195972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 196072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // The certificate cache may have been updated/used, in which case, 196172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // duplicate the existing handle, since NSS will free it when no 196272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // longer in use. 196372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!must_free) 196472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CryptContextAddRef(key_context->hCryptProv, NULL, 0); 196572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 196672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SECItem der_cert; 196772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen der_cert.type = siDERCertBuffer; 196872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen der_cert.data = cert_context->pbCertEncoded; 196972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen der_cert.len = cert_context->cbCertEncoded; 197072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 197172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TODO(rsleevi): Error checking for NSS allocation errors. 197272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *result_certs = CERT_NewCertList(); 197372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERTCertDBHandle* db_handle = CERT_GetDefaultCertDB(); 197472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERTCertificate* user_cert = CERT_NewTempCertificate( 197572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE); 197672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_AddCertToListTail(*result_certs, user_cert); 19773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 197872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Add the intermediates. 197972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen X509Certificate::OSCertHandles intermediates = 198072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen that->ssl_config_.client_cert->GetIntermediateCertificates(); 198172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (X509Certificate::OSCertHandles::const_iterator it = 198272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen intermediates.begin(); it != intermediates.end(); ++it) { 198372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen der_cert.data = (*it)->pbCertEncoded; 198472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen der_cert.len = (*it)->cbCertEncoded; 19853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 198672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERTCertificate* intermediate = CERT_NewTempCertificate( 198772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen db_handle, &der_cert, NULL, PR_FALSE, PR_TRUE); 198872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_AddCertToListTail(*result_certs, intermediate); 198972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 199072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *result_private_key = key_context; 199172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return SECSuccess; 199272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 199372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PORT_Free(key_context); 199472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LOG(WARNING) << "Client cert found without private key"; 199572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 199672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Send no client certificate. 199772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return SECFailure; 19983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 19993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 200072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen that->client_certs_.clear(); 20013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 200272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::vector<CERT_NAME_BLOB> issuer_list(ca_names->nnames); 200372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (int i = 0; i < ca_names->nnames; ++i) { 200472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen issuer_list[i].cbData = ca_names->names[i].len; 200572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen issuer_list[i].pbData = ca_names->names[i].data; 2006201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 2007201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 200872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Client certificates of the user are in the "MY" system certificate store. 200972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen HCERTSTORE my_cert_store = CertOpenSystemStore(NULL, L"MY"); 201072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!my_cert_store) { 201172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LOG(ERROR) << "Could not open the \"MY\" system certificate store: " 201272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen << GetLastError(); 201372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return SECFailure; 20143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 20153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 201672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Enumerate the client certificates. 201772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_CHAIN_FIND_BY_ISSUER_PARA find_by_issuer_para; 201872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memset(&find_by_issuer_para, 0, sizeof(find_by_issuer_para)); 201972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen find_by_issuer_para.cbSize = sizeof(find_by_issuer_para); 202072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen find_by_issuer_para.pszUsageIdentifier = szOID_PKIX_KP_CLIENT_AUTH; 202172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen find_by_issuer_para.cIssuer = ca_names->nnames; 202272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen find_by_issuer_para.rgIssuer = ca_names->nnames ? &issuer_list[0] : NULL; 202372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen find_by_issuer_para.pfnFindCallback = ClientCertFindCallback; 20243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 202572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PCCERT_CHAIN_CONTEXT chain_context = NULL; 20263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 202772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (;;) { 202872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Find a certificate chain. 202972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen chain_context = CertFindChainInStore(my_cert_store, 203072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen X509_ASN_ENCODING, 203172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 0, 203272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_CHAIN_FIND_BY_ISSUER, 203372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &find_by_issuer_para, 203472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen chain_context); 203572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!chain_context) { 203672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DWORD err = GetLastError(); 203772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (err != CRYPT_E_NOT_FOUND) 203872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DLOG(ERROR) << "CertFindChainInStore failed: " << err; 203972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 204072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 20413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 204272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Get the leaf certificate. 204372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PCCERT_CONTEXT cert_context = 204472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen chain_context->rgpChain[0]->rgpElement[0]->pCertContext; 204572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Copy it to our own certificate store, so that we can close the "MY" 204672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // certificate store before returning from this function. 204772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PCCERT_CONTEXT cert_context2; 204872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BOOL ok = CertAddCertificateContextToStore(X509Certificate::cert_store(), 204972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen cert_context, 205072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_STORE_ADD_USE_EXISTING, 205172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &cert_context2); 205272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!ok) { 205372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NOTREACHED(); 205472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen continue; 205572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 20563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 205772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Copy the rest of the chain to our own store as well. Copying the chain 205872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // stops gracefully if an error is encountered, with the partial chain 205972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // being used as the intermediates, rather than failing to consider the 206072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // client certificate. 206172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net::X509Certificate::OSCertHandles intermediates; 206272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (DWORD i = 1; i < chain_context->rgpChain[0]->cElement; i++) { 206372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PCCERT_CONTEXT intermediate_copy; 206472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ok = CertAddCertificateContextToStore(X509Certificate::cert_store(), 206572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen chain_context->rgpChain[0]->rgpElement[i]->pCertContext, 206672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_STORE_ADD_USE_EXISTING, &intermediate_copy); 206772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!ok) { 206872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NOTREACHED(); 206972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 207072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 207172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen intermediates.push_back(intermediate_copy); 207272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 20733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 207472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( 207572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen cert_context2, X509Certificate::SOURCE_LONE_CERT_IMPORT, 207672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen intermediates); 207772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen that->client_certs_.push_back(cert); 20783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 207972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen X509Certificate::FreeOSCertHandle(cert_context2); 208072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (net::X509Certificate::OSCertHandles::iterator it = 208172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen intermediates.begin(); it != intermediates.end(); ++it) { 208272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net::X509Certificate::FreeOSCertHandle(*it); 208372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 20843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 20853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 208672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BOOL ok = CertCloseStore(my_cert_store, CERT_CLOSE_STORE_CHECK_FLAG); 208772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(ok); 20883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 208972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Tell NSS to suspend the client authentication. We will then abort the 209072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED. 209172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return SECWouldBlock; 209272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#elif defined(OS_MACOSX) 209372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (that->ssl_config_.send_client_cert) { 209472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (that->ssl_config_.client_cert) { 209572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OSStatus os_error = noErr; 209672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SecIdentityRef identity = NULL; 209772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SecKeyRef private_key = NULL; 209872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CFArrayRef chain = 209972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen that->ssl_config_.client_cert->CreateClientCertificateChain(); 210072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (chain) { 210172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen identity = reinterpret_cast<SecIdentityRef>( 210272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const_cast<void*>(CFArrayGetValueAtIndex(chain, 0))); 210372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 210472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (identity) 210572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen os_error = SecIdentityCopyPrivateKey(identity, &private_key); 21063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 210772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (chain && identity && os_error == noErr) { 210872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TODO(rsleevi): Error checking for NSS allocation errors. 210972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *result_certs = CERT_NewCertList(); 211072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *result_private_key = private_key; 2111513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 211272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (CFIndex i = 0; i < CFArrayGetCount(chain); ++i) { 211372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CSSM_DATA cert_data; 211472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SecCertificateRef cert_ref; 211572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (i == 0) { 211672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen cert_ref = that->ssl_config_.client_cert->os_cert_handle(); 211772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 211872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen cert_ref = reinterpret_cast<SecCertificateRef>( 211972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const_cast<void*>(CFArrayGetValueAtIndex(chain, i))); 212072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 212172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen os_error = SecCertificateGetData(cert_ref, &cert_data); 212272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (os_error != noErr) 212372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 2124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 212572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SECItem der_cert; 212672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen der_cert.type = siDERCertBuffer; 212772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen der_cert.data = cert_data.Data; 212872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen der_cert.len = cert_data.Length; 212972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERTCertificate* nss_cert = CERT_NewTempCertificate( 213072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE); 213172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_AddCertToListTail(*result_certs, nss_cert); 213272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 213372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 213472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (os_error == noErr) { 213572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CFRelease(chain); 213672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return SECSuccess; 213772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 213872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LOG(WARNING) << "Client cert found, but could not be used: " 213972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen << os_error; 214072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (*result_certs) { 214172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_DestroyCertList(*result_certs); 214272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *result_certs = NULL; 214372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 214472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (*result_private_key) 214572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *result_private_key = NULL; 214672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (private_key) 214772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CFRelease(private_key); 214872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (chain) 214972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CFRelease(chain); 215072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 215172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Send no client certificate. 215272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return SECFailure; 2153513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 2154513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 215572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen that->client_certs_.clear(); 215621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 215772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // First, get the cert issuer names allowed by the server. 215872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::vector<CertPrincipal> valid_issuers; 215972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int n = ca_names->nnames; 216072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (int i = 0; i < n; i++) { 216172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Parse each name into a CertPrincipal object. 216272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CertPrincipal p; 216372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (p.ParseDistinguishedName(ca_names->names[i].data, 216472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ca_names->names[i].len)) { 216572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen valid_issuers.push_back(p); 216672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 216721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 216821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 216972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Now get the available client certs whose issuers are allowed by the server. 217072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen X509Certificate::GetSSLClientCertificates(that->host_and_port_.host(), 217172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen valid_issuers, 217272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &that->client_certs_); 2173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 217472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Tell NSS to suspend the client authentication. We will then abort the 217572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED. 217672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return SECWouldBlock; 217772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#else 217872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return SECFailure; 217972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif 218072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 2181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 218272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#else // NSS_PLATFORM_CLIENT_AUTH 2183513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 218472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static 218572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// NSS calls this if a client certificate is needed. 218672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Based on Mozilla's NSS_GetClientAuthData. 218772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSECStatus SSLClientSocketNSS::ClientAuthHandler( 218872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void* arg, 218972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PRFileDesc* socket, 219072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERTDistNames* ca_names, 219172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERTCertificate** result_certificate, 219272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SECKEYPrivateKey** result_private_key) { 219372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); 2194731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 219572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen that->client_auth_cert_needed_ = !that->ssl_config_.send_client_cert; 219672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void* wincx = SSL_RevealPinArg(socket); 219772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 219872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Second pass: a client certificate should have been selected. 219972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (that->ssl_config_.send_client_cert) { 220072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (that->ssl_config_.client_cert) { 220172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERTCertificate* cert = CERT_DupCertificate( 220272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen that->ssl_config_.client_cert->os_cert_handle()); 220372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SECKEYPrivateKey* privkey = PK11_FindKeyByAnyCert(cert, wincx); 220472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (privkey) { 220572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TODO(jsorianopastor): We should wait for server certificate 220672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // verification before sending our credentials. See 220772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // http://crbug.com/13934. 220872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *result_certificate = cert; 220972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *result_private_key = privkey; 221072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return SECSuccess; 2211513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 221272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LOG(WARNING) << "Client cert found without private key"; 2213513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 221472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Send no client certificate. 221572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return SECFailure; 2216513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 2217513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 221872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Iterate over all client certificates. 221972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERTCertList* client_certs = CERT_FindUserCertsByUsage( 222072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_GetDefaultCertDB(), certUsageSSLClient, 222172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PR_FALSE, PR_FALSE, wincx); 222272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (client_certs) { 222372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (CERTCertListNode* node = CERT_LIST_HEAD(client_certs); 222472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen !CERT_LIST_END(node, client_certs); 222572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node = CERT_LIST_NEXT(node)) { 222672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Only offer unexpired certificates. 222772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (CERT_CheckCertValidTimes(node->cert, PR_Now(), PR_TRUE) != 222872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen secCertTimeValid) 222972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen continue; 223072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Filter by issuer. 223172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // 223272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TODO(davidben): This does a binary comparison of the DER-encoded 223372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // issuers. We should match according to RFC 5280 sec. 7.1. We should find 223472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // an appropriate NSS function or add one if needbe. 223572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (ca_names->nnames && 223672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NSS_CmpCertChainWCANames(node->cert, ca_names) != SECSuccess) 223772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen continue; 223872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen X509Certificate* x509_cert = X509Certificate::CreateFromHandle( 223972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node->cert, X509Certificate::SOURCE_LONE_CERT_IMPORT, 224072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net::X509Certificate::OSCertHandles()); 224172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen that->client_certs_.push_back(x509_cert); 224272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 224372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CERT_DestroyCertList(client_certs); 2244731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 2245731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 224672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Tell NSS to suspend the client authentication. We will then abort the 224772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // handshake by returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED. 224872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return SECWouldBlock; 2249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 225072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif // NSS_PLATFORM_CLIENT_AUTH 2251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 225272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static 225372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// NSS calls this when handshake is completed. 225472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// After the SSL handshake is finished, use CertVerifier to verify 225572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// the saved server certificate. 225672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLClientSocketNSS::HandshakeCallback(PRFileDesc* socket, 225772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void* arg) { 225872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); 225972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 226072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen that->handshake_callback_called_ = true; 226172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 226272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen that->UpdateServerCert(); 226372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen that->UpdateConnectionStatus(); 2264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 2265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 226672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLClientSocketNSS::EnsureThreadIdAssigned() const { 226772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::AutoLock auto_lock(lock_); 226872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (valid_thread_id_ != base::kInvalidThreadId) 226972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 227072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen valid_thread_id_ = base::PlatformThread::CurrentId(); 2271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 2272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 227372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SSLClientSocketNSS::CalledOnValidThread() const { 227472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EnsureThreadIdAssigned(); 227572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::AutoLock auto_lock(lock_); 227672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return valid_thread_id_ == base::PlatformThread::CurrentId(); 2277513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 2278513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 2279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 2280