1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian 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#include "net/socket/ssl_client_socket_mac.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <CoreServices/CoreServices.h> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <netdb.h> 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <sys/socket.h> 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <sys/types.h> 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include <algorithm> 134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 14ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch#include "base/lazy_instance.h" 15731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/mac/scoped_cftyperef.h" 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/address_list.h" 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/cert_verifier.h" 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/io_buffer.h" 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_log.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/ssl_cert_request_info.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/ssl_connection_status_flags.h" 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/ssl_info.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/socket/client_socket_handle.h" 264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "net/socket/ssl_error_params.h" 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Welcome to Mac SSL. We've been waiting for you. 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The Mac SSL implementation is, like the Windows and NSS implementations, a 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// giant state machine. This design constraint is due to the asynchronous nature 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// of our underlying transport mechanism. We can call down to read/write on the 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// network, but what happens is that either it completes immediately or returns 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// saying that we'll get a callback sometime in the future. In that case, we 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// have to return to our caller but pick up where we left off when we 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// resume. Thus the fun. 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// On Windows, we use Security Contexts, which are driven by us. We fetch data 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// from the network, we call the context to decrypt the data, and so on. On the 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Mac, however, we provide Secure Transport with callbacks to get data from the 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// network, and it calls us back to fetch the data from the network for 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// it. Therefore, there are different sets of states in our respective state 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// machines, fewer on the Mac because Secure Transport keeps a lot of its own 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// state. The discussion about what each of the states means lives in comments 45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// in the DoHandshakeLoop() function. 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Secure Transport is designed for use by either blocking or non-blocking 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// network I/O. If, for example, you called SSLRead() to fetch data, Secure 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Transport will, unless it has some cached data, issue a read to your network 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// callback read function to fetch it some more encrypted data. It's expecting 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// one of two things. If your function is hooked up to a blocking source, then 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// it'll block pending receipt of the data from the other end. That's fine, as 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// when you return with the data, Secure Transport will do its thing. On the 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// other hand, suppose that your socket is non-blocking and tells your function 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// that it would block. Then you let Secure Transport know, and it'll tell the 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// original caller that it would have blocked and that they need to call it 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// "later." 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// When's "later," though? We have fully-asynchronous networking, so we get a 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// callback when our data's ready. But Secure Transport has no way for us to 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// tell it that data has arrived, so we must re-execute the call that triggered 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the I/O (we rely on our state machine to do this). When we do so Secure 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Transport will ask once again for the data. Chances are that it'll be the 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// same request as the previous time, but that's not actually guaranteed. But as 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// long as we buffer what we have and keep track of where we were, it works 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// quite well. 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Except for network writes. They shoot this plan straight to hell. 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Faking a blocking connection with an asynchronous connection (theoretically 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// more powerful) simply doesn't work for writing. Suppose that Secure Transport 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// requests a write of data to the network. With blocking I/O, we'd just block 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// until the write completed, and with non-blocking I/O we'd know how many bytes 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// we wrote before we would have blocked. But with the asynchronous I/O, the 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// transport underneath us can tell us that it'll let us know sometime "later" 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// whether or not things succeeded, and how many bytes were written. What do we 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// return to Secure Transport? We can't return a byte count, but we can't return 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// "later" as we're not guaranteed to be called in the future with the same data 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// to write. 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// So, like in any good relationship, we're forced to lie. Whenever Secure 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Transport asks for data to be written, we take it all and lie about it always 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// being written. We spin in a loop (see SSLWriteCallback() and 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// OnTransportWriteComplete()) independent of the main state machine writing 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the data to the network, and get the data out. The main consequence of this 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// independence from the state machine is that we require a full-duplex 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// transport underneath us since we can't use it to keep our reading and 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// writing straight. Fortunately, the NSS implementation also has this issue 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// to deal with, so we share the same Libevent-based full-duplex TCP socket. 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A side comment on return values might be in order. Those who haven't taken 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the time to read the documentation (ahem, header comments) in our various 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// files might be a bit surprised to see result values being treated as both 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// lengths and errors. Like Shimmer, they are both. In both the case of 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// immediate results as well as results returned in callbacks, a negative return 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// value indicates an error, a zero return value indicates end-of-stream (for 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// reads), and a positive return value indicates the number of bytes read or 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// written. Thus, many functions start off with |if (result < 0) return 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// result;|. That gets the error condition out of the way, and from that point 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// forward the result can be treated as a length. 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net { 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Pause if we have 2MB of data in flight, resume once we're down below 1MB. 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst unsigned int kWriteSizePauseLimit = 2 * 1024 * 1024; 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst unsigned int kWriteSizeResumeLimit = 1 * 1024 * 1024; 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// When compiled against the Mac OS X 10.5 SDK, define symbolic constants for 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// cipher suites added in Mac OS X 10.6. 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottenum { 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // ECC cipher suites from RFC 4492. 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001, 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002, 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003, 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004, 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005, 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006, 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007, 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008, 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009, 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A, 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B, 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C, 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D, 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E, 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F, 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010, 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011, 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012, 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013, 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014, 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDH_anon_WITH_NULL_SHA = 0xC015, 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016, 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017, 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018, 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019, 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// For an explanation of the Mac OS X error codes, please refer to: 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// http://developer.apple.com/mac/library/documentation/Security/Reference/secureTransportRef/Reference/reference.html 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint NetErrorFromOSStatus(OSStatus status) { 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (status) { 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLWouldBlock: 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_IO_PENDING; 1494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch case paramErr: 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLBadCipherSuite: 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLBadConfiguration: 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_INVALID_ARGUMENT; 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLClosedNoNotify: 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CONNECTION_RESET; 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLClosedAbort: 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CONNECTION_ABORTED; 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLInternal: 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_UNEXPECTED; 159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case errSSLBadRecordMac: 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLCrypto: 161731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case errSSLConnectionRefused: 162731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case errSSLDecryptionFail: 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLFatalAlert: 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLIllegalParam: // Received an illegal_parameter alert. 165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case errSSLPeerDecodeError: // Received a decode_error alert. 166731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case errSSLPeerDecryptError: // Received a decrypt_error alert. 167731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case errSSLPeerExportRestriction: // Received an export_restriction alert. 168731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case errSSLPeerHandshakeFail: // Received a handshake_failure alert. 169731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case errSSLPeerNoRenegotiation: // Received a no_renegotiation alert 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLPeerUnexpectedMsg: // Received an unexpected_message alert. 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLProtocol: 172731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case errSSLRecordOverflow: 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_SSL_PROTOCOL_ERROR; 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLHostNameMismatch: 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CERT_COMMON_NAME_INVALID; 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLCertExpired: 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLCertNotYetValid: 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CERT_DATE_INVALID; 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLNoRootCert: 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLUnknownRootCert: 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CERT_AUTHORITY_INVALID; 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLXCertChainInvalid: 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLBadCert: 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CERT_INVALID; 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLClosedGraceful: 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case noErr: 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 190731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // (Note that all errSSLPeer* codes indicate errors reported by the peer, 191731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // so the cert-related ones refer to my _client_ cert.) 192731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO(wtc): Add fine-grained error codes for client certificate errors 193731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // reported by the server using the following SSL/TLS alert messages: 194731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // access_denied 195731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // bad_certificate 196731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // unsupported_certificate 197731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // certificate_expired 198731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // certificate_revoked 199731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // certificate_unknown 200731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // unknown_ca 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case errSSLPeerCertUnknown...errSSLPeerBadCert: 202731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case errSSLPeerUnknownCA: 203731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case errSSLPeerAccessDenied: 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(WARNING) << "Server rejected client cert (OSStatus=" << status << ")"; 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_BAD_SSL_CLIENT_AUTH_CERT; 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch case errSSLNegotiation: 208731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case errSSLPeerInsufficientSecurity: 209731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case errSSLPeerProtocolVersion: 210731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_SSL_VERSION_OR_CIPHER_MISMATCH; 211731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLBufferOverflow: 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLModuleAttach: 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case errSSLSessionNotFound: 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(WARNING) << "Unknown error " << status << 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott " mapped to net::ERR_FAILED"; 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_FAILED; 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottOSStatus OSStatusFromNetError(int net_error) { 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (net_error) { 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ERR_IO_PENDING: 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return errSSLWouldBlock; 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ERR_INTERNET_DISCONNECTED: 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ERR_TIMED_OUT: 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ERR_CONNECTION_ABORTED: 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ERR_CONNECTION_RESET: 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ERR_CONNECTION_REFUSED: 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ERR_ADDRESS_UNREACHABLE: 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ERR_ADDRESS_INVALID: 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return errSSLClosedAbort; 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ERR_UNEXPECTED: 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return errSSLInternal; 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ERR_INVALID_ARGUMENT: 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return paramErr; 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case OK: 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return noErr; 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(WARNING) << "Unknown error " << net_error << 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott " mapped to paramErr"; 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return paramErr; 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Converts from a cipher suite to its key size. If the suite is marked with a 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// **, it's not actually implemented in Secure Transport and won't be returned 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// (but we'll code for it anyway). The reference here is 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// http://www.opensource.apple.com/darwinsource/10.5.5/libsecurity_ssl-32463/lib/cipherSpecs.c 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Seriously, though, there has to be an API for this, but I can't find one. 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Anybody? 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint KeySizeOfCipherSuite(SSLCipherSuite suite) { 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (suite) { 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // SSL 2 only 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_WITH_DES_CBC_MD5: 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 56; 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_WITH_3DES_EDE_CBC_MD5: 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 112; 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_WITH_RC2_CBC_MD5: 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_WITH_IDEA_CBC_MD5: // ** 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 128; 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_NO_SUCH_CIPHERSUITE: // ** 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // SSL 2, 3, TLS 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_NULL_WITH_NULL_NULL: 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_WITH_NULL_MD5: 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_WITH_NULL_SHA: // ** 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_FORTEZZA_DMS_WITH_NULL_SHA: // ** 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_ECDSA_WITH_NULL_SHA: 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_ECDSA_WITH_NULL_SHA: 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_RSA_WITH_NULL_SHA: 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_RSA_WITH_NULL_SHA: 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_anon_WITH_NULL_SHA: 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_EXPORT_WITH_RC4_40_MD5: 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: // ** 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: // ** 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 40; 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_WITH_DES_CBC_SHA: 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DH_DSS_WITH_DES_CBC_SHA: // ** 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DH_RSA_WITH_DES_CBC_SHA: // ** 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DHE_DSS_WITH_DES_CBC_SHA: 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DHE_RSA_WITH_DES_CBC_SHA: 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DH_anon_WITH_DES_CBC_SHA: 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 56; 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: // ** 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 80; 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_WITH_3DES_EDE_CBC_SHA: 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: // ** 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: // ** 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 112; 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_WITH_RC4_128_MD5: 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_WITH_RC4_128_SHA: 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_WITH_IDEA_CBC_SHA: // ** 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DH_anon_WITH_RC4_128_MD5: 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_RSA_WITH_RC4_128_SHA: 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_RSA_WITH_RC4_128_SHA: 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_anon_WITH_RC4_128_SHA: 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 128; 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TLS AES options (see RFC 3268 and RFC 4492) 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_RSA_WITH_AES_128_CBC_SHA: 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DH_DSS_WITH_AES_128_CBC_SHA: // ** 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DH_RSA_WITH_AES_128_CBC_SHA: // ** 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DH_anon_WITH_AES_128_CBC_SHA: 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 128; 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_RSA_WITH_AES_256_CBC_SHA: 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DH_DSS_WITH_AES_256_CBC_SHA: // ** 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DH_RSA_WITH_AES_256_CBC_SHA: // ** 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DH_anon_WITH_AES_256_CBC_SHA: 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 256; 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return -1; 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Whitelist the cipher suites we want to enable. We disable the following 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// cipher suites. 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - Null encryption cipher suites. 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - Weak cipher suites: < 80 bits of security strength. 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - FORTEZZA cipher suites (obsolete). 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - IDEA cipher suites (RFC 5469 explains why). 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - Anonymous cipher suites. 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Why don't we use a blacklist? A blacklist that isn't updated for a new 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Mac OS X release is a potential security issue because the new release 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// may have new null encryption or anonymous cipher suites, whereas a 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// whitelist that isn't updated for a new Mac OS X release just means we 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// won't support any new cipher suites in that release. 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool ShouldEnableCipherSuite(SSLCipherSuite suite) { 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (suite) { 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_WITH_3DES_EDE_CBC_MD5: 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_WITH_RC2_CBC_MD5: 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_WITH_3DES_EDE_CBC_SHA: 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: // ** 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: // ** 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_WITH_RC4_128_MD5: 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_RSA_WITH_RC4_128_SHA: 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_RSA_WITH_RC4_128_SHA: 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_RSA_WITH_RC4_128_SHA: 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_RSA_WITH_AES_128_CBC_SHA: 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DH_DSS_WITH_AES_128_CBC_SHA: // ** 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DH_RSA_WITH_AES_128_CBC_SHA: // ** 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_RSA_WITH_AES_256_CBC_SHA: 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DH_DSS_WITH_AES_256_CBC_SHA: // ** 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DH_RSA_WITH_AES_256_CBC_SHA: // ** 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: 405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Returns the server's certificate. The caller must release a reference 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// to the return value when done. Returns NULL on failure. 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottX509Certificate* GetServerCert(SSLContextRef ssl_context) { 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFArrayRef certs; 418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OSStatus status = SSLCopyPeerCertificates(ssl_context, &certs); 419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // SSLCopyPeerCertificates may succeed but return a null |certs| 420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // (if we're using an anonymous cipher suite or if we call it 421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // before the certificate message has arrived and been parsed). 422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (status != noErr || !certs) 423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 424731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::mac::ScopedCFTypeRef<CFArrayRef> scoped_certs(certs); 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GT(CFArrayGetCount(certs), 0); 427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Add each of the intermediate certificates in the server's chain to the 429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // server's X509Certificate object. This makes them available to 430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // X509Certificate::Verify() for chain building. 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<SecCertificateRef> intermediate_ca_certs; 432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFIndex certs_length = CFArrayGetCount(certs); 433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (CFIndex i = 1; i < certs_length; ++i) { 434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SecCertificateRef cert_ref = reinterpret_cast<SecCertificateRef>( 435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const_cast<void*>(CFArrayGetValueAtIndex(certs, i))); 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch intermediate_ca_certs.push_back(cert_ref); 437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SecCertificateRef server_cert = static_cast<SecCertificateRef>( 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const_cast<void*>(CFArrayGetValueAtIndex(certs, 0))); 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return X509Certificate::CreateFromHandle( 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch server_cert, X509Certificate::SOURCE_FROM_NETWORK, intermediate_ca_certs); 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Dynamically look up a pointer to a function exported by a bundle. 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate <typename FNTYPE> 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFNTYPE LookupFunction(CFStringRef bundleName, CFStringRef fnName) { 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CFBundleRef bundle = CFBundleGetBundleWithIdentifier(bundleName); 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!bundle) 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return reinterpret_cast<FNTYPE>( 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CFBundleGetFunctionPointerForName(bundle, fnName)); 453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 4554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochstruct CipherSuiteIsDisabledFunctor { 4564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch explicit CipherSuiteIsDisabledFunctor( 4574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const std::vector<uint16>& disabled_cipher_suites) 4584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch : disabled_cipher_suites_(disabled_cipher_suites) {} 4594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 4604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Returns true if the given |cipher_suite| appears within the set of 4614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // |disabled_cipher_suites|. 4624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch bool operator()(SSLCipherSuite cipher_suite) const { 4634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return binary_search(disabled_cipher_suites_.begin(), 4644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch disabled_cipher_suites_.end(), 4654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch static_cast<uint16>(cipher_suite)); 4664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 4674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 4684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const std::vector<uint16>& disabled_cipher_suites_; 4694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}; 4704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 4714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// Class to determine what cipher suites are available and which cipher 4724a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// suites should be enabled, based on the overall security policy. 473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass EnabledCipherSuites { 474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 4754a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const std::vector<SSLCipherSuite>& ciphers() const { return ciphers_; } 476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 47821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen friend struct base::DefaultLazyInstanceTraits<EnabledCipherSuites>; 4794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch EnabledCipherSuites(); 4804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ~EnabledCipherSuites() {} 4814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::vector<SSLCipherSuite> ciphers_; 483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(EnabledCipherSuites); 485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 48721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstatic base::LazyInstance<EnabledCipherSuites> g_enabled_cipher_suites( 48821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::LINKER_INITIALIZED); 48921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottEnabledCipherSuites::EnabledCipherSuites() { 491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSLContextRef ssl_context; 492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OSStatus status = SSLNewContext(false, &ssl_context); 493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (status != noErr) 494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t num_supported_ciphers; 497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott status = SSLGetNumberSupportedCiphers(ssl_context, &num_supported_ciphers); 498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (status != noErr) { 499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSLDisposeContext(ssl_context); 500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(num_supported_ciphers, 0U); 503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::vector<SSLCipherSuite> supported_ciphers(num_supported_ciphers); 505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott status = SSLGetSupportedCiphers(ssl_context, &supported_ciphers[0], 506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &num_supported_ciphers); 507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSLDisposeContext(ssl_context); 508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (status != noErr) 509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t i = 0; i < num_supported_ciphers; ++i) { 512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ShouldEnableCipherSuite(supported_ciphers[i])) 513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ciphers_.push_back(supported_ciphers[i]); 514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace 518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//----------------------------------------------------------------------------- 520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSSLClientSocketMac::SSLClientSocketMac(ClientSocketHandle* transport_socket, 5224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const HostPortPair& host_and_port, 52321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const SSLConfig& ssl_config, 52421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CertVerifier* cert_verifier) 525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : handshake_io_callback_(this, &SSLClientSocketMac::OnHandshakeIOComplete), 526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transport_read_callback_(this, 527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &SSLClientSocketMac::OnTransportReadComplete), 528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transport_write_callback_(this, 529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &SSLClientSocketMac::OnTransportWriteComplete), 530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transport_(transport_socket), 5314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch host_and_port_(host_and_port), 532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssl_config_(ssl_config), 533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_connect_callback_(NULL), 534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_callback_(NULL), 535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_write_callback_(NULL), 536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_len_(0), 537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_write_buf_len_(0), 538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_handshake_state_(STATE_NONE), 53921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cert_verifier_(cert_verifier), 540731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick renegotiating_(false), 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_cert_requested_(false), 542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssl_context_(NULL), 54372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bytes_read_after_renegotiation_(0), 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_send_error_(OK), 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_(transport_socket->socket()->NetLog()) { 5464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Sort the list of ciphers to disable, since disabling ciphers on Mac 5474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // requires subtracting from a list of enabled ciphers while maintaining 5484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // ordering, as opposed to merely needing to iterate them as with NSS. 5494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch sort(ssl_config_.disabled_cipher_suites.begin(), 5504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ssl_config_.disabled_cipher_suites.end()); 551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSSLClientSocketMac::~SSLClientSocketMac() { 554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Disconnect(); 555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5577b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID 5587b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen// TODO(kristianm): handle the case when wait_for_connect is true 5597b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen// (sync requests) 5607b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif 5617b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsenint SSLClientSocketMac::Connect(CompletionCallback* callback 5627b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID 5637b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen , bool wait_for_connect 5647b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif 5657b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen ) { 566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(transport_.get()); 567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(next_handshake_state_ == STATE_NONE); 568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_connect_callback_); 569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT, NULL); 571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = InitializeSSLContext(); 573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != OK) { 57472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); 575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 578731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_handshake_state_ = STATE_HANDSHAKE; 579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoHandshakeLoop(OK); 580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv == ERR_IO_PENDING) { 581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_connect_callback_ = callback; 582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 58372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); 584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SSLClientSocketMac::Disconnect() { 589731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_handshake_state_ = STATE_NONE; 590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ssl_context_) { 592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSLClose(ssl_context_); 593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSLDisposeContext(ssl_context_); 594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssl_context_ = NULL; 595731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "----- Disposed SSLContext"; 596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Shut down anything that may call us back. 599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott verifier_.reset(); 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch transport_->socket()->Disconnect(); 601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SSLClientSocketMac::IsConnected() const { 604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Ideally, we should also check if we have received the close_notify alert 605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // message from the server, and return false in that case. We're not doing 606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // that, so this function may return a false positive. Since the upper 607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // layer (HttpNetworkTransaction) needs to handle a persistent connection 608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // closed by the server when we send a request anyway, a false positive in 609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // exchange for simpler code is a good trade-off. 610731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return completed_handshake() && transport_->socket()->IsConnected(); 611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SSLClientSocketMac::IsConnectedAndIdle() const { 614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Unlike IsConnected, this method doesn't return a false positive. 615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Strictly speaking, we should check if we have received the close_notify 617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // alert message from the server, and return false in that case. Although 618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the close_notify alert message means EOF in the SSL layer, it is just 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // bytes to the transport layer below, so 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // transport_->socket()->IsConnectedAndIdle() returns the desired false 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // when we receive close_notify. 622731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return completed_handshake() && transport_->socket()->IsConnectedAndIdle(); 623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint SSLClientSocketMac::GetPeerAddress(AddressList* address) const { 626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transport_->socket()->GetPeerAddress(address); 627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 629ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint SSLClientSocketMac::GetLocalAddress(IPEndPoint* address) const { 630ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return transport_->socket()->GetLocalAddress(address); 631ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 632ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 633dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst BoundNetLog& SSLClientSocketMac::NetLog() const { 634dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return net_log_; 635dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 636dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 6373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SSLClientSocketMac::SetSubresourceSpeculation() { 6383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (transport_.get() && transport_->socket()) { 6393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick transport_->socket()->SetSubresourceSpeculation(); 6403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 6413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 6423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 6433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 6443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 6453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SSLClientSocketMac::SetOmniboxSpeculation() { 6463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (transport_.get() && transport_->socket()) { 6473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick transport_->socket()->SetOmniboxSpeculation(); 6483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 6493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 6503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 6513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 6523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 6533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool SSLClientSocketMac::WasEverUsed() const { 6543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (transport_.get() && transport_->socket()) { 6553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return transport_->socket()->WasEverUsed(); 6563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 6573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 6583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 6593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 6603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 661513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool SSLClientSocketMac::UsingTCPFastOpen() const { 662513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (transport_.get() && transport_->socket()) { 663513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return transport_->socket()->UsingTCPFastOpen(); 664513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 665513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NOTREACHED(); 666513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 667513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 668513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SSLClientSocketMac::Read(IOBuffer* buf, int buf_len, 670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback) { 671731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(completed_handshake()); 672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_read_callback_); 673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_read_buf_); 674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_ = buf; 676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_len_ = buf_len; 677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = DoPayloadRead(); 679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv == ERR_IO_PENDING) { 680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_callback_ = callback; 681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_ = NULL; 683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_len_ = 0; 684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SSLClientSocketMac::Write(IOBuffer* buf, int buf_len, 689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback) { 690731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(completed_handshake()); 691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_write_callback_); 692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_write_buf_); 693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_write_buf_ = buf; 695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_write_buf_len_ = buf_len; 696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = DoPayloadWrite(); 698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv == ERR_IO_PENDING) { 699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_write_callback_ = callback; 700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_write_buf_ = NULL; 702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_write_buf_len_ = 0; 703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SSLClientSocketMac::SetReceiveBufferSize(int32 size) { 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transport_->socket()->SetReceiveBufferSize(size); 709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SSLClientSocketMac::SetSendBufferSize(int32 size) { 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transport_->socket()->SetSendBufferSize(size); 713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SSLClientSocketMac::GetSSLInfo(SSLInfo* ssl_info) { 716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssl_info->Reset(); 717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!server_cert_) { 718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED(); 719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssl_info->cert = server_cert_; 723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssl_info->cert_status = server_cert_verify_result_.cert_status; 724ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ssl_info->public_key_hashes = server_cert_verify_result_.public_key_hashes; 725ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ssl_info->is_issued_by_known_root = 726ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen server_cert_verify_result_.is_issued_by_known_root; 727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // security info 729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSLCipherSuite suite; 730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OSStatus status = SSLGetNegotiatedCipher(ssl_context_, &suite); 7313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!status) { 732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssl_info->security_bits = KeySizeOfCipherSuite(suite); 7333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ssl_info->connection_status |= 7343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick (suite & SSL_CONNECTION_CIPHERSUITE_MASK) << 7353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SSL_CONNECTION_CIPHERSUITE_SHIFT; 7363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ssl_config_.ssl3_fallback) 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK; 740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SSLClientSocketMac::GetSSLCertRequestInfo( 743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSLCertRequestInfo* cert_request_info) { 744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // I'm being asked for available client certs (identities). 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // First, get the cert issuer names allowed by the server. 746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<CertPrincipal> valid_issuers; 747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CFArrayRef valid_issuer_names = NULL; 748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (SSLCopyDistinguishedNames(ssl_context_, &valid_issuer_names) == noErr && 749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch valid_issuer_names != NULL) { 750731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Server has " << CFArrayGetCount(valid_issuer_names) 751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << " valid issuer names"; 752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int n = CFArrayGetCount(valid_issuer_names); 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < n; i++) { 754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Parse each name into a CertPrincipal object. 755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CFDataRef issuer = reinterpret_cast<CFDataRef>( 756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CFArrayGetValueAtIndex(valid_issuer_names, i)); 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CertPrincipal p; 758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (p.ParseDistinguishedName(CFDataGetBytePtr(issuer), 759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CFDataGetLength(issuer))) { 760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch valid_issuers.push_back(p); 761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CFRelease(valid_issuer_names); 764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now get the available client certs whose issuers are allowed by the server. 7674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch cert_request_info->host_and_port = host_and_port_.ToString(); 768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cert_request_info->client_certs.clear(); 7694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // TODO(rch): we should consider passing a host-port pair as the first 7704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // argument to X509Certificate::GetSSLClientCertificates. 7714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch X509Certificate::GetSSLClientCertificates(host_and_port_.host(), 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch valid_issuers, 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &cert_request_info->client_certs); 774731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Asking user to choose between " 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << cert_request_info->client_certs.size() << " client certs..."; 776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSSLClientSocket::NextProtoStatus 779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSSLClientSocketMac::GetNextProto(std::string* proto) { 780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott proto->clear(); 781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return kNextProtoUnsupported; 782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SSLClientSocketMac::InitializeSSLContext() { 785731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "----- InitializeSSLContext"; 786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OSStatus status = noErr; 787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott status = SSLNewContext(false, &ssl_context_); 789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (status) 790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NetErrorFromOSStatus(status); 791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott status = SSLSetProtocolVersionEnabled(ssl_context_, 793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kSSLProtocol2, 79421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen false); 795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (status) 796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NetErrorFromOSStatus(status); 797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott status = SSLSetProtocolVersionEnabled(ssl_context_, 799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kSSLProtocol3, 800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssl_config_.ssl3_enabled); 801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (status) 802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NetErrorFromOSStatus(status); 803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott status = SSLSetProtocolVersionEnabled(ssl_context_, 805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kTLSProtocol1, 806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ssl_config_.tls1_enabled); 807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (status) 808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NetErrorFromOSStatus(status); 809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::vector<SSLCipherSuite> enabled_ciphers = 81121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen g_enabled_cipher_suites.Get().ciphers(); 8124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 8134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch CipherSuiteIsDisabledFunctor is_disabled_cipher( 8144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ssl_config_.disabled_cipher_suites); 8154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::vector<SSLCipherSuite>::iterator new_end = 8164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::remove_if(enabled_ciphers.begin(), enabled_ciphers.end(), 8174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch is_disabled_cipher); 8184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (new_end != enabled_ciphers.end()) 8194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch enabled_ciphers.erase(new_end, enabled_ciphers.end()); 8204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 8214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch status = SSLSetEnabledCiphers( 8224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ssl_context_, 8234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch enabled_ciphers.empty() ? NULL : &enabled_ciphers[0], 8244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch enabled_ciphers.size()); 8254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (status) 827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NetErrorFromOSStatus(status); 828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott status = SSLSetIOFuncs(ssl_context_, SSLReadCallback, SSLWriteCallback); 830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (status) 831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NetErrorFromOSStatus(status); 832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott status = SSLSetConnection(ssl_context_, this); 834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (status) 835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NetErrorFromOSStatus(status); 836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Passing the domain name enables the server_name TLS extension (SNI). 838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch status = SSLSetPeerDomainName(ssl_context_, 8394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch host_and_port_.host().data(), 8404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch host_and_port_.host().length()); 841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (status) 842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NetErrorFromOSStatus(status); 843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Disable certificate verification within Secure Transport; we'll 845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // be handling that ourselves. 846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott status = SSLSetEnableCertVerify(ssl_context_, false); 847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (status) 848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NetErrorFromOSStatus(status); 849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ssl_config_.send_client_cert) { 851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch status = SetClientCert(); 852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (status) 853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NetErrorFromOSStatus(status); 8543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return OK; 855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 857731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Concatenate the hostname and peer address to use as the peer ID. To 858731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // resume a session, we must connect to the same server on the same port 859731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // using the same hostname (i.e., localhost and 127.0.0.1 are considered 860731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // different peers, which puts us through certificate validation again 861731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // and catches hostname/certificate name mismatches. 862731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AddressList address; 863731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int rv = transport_->socket()->GetPeerAddress(&address); 864731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (rv != OK) 865731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return rv; 866731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const struct addrinfo* ai = address.head(); 8674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string peer_id(host_and_port_.ToString()); 868731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick peer_id += std::string(reinterpret_cast<char*>(ai->ai_addr), 869731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ai->ai_addrlen); 870731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // SSLSetPeerID() treats peer_id as a binary blob, and makes its 871731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // own copy. 872731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick status = SSLSetPeerID(ssl_context_, peer_id.data(), peer_id.length()); 873731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (status) 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NetErrorFromOSStatus(status); 875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SSLClientSocketMac::DoConnectCallback(int rv) { 880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(rv != ERR_IO_PENDING); 881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(user_connect_callback_); 882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* c = user_connect_callback_; 884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_connect_callback_ = NULL; 885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott c->Run(rv > OK ? OK : rv); 886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SSLClientSocketMac::DoReadCallback(int rv) { 889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(rv != ERR_IO_PENDING); 890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(user_read_callback_); 891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Since Run may result in Read being called, clear user_read_callback_ up 893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // front. 894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* c = user_read_callback_; 895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_callback_ = NULL; 896c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_ = NULL; 897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_read_buf_len_ = 0; 898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott c->Run(rv); 899c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SSLClientSocketMac::DoWriteCallback(int rv) { 902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(rv != ERR_IO_PENDING); 903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(user_write_callback_); 904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Since Run may result in Write being called, clear user_write_callback_ up 906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // front. 907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* c = user_write_callback_; 908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_write_callback_ = NULL; 909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_write_buf_ = NULL; 910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_write_buf_len_ = 0; 911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott c->Run(rv); 912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SSLClientSocketMac::OnHandshakeIOComplete(int result) { 915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = DoHandshakeLoop(result); 916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != ERR_IO_PENDING) { 917731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // If there is no connect callback available to call, we are 918731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // renegotiating (which occurs because we are in the middle of a Read 919731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // when the renegotiation process starts). So we complete the Read 920731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // here. 921731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!user_connect_callback_) { 922731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DoReadCallback(rv); 923731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 924731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 92572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); 926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoConnectCallback(rv); 927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 929c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SSLClientSocketMac::OnTransportReadComplete(int result) { 931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result > 0) { 932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott recv_buffer_.insert(recv_buffer_.end(), 933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_io_buf_->data(), 934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_io_buf_->data() + result); 935c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_io_buf_ = NULL; 937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 938731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!completed_handshake()) { 939731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick OnHandshakeIOComplete(result); 940c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 942731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 943c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (user_read_buf_) { 944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0) { 945c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoReadCallback(result); 946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 947c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 948c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = DoPayloadRead(); 949c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != ERR_IO_PENDING) 950c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoReadCallback(rv); 951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 953c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SSLClientSocketMac::OnTransportWriteComplete(int result) { 955c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_io_buf_ = NULL; 956c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 957c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0) { 958c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pending_send_error_ = result; 959c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 962c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott send_buffer_.erase(send_buffer_.begin(), 963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott send_buffer_.begin() + result); 964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!send_buffer_.empty()) 965c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSLWriteCallback(this, NULL, NULL); 966c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 967731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!completed_handshake()) { 968731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick OnHandshakeIOComplete(result); 969731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 970731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 971731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If paused because too much data is in flight, try writing again and make 973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the promised callback. 974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (user_write_buf_ && send_buffer_.size() < kWriteSizeResumeLimit) { 975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv = DoPayloadWrite(); 976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv != ERR_IO_PENDING) 977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoWriteCallback(rv); 978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SSLClientSocketMac::DoHandshakeLoop(int last_io_result) { 982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(next_handshake_state_ != STATE_NONE); 983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = last_io_result; 984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott State state = next_handshake_state_; 986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_handshake_state_ = STATE_NONE; 987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (state) { 988731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case STATE_HANDSHAKE: 989731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Do the SSL/TLS handshake. 990731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick rv = DoHandshake(); 991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_VERIFY_CERT: 993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Kick off server certificate validation. 994c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoVerifyCert(); 995c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_VERIFY_CERT_COMPLETE: 997731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Check the results of the server certificate validation. 998c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoVerifyCertComplete(rv); 999c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 1000731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case STATE_COMPLETED_RENEGOTIATION: 1001731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // The renegotiation handshake has completed, and the Read() call 1002731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // that was interrupted by the renegotiation needs to be resumed in 1003731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // order to to satisfy the original caller's request. 1004731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick rv = DoCompletedRenegotiation(rv); 1005c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 1006731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case STATE_COMPLETED_HANDSHAKE: 1007731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_handshake_state_ = STATE_COMPLETED_HANDSHAKE; 1008731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // This is the end of our state machine, so return. 1009731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return rv; 1010c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 1011c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = ERR_UNEXPECTED; 1012c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED() << "unexpected state"; 1013c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 1014c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1015c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE); 1016c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 1017c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1018c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1019731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint SSLClientSocketMac::DoHandshake() { 1020731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick client_cert_requested_ = false; 1021731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 102272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OSStatus status; 102372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!renegotiating_) { 102472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen status = SSLHandshake(ssl_context_); 102572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 102672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Renegotiation can only be detected by a call to DoPayloadRead(), 102772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // which means |user_read_buf_| should be valid. 102872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(user_read_buf_); 102972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 103072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // On OS X 10.5.x, SSLSetSessionOption with 103172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // kSSLSessionOptionBreakOnServerAuth is broken for renegotiation, as 103272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // SSLRead() does not internally handle errSSLServerAuthCompleted being 103372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // returned during handshake. In order to support certificate validation 103472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // after a renegotiation, SSLRead() sets |renegotiating_| to be true and 103572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // returns errSSLWouldBlock when it detects an attempt to read the 103672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // ServerHello after responding to a HelloRequest. It would be 103772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // appropriate to call SSLHandshake() at this point to restart the 103872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // handshake state machine, however, on 10.5.x, SSLHandshake() is buggy 103972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // and will always return noErr (indicating handshake completion), 104072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // without doing any actual work. Because of this, the only way to 104172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // advance SecureTransport's internal handshake state machine is to 104272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // continuously call SSLRead() until the handshake is marked complete. 104372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Once the handshake is completed, if it completed successfully, the 104472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // user read callback is invoked with |bytes_read_after_renegotiation_| 104572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // as the callback result. On 10.6.0+, both errSSLServerAuthCompleted 104672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // and SSLHandshake() work as expected, so this strange workaround is 104772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // only necessary while OS X 10.5.x is still supported. 104872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bytes_read_after_renegotiation_ = 0; 104972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen status = SSLRead(ssl_context_, user_read_buf_->data(), 105072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen user_read_buf_len_, &bytes_read_after_renegotiation_); 105172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (bytes_read_after_renegotiation_ > 0) { 105272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // With SecureTransport, as of 10.6.5, if application data is read, 105372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // then the handshake should be completed. This is because 105472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // SecureTransport does not (yet) support exchanging application data 105572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // in the midst of handshakes. This is permitted in the TLS 105672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // specification, as peers may exchange messages using the previous 105772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // cipher spec up until they exchange ChangeCipherSpec messages. 105872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // However, in addition to SecureTransport not supporting this, we do 105972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // not permit callers to enter Read() or Write() when a handshake is 106072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // occurring, in part due to the deception that happens in 106172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // SSLWriteCallback(). Thus we need to make sure the handshake is 106272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // truly completed before processing application data, and if any was 106372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // read before the handshake is completed, it will be dropped and the 106472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // connection aborted. 106572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SSLSessionState session_state = kSSLIdle; 106672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen status = SSLGetSessionState(ssl_context_, &session_state); 106772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (session_state != kSSLConnected) 106872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen status = errSSLProtocol; 106972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 107072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1072731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick SSLClientCertificateState client_cert_state; 1073731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (SSLGetClientCertificateState(ssl_context_, &client_cert_state) != noErr) 1074731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick client_cert_state = kSSLClientCertNone; 1075731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (client_cert_state > kSSLClientCertNone) 1076731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick client_cert_requested_ = true; 1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 10784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch int net_error = ERR_FAILED; 1079731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick switch (status) { 1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case noErr: 1081731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return DidCompleteHandshake(); 1082731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case errSSLWouldBlock: 1083731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_handshake_state_ = STATE_HANDSHAKE; 10844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return ERR_IO_PENDING; 1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case errSSLClosedGraceful: 1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The server unexpectedly closed on us. 10874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch net_error = ERR_SSL_PROTOCOL_ERROR; 10884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch break; 1089731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case errSSLClosedAbort: 1090731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case errSSLPeerHandshakeFail: 1091731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (client_cert_requested_) { 1092731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!ssl_config_.send_client_cert) { 10934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // The server aborted, likely due to requiring a client certificate 10944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // and one wasn't sent. 1095731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Server requested SSL cert during handshake"; 10964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; 10974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else { 10984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // The server aborted, likely due to not liking the client 10994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // certificate that was sent. 11004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch LOG(WARNING) << "Server aborted SSL handshake"; 11014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch net_error = ERR_BAD_SSL_CLIENT_AUTH_CERT; 1102731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 11034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Don't fall through - the error was intentionally remapped. 11044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch break; 11054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 11064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Fall through if a client cert wasn't requested. 11074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch default: 11084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch net_error = NetErrorFromOSStatus(status); 11094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch DCHECK(!IsCertificateError(net_error)); 11104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!ssl_config_.send_client_cert && 11114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch (client_cert_state == kSSLClientCertRejected || 11124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch net_error == ERR_BAD_SSL_CLIENT_AUTH_CERT)) { 11134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // The server unexpectedly sent a peer certificate error alert when no 11144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // certificate had been sent. 11154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch net_error = ERR_SSL_PROTOCOL_ERROR; 1116731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 1117731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 1118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 11204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR, 11214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch new SSLErrorParams(net_error, status)); 1122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net_error; 1123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SSLClientSocketMac::DoVerifyCert() { 1126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_handshake_state_ = STATE_VERIFY_CERT_COMPLETE; 1127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1128731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(server_cert_); 1129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1130731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "DoVerifyCert..."; 1131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int flags = 0; 1132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ssl_config_.rev_checking_enabled) 1133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; 1134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ssl_config_.verify_ev_cert) 1135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott flags |= X509Certificate::VERIFY_EV_CERT; 113621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen verifier_.reset(new SingleRequestCertVerifier(cert_verifier_)); 11374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return verifier_->Verify(server_cert_, host_and_port_.host(), flags, 1138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &server_cert_verify_result_, 1139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &handshake_io_callback_); 1140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SSLClientSocketMac::DoVerifyCertComplete(int result) { 1143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(verifier_.get()); 1144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott verifier_.reset(); 1145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1146731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "...DoVerifyCertComplete (result=" << result << ")"; 1147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (IsCertificateError(result) && ssl_config_.IsAllowedBadCert(server_cert_)) 1148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = OK; 1149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1150731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (result == OK && client_cert_requested_ && 1151731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick !ssl_config_.send_client_cert) { 1152731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Caller hasn't specified a client cert, so let it know the server is 1153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // asking for one, and abort the connection. 1154731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; 1155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Handshake finished! (DoVerifyCertComplete)"; 1157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (renegotiating_) { 1159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DidCompleteRenegotiation(); 1160731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return result; 1161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // The initial handshake has completed. 1164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_handshake_state_ = STATE_COMPLETED_HANDSHAKE; 1165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 1167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint SSLClientSocketMac::SetClientCert() { 1170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ssl_config_.send_client_cert || !ssl_config_.client_cert) 1171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return noErr; 1172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1173731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::mac::ScopedCFTypeRef<CFArrayRef> cert_refs( 1174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ssl_config_.client_cert->CreateClientCertificateChain()); 1175731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "SSLSetCertificate(" << CFArrayGetCount(cert_refs) << " certs)"; 1176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OSStatus result = SSLSetCertificate(ssl_context_, cert_refs); 1177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (result) 1178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "SSLSetCertificate returned OSStatus " << result; 1179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 1180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SSLClientSocketMac::DoPayloadRead() { 1183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t processed = 0; 1184731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick OSStatus status = SSLRead(ssl_context_, user_read_buf_->data(), 1185731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick user_read_buf_len_, &processed); 1186731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (status == errSSLWouldBlock && renegotiating_) { 1187731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CHECK_EQ(static_cast<size_t>(0), processed); 1188731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_handshake_state_ = STATE_HANDSHAKE; 1189731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return DoHandshakeLoop(OK); 1190731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 1191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // There's a subtle difference here in semantics of the "would block" errors. 1192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // In our code, ERR_IO_PENDING means the whole operation is async, while 1193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // errSSLWouldBlock means that the stream isn't ending (and is often returned 1194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // along with partial data). So even though "would block" is returned, if we 1195731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // have data, let's just return it. This is further complicated by the fact 1196731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // that errSSLWouldBlock is also used to short-circuit SSLRead()'s 1197731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // transparent renegotiation, so that we can update our state machine above, 1198731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // which otherwise would get out of sync with the SSLContextRef's internal 1199731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // state machine. 1200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (processed > 0) 1201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return processed; 1202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (status) { 1204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case errSSLClosedNoNotify: 1205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(wtc): Unless we have received the close_notify alert, we need to 1206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // return an error code indicating that the SSL connection ended 1207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // uncleanly, a potential truncation attack. See http://crbug.com/18586. 1208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 1209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 1211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NetErrorFromOSStatus(status); 1212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SSLClientSocketMac::DoPayloadWrite() { 1216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Too much data in flight? 1217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (send_buffer_.size() > kWriteSizePauseLimit) 1218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_IO_PENDING; 1219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t processed = 0; 1221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OSStatus status = SSLWrite(ssl_context_, 1222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_write_buf_->data(), 1223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_write_buf_len_, 1224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &processed); 1225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (processed > 0) 1227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return processed; 1228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NetErrorFromOSStatus(status); 1230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1232731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint SSLClientSocketMac::DoCompletedRenegotiation(int result) { 123372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // The user had a read in progress, which was interrupted by the 123472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // renegotiation. Return the application data that was processed after the 123572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // handshake completed. 1236731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_handshake_state_ = STATE_COMPLETED_HANDSHAKE; 1237731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (result != OK) 1238731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return result; 123972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return bytes_read_after_renegotiation_; 1240731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 1241731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1242731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid SSLClientSocketMac::DidCompleteRenegotiation() { 1243731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(!user_connect_callback_); 1244731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick renegotiating_ = false; 1245731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_handshake_state_ = STATE_COMPLETED_RENEGOTIATION; 1246731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 1247731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1248731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint SSLClientSocketMac::DidCompleteHandshake() { 1249731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(!server_cert_ || renegotiating_); 1250731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Handshake completed, next verify cert"; 1251731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1252513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_refptr<X509Certificate> new_server_cert( 1253513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch GetServerCert(ssl_context_)); 1254731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!new_server_cert) 1255731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return ERR_UNEXPECTED; 1256731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1257731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (renegotiating_ && 1258731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick X509Certificate::IsSameOSCert(server_cert_->os_cert_handle(), 1259731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new_server_cert->os_cert_handle())) { 1260731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // We already verified the server certificate. Either it is good or the 1261731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // user has accepted the certificate error. 1262731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DidCompleteRenegotiation(); 1263731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else { 1264731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick server_cert_ = new_server_cert; 1265731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick next_handshake_state_ = STATE_VERIFY_CERT; 1266731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 1267731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return OK; 1268731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 1269731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 1271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottOSStatus SSLClientSocketMac::SSLReadCallback(SSLConnectionRef connection, 1272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void* data, 1273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t* data_length) { 1274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(data); 1275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(data_length); 1276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSLClientSocketMac* us = 1277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const_cast<SSLClientSocketMac*>( 1278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static_cast<const SSLClientSocketMac*>(connection)); 1279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (us->read_io_buf_) { 1281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We have I/O in flight; promise we'll get back to them and use the 1282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // existing callback to do so. 1283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *data_length = 0; 1284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return errSSLWouldBlock; 1285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1286731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (us->completed_handshake()) { 1287731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // The state machine for SSLRead, located in libsecurity_ssl's 1288731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // sslTransport.c, will attempt to fully complete the renegotiation 1289731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // transparently in SSLRead once it reads the server's HelloRequest 1290731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // message. In order to make sure that the server certificate is 1291731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // (re-)verified and that any other parameters are logged (eg: 1292731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // certificate request state), we try to detect that the 1293731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // SSLClientSocketMac's state machine is out of sync with the 1294731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // SSLContext's. When that happens, we break out by faking 1295731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // errSSLWouldBlock, and set a flag so that DoPayloadRead() knows that 1296731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // it's not actually blocked. DoPayloadRead() will then restart the 1297731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // handshake state machine, and finally resume the original Read() 1298731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // once it successfully completes, similar to the behaviour of 1299731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // SSLClientSocketWin's DoDecryptPayload() and DoLoop() behave. 1300731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick SSLSessionState state; 1301731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick OSStatus status = SSLGetSessionState(us->ssl_context_, &state); 1302731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (status) { 1303731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick *data_length = 0; 1304731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return status; 1305731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 1306731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (state == kSSLHandshake) { 1307731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick *data_length = 0; 1308731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick us->renegotiating_ = true; 1309731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return errSSLWouldBlock; 1310731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 1311731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 1312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t total_read = us->recv_buffer_.size(); 1314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = 1; // any old value to spin the loop below 1316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (rv > 0 && total_read < *data_length) { 1317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott us->read_io_buf_ = new IOBuffer(*data_length - total_read); 1318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = us->transport_->socket()->Read(us->read_io_buf_, 1319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *data_length - total_read, 1320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &us->transport_read_callback_); 1321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv >= 0) { 1323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott us->recv_buffer_.insert(us->recv_buffer_.end(), 1324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott us->read_io_buf_->data(), 1325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott us->read_io_buf_->data() + rv); 1326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott us->read_io_buf_ = NULL; 1327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott total_read += rv; 1328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *data_length = total_read; 1332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (total_read) { 1333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(data, &us->recv_buffer_[0], total_read); 1334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott us->recv_buffer_.clear(); 1335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != ERR_IO_PENDING) 1338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott us->read_io_buf_ = NULL; 1339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv < 0) 1341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OSStatusFromNetError(rv); 1342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (rv == 0) // stream closed 1343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return errSSLClosedGraceful; 1344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 1345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return noErr; 1346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 1349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottOSStatus SSLClientSocketMac::SSLWriteCallback(SSLConnectionRef connection, 1350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const void* data, 1351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t* data_length) { 1352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SSLClientSocketMac* us = 1353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const_cast<SSLClientSocketMac*>( 1354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static_cast<const SSLClientSocketMac*>(connection)); 1355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (us->pending_send_error_ != OK) { 1357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OSStatus status = OSStatusFromNetError(us->pending_send_error_); 1358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott us->pending_send_error_ = OK; 1359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return status; 1360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (data) 1363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott us->send_buffer_.insert(us->send_buffer_.end(), 1364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static_cast<const char*>(data), 1365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static_cast<const char*>(data) + *data_length); 1366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (us->write_io_buf_) { 1368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If we have I/O in flight, just add the data to the end of the buffer and 1369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // return to our caller. The existing callback will trigger the write of the 1370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // new data when it sees that data remains in the buffer after removing the 1371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // sent data. As always, lie to our caller. 1372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return noErr; 1373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv; 1376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 1377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott us->write_io_buf_ = new IOBuffer(us->send_buffer_.size()); 1378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(us->write_io_buf_->data(), &us->send_buffer_[0], 1379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott us->send_buffer_.size()); 1380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = us->transport_->socket()->Write(us->write_io_buf_, 1381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch us->send_buffer_.size(), 1382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &us->transport_write_callback_); 1383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv > 0) { 1384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott us->send_buffer_.erase(us->send_buffer_.begin(), 1385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott us->send_buffer_.begin() + rv); 1386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott us->write_io_buf_ = NULL; 1387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while (rv > 0 && !us->send_buffer_.empty()); 1389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv < 0 && rv != ERR_IO_PENDING) { 1391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott us->write_io_buf_ = NULL; 1392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OSStatusFromNetError(rv); 1393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // always lie to our caller 1396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return noErr; 1397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 1400