Home | History | Annotate | Download | only in socket
      1 // Copyright (c) 2008-2009 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/socket/ssl_client_socket_mac.h"
      6 
      7 #include <CoreServices/CoreServices.h>
      8 
      9 #include "base/scoped_cftyperef.h"
     10 #include "base/singleton.h"
     11 #include "base/string_util.h"
     12 #include "net/base/cert_verifier.h"
     13 #include "net/base/io_buffer.h"
     14 #include "net/base/load_log.h"
     15 #include "net/base/net_errors.h"
     16 #include "net/base/ssl_info.h"
     17 
     18 // Welcome to Mac SSL. We've been waiting for you.
     19 //
     20 // The Mac SSL implementation is, like the Windows and NSS implementations, a
     21 // giant state machine. This design constraint is due to the asynchronous nature
     22 // of our underlying transport mechanism. We can call down to read/write on the
     23 // network, but what happens is that either it completes immediately or returns
     24 // saying that we'll get a callback sometime in the future. In that case, we
     25 // have to return to our caller but pick up where we left off when we
     26 // resume. Thus the fun.
     27 //
     28 // On Windows, we use Security Contexts, which are driven by us. We fetch data
     29 // from the network, we call the context to decrypt the data, and so on. On the
     30 // Mac, however, we provide Secure Transport with callbacks to get data from the
     31 // network, and it calls us back to fetch the data from the network for
     32 // it. Therefore, there are different sets of states in our respective state
     33 // machines, fewer on the Mac because Secure Transport keeps a lot of its own
     34 // state. The discussion about what each of the states means lives in comments
     35 // in the DoLoop() function.
     36 //
     37 // Secure Transport is designed for use by either blocking or non-blocking
     38 // network I/O. If, for example, you called SSLRead() to fetch data, Secure
     39 // Transport will, unless it has some cached data, issue a read to your network
     40 // callback read function to fetch it some more encrypted data. It's expecting
     41 // one of two things. If your function is hooked up to a blocking source, then
     42 // it'll block pending receipt of the data from the other end. That's fine, as
     43 // when you return with the data, Secure Transport will do its thing. On the
     44 // other hand, suppose that your socket is non-blocking and tells your function
     45 // that it would block. Then you let Secure Transport know, and it'll tell the
     46 // original caller that it would have blocked and that they need to call it
     47 // "later."
     48 //
     49 // When's "later," though? We have fully-asynchronous networking, so we get a
     50 // callback when our data's ready. But Secure Transport has no way for us to
     51 // tell it that data has arrived, so we must re-execute the call that triggered
     52 // the I/O (we rely on our state machine to do this). When we do so Secure
     53 // Transport will ask once again for the data. Chances are that it'll be the
     54 // same request as the previous time, but that's not actually guaranteed. But as
     55 // long as we buffer what we have and keep track of where we were, it works
     56 // quite well.
     57 //
     58 // Except for network writes. They shoot this plan straight to hell.
     59 //
     60 // Faking a blocking connection with an asynchronous connection (theoretically
     61 // more powerful) simply doesn't work for writing. Suppose that Secure Transport
     62 // requests a write of data to the network. With blocking I/O, we'd just block
     63 // until the write completed, and with non-blocking I/O we'd know how many bytes
     64 // we wrote before we would have blocked. But with the asynchronous I/O, the
     65 // transport underneath us can tell us that it'll let us know sometime "later"
     66 // whether or not things succeeded, and how many bytes were written. What do we
     67 // return to Secure Transport? We can't return a byte count, but we can't return
     68 // "later" as we're not guaranteed to be called in the future with the same data
     69 // to write.
     70 //
     71 // So, like in any good relationship, we're forced to lie. Whenever Secure
     72 // Transport asks for data to be written, we take it all and lie about it always
     73 // being written. We spin in a loop (see SSLWriteCallback() and
     74 // OnTransportWriteComplete()) independent of the main state machine writing
     75 // the data to the network, and get the data out. The main consequence of this
     76 // independence from the state machine is that we require a full-duplex
     77 // transport underneath us since we can't use it to keep our reading and
     78 // writing straight. Fortunately, the NSS implementation also has this issue
     79 // to deal with, so we share the same Libevent-based full-duplex TCP socket.
     80 //
     81 // A side comment on return values might be in order. Those who haven't taken
     82 // the time to read the documentation (ahem, header comments) in our various
     83 // files might be a bit surprised to see result values being treated as both
     84 // lengths and errors. Like Shimmer, they are both. In both the case of
     85 // immediate results as well as results returned in callbacks, a negative return
     86 // value indicates an error, a zero return value indicates end-of-stream (for
     87 // reads), and a positive return value indicates the number of bytes read or
     88 // written. Thus, many functions start off with |if (result < 0) return
     89 // result;|. That gets the error condition out of the way, and from that point
     90 // forward the result can be treated as a length.
     91 
     92 namespace net {
     93 
     94 namespace {
     95 
     96 // Declarations needed to call the 10.5.7 and later SSLSetSessionOption()
     97 // function when building with the 10.5.0 SDK.
     98 typedef enum {
     99   kSSLSessionOptionBreakOnServerAuthFlag
    100 } SSLSetSessionOptionType;
    101 
    102 enum {
    103   errSSLServerAuthCompletedFlag = -9841
    104 };
    105 
    106 // When compiled against the Mac OS X 10.5 SDK, define symbolic constants for
    107 // cipher suites added in Mac OS X 10.6.
    108 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
    109 enum {
    110   // ECC cipher suites from RFC 4492.
    111   TLS_ECDH_ECDSA_WITH_NULL_SHA           = 0xC001,
    112   TLS_ECDH_ECDSA_WITH_RC4_128_SHA        = 0xC002,
    113   TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA   = 0xC003,
    114   TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA    = 0xC004,
    115   TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA    = 0xC005,
    116   TLS_ECDHE_ECDSA_WITH_NULL_SHA          = 0xC006,
    117   TLS_ECDHE_ECDSA_WITH_RC4_128_SHA       = 0xC007,
    118   TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA  = 0xC008,
    119   TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA   = 0xC009,
    120   TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA   = 0xC00A,
    121   TLS_ECDH_RSA_WITH_NULL_SHA             = 0xC00B,
    122   TLS_ECDH_RSA_WITH_RC4_128_SHA          = 0xC00C,
    123   TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA     = 0xC00D,
    124   TLS_ECDH_RSA_WITH_AES_128_CBC_SHA      = 0xC00E,
    125   TLS_ECDH_RSA_WITH_AES_256_CBC_SHA      = 0xC00F,
    126   TLS_ECDHE_RSA_WITH_NULL_SHA            = 0xC010,
    127   TLS_ECDHE_RSA_WITH_RC4_128_SHA         = 0xC011,
    128   TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA    = 0xC012,
    129   TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA     = 0xC013,
    130   TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA     = 0xC014,
    131   TLS_ECDH_anon_WITH_NULL_SHA            = 0xC015,
    132   TLS_ECDH_anon_WITH_RC4_128_SHA         = 0xC016,
    133   TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA    = 0xC017,
    134   TLS_ECDH_anon_WITH_AES_128_CBC_SHA     = 0xC018,
    135   TLS_ECDH_anon_WITH_AES_256_CBC_SHA     = 0xC019,
    136 };
    137 #endif
    138 
    139 typedef OSStatus (*SSLSetSessionOptionFuncPtr)(SSLContextRef,
    140                                                SSLSetSessionOptionType,
    141                                                Boolean);
    142 // For an explanation of the Mac OS X error codes, please refer to:
    143 // http://developer.apple.com/mac/library/documentation/Security/Reference/secureTransportRef/Reference/reference.html
    144 int NetErrorFromOSStatus(OSStatus status) {
    145   switch (status) {
    146     case errSSLWouldBlock:
    147       return ERR_IO_PENDING;
    148     case errSSLBadCipherSuite:
    149     case errSSLBadConfiguration:
    150       return ERR_INVALID_ARGUMENT;
    151     case errSSLClosedNoNotify:
    152       return ERR_CONNECTION_RESET;
    153     case errSSLClosedAbort:
    154       return ERR_CONNECTION_ABORTED;
    155     case errSSLInternal:
    156       return ERR_UNEXPECTED;
    157     case errSSLCrypto:
    158     case errSSLFatalAlert:
    159     case errSSLIllegalParam:  // Received an illegal_parameter alert.
    160     case errSSLPeerUnexpectedMsg:  // Received an unexpected_message alert.
    161     case errSSLProtocol:
    162     case errSSLPeerHandshakeFail:  // Received a handshake_failure alert.
    163     case errSSLConnectionRefused:
    164       return ERR_SSL_PROTOCOL_ERROR;
    165     case errSSLHostNameMismatch:
    166       return ERR_CERT_COMMON_NAME_INVALID;
    167     case errSSLCertExpired:
    168     case errSSLCertNotYetValid:
    169       return ERR_CERT_DATE_INVALID;
    170     case errSSLNoRootCert:
    171     case errSSLUnknownRootCert:
    172       return ERR_CERT_AUTHORITY_INVALID;
    173     case errSSLXCertChainInvalid:
    174     case errSSLBadCert:
    175       return ERR_CERT_INVALID;
    176     case errSSLPeerCertRevoked:
    177       return ERR_CERT_REVOKED;
    178 
    179     case errSSLClosedGraceful:
    180     case noErr:
    181       return OK;
    182 
    183     case errSSLBadRecordMac:
    184     case errSSLBufferOverflow:
    185     case errSSLDecryptionFail:
    186     case errSSLModuleAttach:
    187     case errSSLNegotiation:
    188     case errSSLRecordOverflow:
    189     case errSSLSessionNotFound:
    190     default:
    191       LOG(WARNING) << "Unknown error " << status <<
    192           " mapped to net::ERR_FAILED";
    193       return ERR_FAILED;
    194   }
    195 }
    196 
    197 OSStatus OSStatusFromNetError(int net_error) {
    198   switch (net_error) {
    199     case ERR_IO_PENDING:
    200       return errSSLWouldBlock;
    201     case ERR_INTERNET_DISCONNECTED:
    202     case ERR_TIMED_OUT:
    203     case ERR_CONNECTION_ABORTED:
    204     case ERR_CONNECTION_RESET:
    205     case ERR_CONNECTION_REFUSED:
    206     case ERR_ADDRESS_UNREACHABLE:
    207     case ERR_ADDRESS_INVALID:
    208       return errSSLClosedAbort;
    209     case ERR_UNEXPECTED:
    210       return errSSLInternal;
    211     case ERR_INVALID_ARGUMENT:
    212       return paramErr;
    213     case OK:
    214       return noErr;
    215     default:
    216       LOG(WARNING) << "Unknown error " << net_error <<
    217           " mapped to paramErr";
    218       return paramErr;
    219   }
    220 }
    221 
    222 // Converts from a cipher suite to its key size. If the suite is marked with a
    223 // **, it's not actually implemented in Secure Transport and won't be returned
    224 // (but we'll code for it anyway).  The reference here is
    225 // http://www.opensource.apple.com/darwinsource/10.5.5/libsecurity_ssl-32463/lib/cipherSpecs.c
    226 // Seriously, though, there has to be an API for this, but I can't find one.
    227 // Anybody?
    228 int KeySizeOfCipherSuite(SSLCipherSuite suite) {
    229   switch (suite) {
    230     // SSL 2 only
    231 
    232     case SSL_RSA_WITH_DES_CBC_MD5:
    233       return 56;
    234     case SSL_RSA_WITH_3DES_EDE_CBC_MD5:
    235       return 112;
    236     case SSL_RSA_WITH_RC2_CBC_MD5:
    237     case SSL_RSA_WITH_IDEA_CBC_MD5:              // **
    238       return 128;
    239     case SSL_NO_SUCH_CIPHERSUITE:                // **
    240       return 0;
    241 
    242     // SSL 2, 3, TLS
    243 
    244     case SSL_NULL_WITH_NULL_NULL:
    245     case SSL_RSA_WITH_NULL_MD5:
    246     case SSL_RSA_WITH_NULL_SHA:                  // **
    247     case SSL_FORTEZZA_DMS_WITH_NULL_SHA:         // **
    248     case TLS_ECDH_ECDSA_WITH_NULL_SHA:
    249     case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
    250     case TLS_ECDH_RSA_WITH_NULL_SHA:
    251     case TLS_ECDHE_RSA_WITH_NULL_SHA:
    252     case TLS_ECDH_anon_WITH_NULL_SHA:
    253       return 0;
    254     case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
    255     case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
    256     case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
    257     case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:   // **
    258     case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:   // **
    259     case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
    260     case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
    261     case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
    262     case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
    263       return 40;
    264     case SSL_RSA_WITH_DES_CBC_SHA:
    265     case SSL_DH_DSS_WITH_DES_CBC_SHA:            // **
    266     case SSL_DH_RSA_WITH_DES_CBC_SHA:            // **
    267     case SSL_DHE_DSS_WITH_DES_CBC_SHA:
    268     case SSL_DHE_RSA_WITH_DES_CBC_SHA:
    269     case SSL_DH_anon_WITH_DES_CBC_SHA:
    270       return 56;
    271     case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: // **
    272       return 80;
    273     case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
    274     case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA:       // **
    275     case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA:       // **
    276     case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
    277     case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
    278     case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
    279     case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
    280     case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
    281     case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
    282     case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
    283     case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:
    284       return 112;
    285     case SSL_RSA_WITH_RC4_128_MD5:
    286     case SSL_RSA_WITH_RC4_128_SHA:
    287     case SSL_RSA_WITH_IDEA_CBC_SHA:              // **
    288     case SSL_DH_anon_WITH_RC4_128_MD5:
    289     case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
    290     case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
    291     case TLS_ECDH_RSA_WITH_RC4_128_SHA:
    292     case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
    293     case TLS_ECDH_anon_WITH_RC4_128_SHA:
    294       return 128;
    295 
    296     // TLS AES options (see RFC 3268 and RFC 4492)
    297 
    298     case TLS_RSA_WITH_AES_128_CBC_SHA:
    299     case TLS_DH_DSS_WITH_AES_128_CBC_SHA:        // **
    300     case TLS_DH_RSA_WITH_AES_128_CBC_SHA:        // **
    301     case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
    302     case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
    303     case TLS_DH_anon_WITH_AES_128_CBC_SHA:
    304     case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
    305     case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
    306     case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
    307     case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
    308     case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
    309       return 128;
    310     case TLS_RSA_WITH_AES_256_CBC_SHA:
    311     case TLS_DH_DSS_WITH_AES_256_CBC_SHA:        // **
    312     case TLS_DH_RSA_WITH_AES_256_CBC_SHA:        // **
    313     case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
    314     case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
    315     case TLS_DH_anon_WITH_AES_256_CBC_SHA:
    316     case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
    317     case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
    318     case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
    319     case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
    320     case TLS_ECDH_anon_WITH_AES_256_CBC_SHA:
    321       return 256;
    322 
    323     default:
    324       return -1;
    325   }
    326 }
    327 
    328 // Whitelist the cipher suites we want to enable.  We disable the following
    329 // cipher suites.
    330 // - Null encryption cipher suites.
    331 // - Weak cipher suites: < 80 bits of security strength.
    332 // - FORTEZZA cipher suites (obsolete).
    333 // - IDEA cipher suites (RFC 5469 explains why).
    334 // - Anonymous cipher suites.
    335 //
    336 // Why don't we use a blacklist?  A blacklist that isn't updated for a new
    337 // Mac OS X release is a potential security issue because the new release
    338 // may have new null encryption or anonymous cipher suites, whereas a
    339 // whitelist that isn't updated for a new Mac OS X release just means we
    340 // won't support any new cipher suites in that release.
    341 bool ShouldEnableCipherSuite(SSLCipherSuite suite) {
    342   switch (suite) {
    343     case SSL_RSA_WITH_3DES_EDE_CBC_MD5:
    344     case SSL_RSA_WITH_RC2_CBC_MD5:
    345 
    346     case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
    347     case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA:       // **
    348     case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA:       // **
    349     case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
    350     case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
    351     case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
    352     case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
    353     case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
    354     case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
    355 
    356     case SSL_RSA_WITH_RC4_128_MD5:
    357     case SSL_RSA_WITH_RC4_128_SHA:
    358     case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
    359     case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
    360     case TLS_ECDH_RSA_WITH_RC4_128_SHA:
    361     case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
    362 
    363     case TLS_RSA_WITH_AES_128_CBC_SHA:
    364     case TLS_DH_DSS_WITH_AES_128_CBC_SHA:        // **
    365     case TLS_DH_RSA_WITH_AES_128_CBC_SHA:        // **
    366     case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
    367     case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
    368     case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
    369     case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
    370     case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
    371     case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
    372 
    373     case TLS_RSA_WITH_AES_256_CBC_SHA:
    374     case TLS_DH_DSS_WITH_AES_256_CBC_SHA:        // **
    375     case TLS_DH_RSA_WITH_AES_256_CBC_SHA:        // **
    376     case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
    377     case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
    378     case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
    379     case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
    380     case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
    381     case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
    382       return true;
    383 
    384     default:
    385       return false;
    386   }
    387 }
    388 
    389 // Returns the server's certificate.  The caller must release a reference
    390 // to the return value when done.  Returns NULL on failure.
    391 X509Certificate* GetServerCert(SSLContextRef ssl_context) {
    392   CFArrayRef certs;
    393   OSStatus status = SSLCopyPeerCertificates(ssl_context, &certs);
    394   // SSLCopyPeerCertificates may succeed but return a null |certs|
    395   // (if we're using an anonymous cipher suite or if we call it
    396   // before the certificate message has arrived and been parsed).
    397   if (status != noErr || !certs)
    398     return NULL;
    399   scoped_cftyperef<CFArrayRef> scoped_certs(certs);
    400 
    401   DCHECK_GT(CFArrayGetCount(certs), 0);
    402 
    403   SecCertificateRef server_cert = static_cast<SecCertificateRef>(
    404       const_cast<void*>(CFArrayGetValueAtIndex(certs, 0)));
    405   CFRetain(server_cert);
    406   X509Certificate *x509_cert = X509Certificate::CreateFromHandle(
    407       server_cert, X509Certificate::SOURCE_FROM_NETWORK);
    408   if (!x509_cert)
    409     return NULL;
    410 
    411   // Add each of the intermediate certificates in the server's chain to the
    412   // server's X509Certificate object. This makes them available to
    413   // X509Certificate::Verify() for chain building.
    414   // TODO(wtc): Since X509Certificate::CreateFromHandle may return a cached
    415   // X509Certificate object, we may be adding intermediate CA certificates to
    416   // it repeatedly!
    417   CFIndex certs_length = CFArrayGetCount(certs);
    418   for (CFIndex i = 1; i < certs_length; ++i) {
    419     SecCertificateRef cert_ref = reinterpret_cast<SecCertificateRef>(
    420         const_cast<void*>(CFArrayGetValueAtIndex(certs, i)));
    421     CFRetain(cert_ref);
    422     x509_cert->AddIntermediateCertificate(cert_ref);
    423   }
    424 
    425   return x509_cert;
    426 }
    427 
    428 // A class that wraps an array of enabled cipher suites that can be passed to
    429 // SSLSetEnabledCiphers.
    430 //
    431 // Used as a singleton.
    432 class EnabledCipherSuites {
    433  public:
    434   EnabledCipherSuites();
    435 
    436   const SSLCipherSuite* ciphers() const {
    437     return ciphers_.empty() ? NULL : &ciphers_[0];
    438   }
    439   size_t num_ciphers() const { return ciphers_.size(); }
    440 
    441  private:
    442   std::vector<SSLCipherSuite> ciphers_;
    443 
    444   DISALLOW_COPY_AND_ASSIGN(EnabledCipherSuites);
    445 };
    446 
    447 EnabledCipherSuites::EnabledCipherSuites() {
    448   SSLContextRef ssl_context;
    449   OSStatus status = SSLNewContext(false, &ssl_context);
    450   if (status != noErr)
    451     return;
    452 
    453   size_t num_supported_ciphers;
    454   status = SSLGetNumberSupportedCiphers(ssl_context, &num_supported_ciphers);
    455   if (status != noErr) {
    456     SSLDisposeContext(ssl_context);
    457     return;
    458   }
    459   DCHECK_NE(num_supported_ciphers, 0U);
    460 
    461   std::vector<SSLCipherSuite> supported_ciphers(num_supported_ciphers);
    462   status = SSLGetSupportedCiphers(ssl_context, &supported_ciphers[0],
    463                                   &num_supported_ciphers);
    464   SSLDisposeContext(ssl_context);
    465   if (status != noErr)
    466     return;
    467 
    468   for (size_t i = 0; i < num_supported_ciphers; ++i) {
    469     if (ShouldEnableCipherSuite(supported_ciphers[i]))
    470       ciphers_.push_back(supported_ciphers[i]);
    471   }
    472 }
    473 
    474 }  // namespace
    475 
    476 //-----------------------------------------------------------------------------
    477 
    478 SSLClientSocketMac::SSLClientSocketMac(ClientSocket* transport_socket,
    479                                        const std::string& hostname,
    480                                        const SSLConfig& ssl_config)
    481     : handshake_io_callback_(this, &SSLClientSocketMac::OnHandshakeIOComplete),
    482       transport_read_callback_(this,
    483                                &SSLClientSocketMac::OnTransportReadComplete),
    484       transport_write_callback_(this,
    485                                 &SSLClientSocketMac::OnTransportWriteComplete),
    486       transport_(transport_socket),
    487       hostname_(hostname),
    488       ssl_config_(ssl_config),
    489       user_connect_callback_(NULL),
    490       user_read_callback_(NULL),
    491       user_write_callback_(NULL),
    492       user_read_buf_len_(0),
    493       user_write_buf_len_(0),
    494       next_handshake_state_(STATE_NONE),
    495       completed_handshake_(false),
    496       handshake_interrupted_(false),
    497       ssl_context_(NULL),
    498       pending_send_error_(OK) {
    499 }
    500 
    501 SSLClientSocketMac::~SSLClientSocketMac() {
    502   Disconnect();
    503 }
    504 
    505 int SSLClientSocketMac::Connect(CompletionCallback* callback,
    506                                 LoadLog* load_log) {
    507   DCHECK(transport_.get());
    508   DCHECK(next_handshake_state_ == STATE_NONE);
    509   DCHECK(!user_connect_callback_);
    510 
    511   LoadLog::BeginEvent(load_log, LoadLog::TYPE_SSL_CONNECT);
    512 
    513   int rv = InitializeSSLContext();
    514   if (rv != OK) {
    515     LoadLog::EndEvent(load_log, LoadLog::TYPE_SSL_CONNECT);
    516     return rv;
    517   }
    518 
    519   next_handshake_state_ = STATE_HANDSHAKE_START;
    520   rv = DoHandshakeLoop(OK);
    521   if (rv == ERR_IO_PENDING) {
    522     load_log_ = load_log;
    523     user_connect_callback_ = callback;
    524   } else {
    525     LoadLog::EndEvent(load_log, LoadLog::TYPE_SSL_CONNECT);
    526   }
    527   return rv;
    528 }
    529 
    530 void SSLClientSocketMac::Disconnect() {
    531   completed_handshake_ = false;
    532 
    533   if (ssl_context_) {
    534     SSLClose(ssl_context_);
    535     SSLDisposeContext(ssl_context_);
    536     ssl_context_ = NULL;
    537   }
    538 
    539   // Shut down anything that may call us back.
    540   verifier_.reset();
    541   transport_->Disconnect();
    542 }
    543 
    544 bool SSLClientSocketMac::IsConnected() const {
    545   // Ideally, we should also check if we have received the close_notify alert
    546   // message from the server, and return false in that case.  We're not doing
    547   // that, so this function may return a false positive.  Since the upper
    548   // layer (HttpNetworkTransaction) needs to handle a persistent connection
    549   // closed by the server when we send a request anyway, a false positive in
    550   // exchange for simpler code is a good trade-off.
    551   return completed_handshake_ && transport_->IsConnected();
    552 }
    553 
    554 bool SSLClientSocketMac::IsConnectedAndIdle() const {
    555   // Unlike IsConnected, this method doesn't return a false positive.
    556   //
    557   // Strictly speaking, we should check if we have received the close_notify
    558   // alert message from the server, and return false in that case.  Although
    559   // the close_notify alert message means EOF in the SSL layer, it is just
    560   // bytes to the transport layer below, so transport_->IsConnectedAndIdle()
    561   // returns the desired false when we receive close_notify.
    562   return completed_handshake_ && transport_->IsConnectedAndIdle();
    563 }
    564 
    565 int SSLClientSocketMac::GetPeerName(struct sockaddr* name, socklen_t* namelen) {
    566   return transport_->GetPeerName(name, namelen);
    567 }
    568 
    569 int SSLClientSocketMac::Read(IOBuffer* buf, int buf_len,
    570                              CompletionCallback* callback) {
    571   DCHECK(completed_handshake_);
    572   DCHECK(!user_read_callback_);
    573   DCHECK(!user_read_buf_);
    574 
    575   user_read_buf_ = buf;
    576   user_read_buf_len_ = buf_len;
    577 
    578   int rv = DoPayloadRead();
    579   if (rv == ERR_IO_PENDING) {
    580     user_read_callback_ = callback;
    581   } else {
    582     user_read_buf_ = NULL;
    583     user_read_buf_len_ = 0;
    584   }
    585   return rv;
    586 }
    587 
    588 int SSLClientSocketMac::Write(IOBuffer* buf, int buf_len,
    589                               CompletionCallback* callback) {
    590   DCHECK(completed_handshake_);
    591   DCHECK(!user_write_callback_);
    592   DCHECK(!user_write_buf_);
    593 
    594   user_write_buf_ = buf;
    595   user_write_buf_len_ = buf_len;
    596 
    597   int rv = DoPayloadWrite();
    598   if (rv == ERR_IO_PENDING) {
    599     user_write_callback_ = callback;
    600   } else {
    601     user_write_buf_ = NULL;
    602     user_write_buf_len_ = 0;
    603   }
    604   return rv;
    605 }
    606 
    607 bool SSLClientSocketMac::SetReceiveBufferSize(int32 size) {
    608   return transport_->SetReceiveBufferSize(size);
    609 }
    610 
    611 bool SSLClientSocketMac::SetSendBufferSize(int32 size) {
    612   return transport_->SetSendBufferSize(size);
    613 }
    614 
    615 void SSLClientSocketMac::GetSSLInfo(SSLInfo* ssl_info) {
    616   ssl_info->Reset();
    617   if (!server_cert_) {
    618     NOTREACHED();
    619     return;
    620   }
    621 
    622   // set cert
    623   ssl_info->cert = server_cert_;
    624 
    625   // update status
    626   ssl_info->cert_status = server_cert_verify_result_.cert_status;
    627 
    628   // security info
    629   SSLCipherSuite suite;
    630   OSStatus status = SSLGetNegotiatedCipher(ssl_context_, &suite);
    631   if (!status)
    632     ssl_info->security_bits = KeySizeOfCipherSuite(suite);
    633 }
    634 
    635 void SSLClientSocketMac::GetSSLCertRequestInfo(
    636     SSLCertRequestInfo* cert_request_info) {
    637   // TODO(wtc): implement this.
    638 }
    639 
    640 SSLClientSocket::NextProtoStatus
    641 SSLClientSocketMac::GetNextProto(std::string* proto) {
    642   proto->clear();
    643   return kNextProtoUnsupported;
    644 }
    645 
    646 int SSLClientSocketMac::InitializeSSLContext() {
    647   OSStatus status = noErr;
    648 
    649   status = SSLNewContext(false, &ssl_context_);
    650   if (status)
    651     return NetErrorFromOSStatus(status);
    652 
    653   status = SSLSetProtocolVersionEnabled(ssl_context_,
    654                                         kSSLProtocol2,
    655                                         ssl_config_.ssl2_enabled);
    656   if (status)
    657     return NetErrorFromOSStatus(status);
    658 
    659   status = SSLSetProtocolVersionEnabled(ssl_context_,
    660                                         kSSLProtocol3,
    661                                         ssl_config_.ssl3_enabled);
    662   if (status)
    663     return NetErrorFromOSStatus(status);
    664 
    665   status = SSLSetProtocolVersionEnabled(ssl_context_,
    666                                         kTLSProtocol1,
    667                                         ssl_config_.tls1_enabled);
    668   if (status)
    669     return NetErrorFromOSStatus(status);
    670 
    671   const EnabledCipherSuites* enabled_ciphers =
    672       Singleton<EnabledCipherSuites>::get();
    673   status = SSLSetEnabledCiphers(ssl_context_, enabled_ciphers->ciphers(),
    674                                 enabled_ciphers->num_ciphers());
    675   if (status)
    676     return NetErrorFromOSStatus(status);
    677 
    678   status = SSLSetIOFuncs(ssl_context_, SSLReadCallback, SSLWriteCallback);
    679   if (status)
    680     return NetErrorFromOSStatus(status);
    681 
    682   status = SSLSetConnection(ssl_context_, this);
    683   if (status)
    684     return NetErrorFromOSStatus(status);
    685 
    686   // Disable certificate verification within Secure Transport; we'll
    687   // be handling that ourselves.
    688   status = SSLSetEnableCertVerify(ssl_context_, false);
    689   if (status)
    690     return NetErrorFromOSStatus(status);
    691 
    692   // SSLSetSessionOption() was introduced in Mac OS X 10.5.7. It allows us
    693   // to perform certificate validation during the handshake, which is
    694   // required in order to properly enable session resumption.
    695   //
    696   // With the kSSLSessionOptionBreakOnServerAuth option set, SSLHandshake()
    697   // will return errSSLServerAuthCompleted after receiving the server's
    698   // Certificate during the handshake. That gives us an opportunity to verify
    699   // the server certificate and then re-enter that handshake (assuming the
    700   // certificate successfully validated).
    701   //
    702   // If SSLSetSessionOption() is not present, we do not enable session
    703   // resumption, because in that case we are verifying the server's certificate
    704   // after the handshake completes (but before any application data is
    705   // exchanged). If we were to enable session resumption in this situation,
    706   // the session would be cached before we verified the certificate, leaving
    707   // the potential for a session in which the certificate failed to validate
    708   // to still be able to be resumed.
    709   CFBundleRef bundle =
    710       CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security"));
    711   if (bundle) {
    712     SSLSetSessionOptionFuncPtr ssl_set_session_options =
    713         reinterpret_cast<SSLSetSessionOptionFuncPtr>(
    714             CFBundleGetFunctionPointerForName(bundle,
    715                 CFSTR("SSLSetSessionOption")));
    716     if (ssl_set_session_options) {
    717       status = ssl_set_session_options(ssl_context_,
    718                                        kSSLSessionOptionBreakOnServerAuthFlag,
    719                                        true);
    720       if (status)
    721         return NetErrorFromOSStatus(status);
    722 
    723       // Concatenate the hostname and peer address to use as the peer ID. To
    724       // resume a session, we must connect to the same server on the same port
    725       // using the same hostname (i.e., localhost and 127.0.0.1 are considered
    726       // different peers, which puts us through certificate validation again
    727       // and catches hostname/certificate name mismatches.
    728       struct sockaddr_storage addr;
    729       socklen_t addr_length = sizeof(struct sockaddr_storage);
    730       memset(&addr, 0, sizeof(addr));
    731       if (!transport_->GetPeerName(reinterpret_cast<struct sockaddr*>(&addr),
    732                                    &addr_length)) {
    733         // Assemble the socket hostname and address into a single buffer.
    734         std::vector<char> peer_id(hostname_.begin(), hostname_.end());
    735         peer_id.insert(peer_id.end(), reinterpret_cast<char*>(&addr),
    736                        reinterpret_cast<char*>(&addr) + addr_length);
    737 
    738         // SSLSetPeerID() treats peer_id as a binary blob, and makes its
    739         // own copy.
    740         status = SSLSetPeerID(ssl_context_, &peer_id[0], peer_id.size());
    741         if (status)
    742           return NetErrorFromOSStatus(status);
    743       }
    744     }
    745   }
    746 
    747   return OK;
    748 }
    749 
    750 void SSLClientSocketMac::DoConnectCallback(int rv) {
    751   DCHECK(rv != ERR_IO_PENDING);
    752   DCHECK(user_connect_callback_);
    753   DCHECK(next_handshake_state_ == STATE_NONE);
    754 
    755   CompletionCallback* c = user_connect_callback_;
    756   user_connect_callback_ = NULL;
    757   c->Run(rv > OK ? OK : rv);
    758 }
    759 
    760 void SSLClientSocketMac::DoReadCallback(int rv) {
    761   DCHECK(rv != ERR_IO_PENDING);
    762   DCHECK(user_read_callback_);
    763 
    764   // Since Run may result in Read being called, clear user_read_callback_ up
    765   // front.
    766   CompletionCallback* c = user_read_callback_;
    767   user_read_callback_ = NULL;
    768   user_read_buf_ = NULL;
    769   user_read_buf_len_ = 0;
    770   c->Run(rv);
    771 }
    772 
    773 void SSLClientSocketMac::DoWriteCallback(int rv) {
    774   DCHECK(rv != ERR_IO_PENDING);
    775   DCHECK(user_write_callback_);
    776 
    777   // Since Run may result in Write being called, clear user_write_callback_ up
    778   // front.
    779   CompletionCallback* c = user_write_callback_;
    780   user_write_callback_ = NULL;
    781   user_write_buf_ = NULL;
    782   user_write_buf_len_ = 0;
    783   c->Run(rv);
    784 }
    785 
    786 void SSLClientSocketMac::OnHandshakeIOComplete(int result) {
    787   DCHECK(next_handshake_state_ != STATE_NONE);
    788   int rv = DoHandshakeLoop(result);
    789   if (rv != ERR_IO_PENDING) {
    790     LoadLog::EndEvent(load_log_, LoadLog::TYPE_SSL_CONNECT);
    791     load_log_ = NULL;
    792     DoConnectCallback(rv);
    793   }
    794 }
    795 
    796 void SSLClientSocketMac::OnTransportReadComplete(int result) {
    797   if (result > 0) {
    798     recv_buffer_.insert(recv_buffer_.end(),
    799                         read_io_buf_->data(),
    800                         read_io_buf_->data() + result);
    801   }
    802   read_io_buf_ = NULL;
    803 
    804   if (next_handshake_state_ != STATE_NONE) {
    805     int rv = DoHandshakeLoop(result);
    806     if (rv != ERR_IO_PENDING) {
    807       LoadLog::EndEvent(load_log_, LoadLog::TYPE_SSL_CONNECT);
    808       load_log_ = NULL;
    809       DoConnectCallback(rv);
    810     }
    811     return;
    812   }
    813   if (user_read_buf_) {
    814     if (result < 0) {
    815       DoReadCallback(result);
    816       return;
    817     }
    818     int rv = DoPayloadRead();
    819     if (rv != ERR_IO_PENDING)
    820       DoReadCallback(rv);
    821   }
    822 }
    823 
    824 void SSLClientSocketMac::OnTransportWriteComplete(int result) {
    825   write_io_buf_ = NULL;
    826 
    827   if (result < 0) {
    828     pending_send_error_ = result;
    829     return;
    830   }
    831 
    832   send_buffer_.erase(send_buffer_.begin(),
    833                      send_buffer_.begin() + result);
    834   if (!send_buffer_.empty())
    835     SSLWriteCallback(this, NULL, NULL);
    836 
    837   // Since SSLWriteCallback() lies to return noErr even if transport_->Write()
    838   // returns ERR_IO_PENDING, we don't need to call any callbacks here.
    839 }
    840 
    841 // This is the main loop driving the state machine. Most calls coming from the
    842 // outside just set up a few variables and jump into here.
    843 int SSLClientSocketMac::DoHandshakeLoop(int last_io_result) {
    844   DCHECK(next_handshake_state_ != STATE_NONE);
    845   int rv = last_io_result;
    846   do {
    847     State state = next_handshake_state_;
    848     next_handshake_state_ = STATE_NONE;
    849     switch (state) {
    850       case STATE_HANDSHAKE_START:
    851         // Do the SSL/TLS handshake, up to the server certificate message.
    852         rv = DoHandshakeStart();
    853         break;
    854       case STATE_VERIFY_CERT:
    855         // Kick off server certificate validation.
    856         rv = DoVerifyCert();
    857         break;
    858       case STATE_VERIFY_CERT_COMPLETE:
    859         // Check the results of the  server certificate validation.
    860         rv = DoVerifyCertComplete(rv);
    861         break;
    862       case STATE_HANDSHAKE_FINISH:
    863         // Do the SSL/TLS handshake, after the server certificate message.
    864         rv = DoHandshakeFinish();
    865         break;
    866       default:
    867         rv = ERR_UNEXPECTED;
    868         NOTREACHED() << "unexpected state";
    869         break;
    870     }
    871   } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
    872   return rv;
    873 }
    874 
    875 int SSLClientSocketMac::DoHandshakeStart() {
    876   OSStatus status = SSLHandshake(ssl_context_);
    877   if (status == errSSLWouldBlock)
    878     next_handshake_state_ = STATE_HANDSHAKE_START;
    879 
    880   if (status == noErr || status == errSSLServerAuthCompletedFlag) {
    881     // TODO(hawk): we verify the certificate chain even on resumed sessions
    882     // so that we have the certificate status (valid, expired but overridden
    883     // by the user, EV, etc.) available. Eliminate this step once we have
    884     // a certificate validation result cache.
    885     next_handshake_state_ = STATE_VERIFY_CERT;
    886     if (status == errSSLServerAuthCompletedFlag) {
    887       // Override errSSLServerAuthCompletedFlag as it's not actually an error,
    888       // but rather an indication that we're only half way through the
    889       // handshake.
    890       handshake_interrupted_ = true;
    891       status = noErr;
    892     }
    893   }
    894 
    895   if (status == errSSLClosedGraceful) {
    896     // The server unexpectedly closed on us.
    897     return ERR_SSL_PROTOCOL_ERROR;
    898   }
    899 
    900   int net_error = NetErrorFromOSStatus(status);
    901   if (status == noErr || IsCertificateError(net_error)) {
    902     server_cert_ = GetServerCert(ssl_context_);
    903     if (!server_cert_)
    904       return ERR_UNEXPECTED;
    905   }
    906   return net_error;
    907 }
    908 
    909 int SSLClientSocketMac::DoVerifyCert() {
    910   next_handshake_state_ = STATE_VERIFY_CERT_COMPLETE;
    911 
    912   if (!server_cert_)
    913     return ERR_UNEXPECTED;
    914 
    915   int flags = 0;
    916   if (ssl_config_.rev_checking_enabled)
    917     flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
    918   if (ssl_config_.verify_ev_cert)
    919     flags |= X509Certificate::VERIFY_EV_CERT;
    920   verifier_.reset(new CertVerifier);
    921   return verifier_->Verify(server_cert_, hostname_, flags,
    922                            &server_cert_verify_result_,
    923                            &handshake_io_callback_);
    924 }
    925 
    926 int SSLClientSocketMac::DoVerifyCertComplete(int result) {
    927   DCHECK(verifier_.get());
    928   verifier_.reset();
    929 
    930   if (IsCertificateError(result) && ssl_config_.IsAllowedBadCert(server_cert_))
    931     result = OK;
    932 
    933   if (handshake_interrupted_) {
    934     // With session resumption enabled the full handshake (i.e., the handshake
    935     // in a non-resumed session) occurs in two steps. Continue on to the second
    936     // step if the certificate is OK.
    937     if (result == OK)
    938       next_handshake_state_ = STATE_HANDSHAKE_FINISH;
    939   } else {
    940     // If the session was resumed or session resumption was disabled, we're
    941     // done with the handshake.
    942     completed_handshake_ = true;
    943     DCHECK(next_handshake_state_ == STATE_NONE);
    944   }
    945 
    946   return result;
    947 }
    948 
    949 int SSLClientSocketMac::DoHandshakeFinish() {
    950   OSStatus status = SSLHandshake(ssl_context_);
    951 
    952   if (status == errSSLWouldBlock)
    953     next_handshake_state_ = STATE_HANDSHAKE_FINISH;
    954 
    955   if (status == errSSLClosedGraceful)
    956     return ERR_SSL_PROTOCOL_ERROR;
    957 
    958   if (status == noErr) {
    959     completed_handshake_ = true;
    960     DCHECK(next_handshake_state_ == STATE_NONE);
    961   }
    962 
    963   return NetErrorFromOSStatus(status);
    964 }
    965 
    966 int SSLClientSocketMac::DoPayloadRead() {
    967   size_t processed = 0;
    968   OSStatus status = SSLRead(ssl_context_,
    969                             user_read_buf_->data(),
    970                             user_read_buf_len_,
    971                             &processed);
    972 
    973   // There's a subtle difference here in semantics of the "would block" errors.
    974   // In our code, ERR_IO_PENDING means the whole operation is async, while
    975   // errSSLWouldBlock means that the stream isn't ending (and is often returned
    976   // along with partial data). So even though "would block" is returned, if we
    977   // have data, let's just return it.
    978 
    979   if (processed > 0)
    980     return processed;
    981 
    982   if (status == errSSLClosedNoNotify) {
    983     // TODO(wtc): Unless we have received the close_notify alert, we need to
    984     // return an error code indicating that the SSL connection ended
    985     // uncleanly, a potential truncation attack.  See http://crbug.com/18586.
    986     return OK;
    987   }
    988 
    989   return NetErrorFromOSStatus(status);
    990 }
    991 
    992 int SSLClientSocketMac::DoPayloadWrite() {
    993   size_t processed = 0;
    994   OSStatus status = SSLWrite(ssl_context_,
    995                              user_write_buf_->data(),
    996                              user_write_buf_len_,
    997                              &processed);
    998 
    999   if (processed > 0)
   1000     return processed;
   1001 
   1002   return NetErrorFromOSStatus(status);
   1003 }
   1004 
   1005 // static
   1006 OSStatus SSLClientSocketMac::SSLReadCallback(SSLConnectionRef connection,
   1007                                              void* data,
   1008                                              size_t* data_length) {
   1009   DCHECK(data);
   1010   DCHECK(data_length);
   1011   SSLClientSocketMac* us =
   1012       const_cast<SSLClientSocketMac*>(
   1013           static_cast<const SSLClientSocketMac*>(connection));
   1014 
   1015   if (us->read_io_buf_) {
   1016     // We have I/O in flight; promise we'll get back to them and use the
   1017     // existing callback to do so.
   1018     *data_length = 0;
   1019     return errSSLWouldBlock;
   1020   }
   1021 
   1022   size_t total_read = us->recv_buffer_.size();
   1023 
   1024   int rv = 1;  // any old value to spin the loop below
   1025   while (rv > 0 && total_read < *data_length) {
   1026     us->read_io_buf_ = new IOBuffer(*data_length - total_read);
   1027     rv = us->transport_->Read(us->read_io_buf_,
   1028                               *data_length - total_read,
   1029                               &us->transport_read_callback_);
   1030 
   1031     if (rv >= 0) {
   1032       us->recv_buffer_.insert(us->recv_buffer_.end(),
   1033                               us->read_io_buf_->data(),
   1034                               us->read_io_buf_->data() + rv);
   1035       us->read_io_buf_ = NULL;
   1036       total_read += rv;
   1037     }
   1038   }
   1039 
   1040   *data_length = total_read;
   1041   if (total_read) {
   1042     memcpy(data, &us->recv_buffer_[0], total_read);
   1043     us->recv_buffer_.clear();
   1044   }
   1045 
   1046   if (rv != ERR_IO_PENDING)
   1047     us->read_io_buf_ = NULL;
   1048 
   1049   if (rv < 0)
   1050     return OSStatusFromNetError(rv);
   1051   else if (rv == 0)  // stream closed
   1052     return errSSLClosedGraceful;
   1053   else
   1054     return noErr;
   1055 }
   1056 
   1057 // static
   1058 OSStatus SSLClientSocketMac::SSLWriteCallback(SSLConnectionRef connection,
   1059                                               const void* data,
   1060                                               size_t* data_length) {
   1061   SSLClientSocketMac* us =
   1062       const_cast<SSLClientSocketMac*>(
   1063           static_cast<const SSLClientSocketMac*>(connection));
   1064 
   1065   if (us->pending_send_error_ != OK) {
   1066     OSStatus status = OSStatusFromNetError(us->pending_send_error_);
   1067     us->pending_send_error_ = OK;
   1068     return status;
   1069   }
   1070 
   1071   if (data)
   1072     us->send_buffer_.insert(us->send_buffer_.end(),
   1073                             static_cast<const char*>(data),
   1074                             static_cast<const char*>(data) + *data_length);
   1075 
   1076   if (us->write_io_buf_) {
   1077     // If we have I/O in flight, just add the data to the end of the buffer and
   1078     // return to our caller. The existing callback will trigger the write of the
   1079     // new data when it sees that data remains in the buffer after removing the
   1080     // sent data. As always, lie to our caller.
   1081     return noErr;
   1082   }
   1083 
   1084   int rv;
   1085   do {
   1086     us->write_io_buf_ = new IOBuffer(us->send_buffer_.size());
   1087     memcpy(us->write_io_buf_->data(), &us->send_buffer_[0],
   1088            us->send_buffer_.size());
   1089     rv = us->transport_->Write(us->write_io_buf_,
   1090                                us->send_buffer_.size(),
   1091                                &us->transport_write_callback_);
   1092     if (rv > 0) {
   1093       us->send_buffer_.erase(us->send_buffer_.begin(),
   1094                              us->send_buffer_.begin() + rv);
   1095       us->write_io_buf_ = NULL;
   1096     }
   1097   } while (rv > 0 && !us->send_buffer_.empty());
   1098 
   1099   if (rv < 0 && rv != ERR_IO_PENDING) {
   1100     us->write_io_buf_ = NULL;
   1101     return OSStatusFromNetError(rv);
   1102   }
   1103 
   1104   // always lie to our caller
   1105   return noErr;
   1106 }
   1107 
   1108 }  // namespace net
   1109