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