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