| OLD | NEW | 
|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "net/socket/ssl_client_socket_mac.h" | 5 #include "net/socket/ssl_client_socket_mac.h" | 
| 6 | 6 | 
| 7 #include <CoreServices/CoreServices.h> | 7 #include <CoreServices/CoreServices.h> | 
| 8 #include <netdb.h> | 8 #include <netdb.h> | 
| 9 #include <sys/socket.h> | 9 #include <sys/socket.h> | 
| 10 #include <sys/types.h> | 10 #include <sys/types.h> | 
| 11 | 11 | 
|  | 12 #include <algorithm> | 
|  | 13 | 
| 12 #include "base/mac/scoped_cftyperef.h" | 14 #include "base/mac/scoped_cftyperef.h" | 
| 13 #include "base/singleton.h" | 15 #include "base/singleton.h" | 
| 14 #include "base/string_util.h" | 16 #include "base/string_util.h" | 
| 15 #include "net/base/address_list.h" | 17 #include "net/base/address_list.h" | 
| 16 #include "net/base/cert_verifier.h" | 18 #include "net/base/cert_verifier.h" | 
| 17 #include "net/base/io_buffer.h" | 19 #include "net/base/io_buffer.h" | 
| 18 #include "net/base/net_errors.h" | 20 #include "net/base/net_errors.h" | 
| 19 #include "net/base/net_log.h" | 21 #include "net/base/net_log.h" | 
| 20 #include "net/base/ssl_cert_request_info.h" | 22 #include "net/base/ssl_cert_request_info.h" | 
| 21 #include "net/base/ssl_connection_status_flags.h" | 23 #include "net/base/ssl_connection_status_flags.h" | 
| 22 #include "net/base/ssl_info.h" | 24 #include "net/base/ssl_info.h" | 
| 23 #include "net/socket/client_socket_handle.h" | 25 #include "net/socket/client_socket_handle.h" | 
|  | 26 #include "net/socket/ssl_error_params.h" | 
| 24 | 27 | 
| 25 // Welcome to Mac SSL. We've been waiting for you. | 28 // Welcome to Mac SSL. We've been waiting for you. | 
| 26 // | 29 // | 
| 27 // The Mac SSL implementation is, like the Windows and NSS implementations, a | 30 // The Mac SSL implementation is, like the Windows and NSS implementations, a | 
| 28 // giant state machine. This design constraint is due to the asynchronous nature | 31 // giant state machine. This design constraint is due to the asynchronous nature | 
| 29 // of our underlying transport mechanism. We can call down to read/write on the | 32 // of our underlying transport mechanism. We can call down to read/write on the | 
| 30 // network, but what happens is that either it completes immediately or returns | 33 // network, but what happens is that either it completes immediately or returns | 
| 31 // saying that we'll get a callback sometime in the future. In that case, we | 34 // saying that we'll get a callback sometime in the future. In that case, we | 
| 32 // have to return to our caller but pick up where we left off when we | 35 // have to return to our caller but pick up where we left off when we | 
| 33 // resume. Thus the fun. | 36 // resume. Thus the fun. | 
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 136   TLS_ECDH_anon_WITH_AES_256_CBC_SHA     = 0xC019, | 139   TLS_ECDH_anon_WITH_AES_256_CBC_SHA     = 0xC019, | 
| 137 }; | 140 }; | 
| 138 #endif | 141 #endif | 
| 139 | 142 | 
| 140 // For an explanation of the Mac OS X error codes, please refer to: | 143 // For an explanation of the Mac OS X error codes, please refer to: | 
| 141 // http://developer.apple.com/mac/library/documentation/Security/Reference/secur
      eTransportRef/Reference/reference.html | 144 // http://developer.apple.com/mac/library/documentation/Security/Reference/secur
      eTransportRef/Reference/reference.html | 
| 142 int NetErrorFromOSStatus(OSStatus status) { | 145 int NetErrorFromOSStatus(OSStatus status) { | 
| 143   switch (status) { | 146   switch (status) { | 
| 144     case errSSLWouldBlock: | 147     case errSSLWouldBlock: | 
| 145       return ERR_IO_PENDING; | 148       return ERR_IO_PENDING; | 
|  | 149     case paramErr: | 
| 146     case errSSLBadCipherSuite: | 150     case errSSLBadCipherSuite: | 
| 147     case errSSLBadConfiguration: | 151     case errSSLBadConfiguration: | 
| 148       return ERR_INVALID_ARGUMENT; | 152       return ERR_INVALID_ARGUMENT; | 
| 149     case errSSLClosedNoNotify: | 153     case errSSLClosedNoNotify: | 
| 150       return ERR_CONNECTION_RESET; | 154       return ERR_CONNECTION_RESET; | 
| 151     case errSSLClosedAbort: | 155     case errSSLClosedAbort: | 
| 152       return ERR_CONNECTION_ABORTED; | 156       return ERR_CONNECTION_ABORTED; | 
| 153     case errSSLInternal: | 157     case errSSLInternal: | 
| 154       return ERR_UNEXPECTED; | 158       return ERR_UNEXPECTED; | 
| 155     case errSSLBadRecordMac: | 159     case errSSLBadRecordMac: | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 193     //   certificate_expired | 197     //   certificate_expired | 
| 194     //   certificate_revoked | 198     //   certificate_revoked | 
| 195     //   certificate_unknown | 199     //   certificate_unknown | 
| 196     //   unknown_ca | 200     //   unknown_ca | 
| 197     case errSSLPeerCertUnknown...errSSLPeerBadCert: | 201     case errSSLPeerCertUnknown...errSSLPeerBadCert: | 
| 198     case errSSLPeerUnknownCA: | 202     case errSSLPeerUnknownCA: | 
| 199     case errSSLPeerAccessDenied: | 203     case errSSLPeerAccessDenied: | 
| 200       LOG(WARNING) << "Server rejected client cert (OSStatus=" << status << ")"; | 204       LOG(WARNING) << "Server rejected client cert (OSStatus=" << status << ")"; | 
| 201       return ERR_BAD_SSL_CLIENT_AUTH_CERT; | 205       return ERR_BAD_SSL_CLIENT_AUTH_CERT; | 
| 202 | 206 | 
|  | 207     case errSSLNegotiation: | 
| 203     case errSSLPeerInsufficientSecurity: | 208     case errSSLPeerInsufficientSecurity: | 
| 204     case errSSLPeerProtocolVersion: | 209     case errSSLPeerProtocolVersion: | 
| 205       return ERR_SSL_VERSION_OR_CIPHER_MISMATCH; | 210       return ERR_SSL_VERSION_OR_CIPHER_MISMATCH; | 
| 206 | 211 | 
| 207     case errSSLBufferOverflow: | 212     case errSSLBufferOverflow: | 
| 208     case errSSLModuleAttach: | 213     case errSSLModuleAttach: | 
| 209     case errSSLNegotiation: |  | 
| 210     case errSSLSessionNotFound: | 214     case errSSLSessionNotFound: | 
| 211     default: | 215     default: | 
| 212       LOG(WARNING) << "Unknown error " << status << | 216       LOG(WARNING) << "Unknown error " << status << | 
| 213           " mapped to net::ERR_FAILED"; | 217           " mapped to net::ERR_FAILED"; | 
| 214       return ERR_FAILED; | 218       return ERR_FAILED; | 
| 215   } | 219   } | 
| 216 } | 220 } | 
| 217 | 221 | 
| 218 OSStatus OSStatusFromNetError(int net_error) { | 222 OSStatus OSStatusFromNetError(int net_error) { | 
| 219   switch (net_error) { | 223   switch (net_error) { | 
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 441 // Dynamically look up a pointer to a function exported by a bundle. | 445 // Dynamically look up a pointer to a function exported by a bundle. | 
| 442 template <typename FNTYPE> | 446 template <typename FNTYPE> | 
| 443 FNTYPE LookupFunction(CFStringRef bundleName, CFStringRef fnName) { | 447 FNTYPE LookupFunction(CFStringRef bundleName, CFStringRef fnName) { | 
| 444   CFBundleRef bundle = CFBundleGetBundleWithIdentifier(bundleName); | 448   CFBundleRef bundle = CFBundleGetBundleWithIdentifier(bundleName); | 
| 445   if (!bundle) | 449   if (!bundle) | 
| 446     return NULL; | 450     return NULL; | 
| 447   return reinterpret_cast<FNTYPE>( | 451   return reinterpret_cast<FNTYPE>( | 
| 448       CFBundleGetFunctionPointerForName(bundle, fnName)); | 452       CFBundleGetFunctionPointerForName(bundle, fnName)); | 
| 449 } | 453 } | 
| 450 | 454 | 
| 451 // A class that wraps an array of enabled cipher suites that can be passed to | 455 struct CipherSuiteIsDisabledFunctor { | 
| 452 // SSLSetEnabledCiphers. | 456   explicit CipherSuiteIsDisabledFunctor( | 
| 453 // | 457       const std::vector<uint16>& disabled_cipher_suites) | 
| 454 // Used as a singleton. | 458       : disabled_cipher_suites_(disabled_cipher_suites) {} | 
|  | 459 | 
|  | 460   // Returns true if the given |cipher_suite| appears within the set of | 
|  | 461   // |disabled_cipher_suites|. | 
|  | 462   bool operator()(SSLCipherSuite cipher_suite) const { | 
|  | 463     return binary_search(disabled_cipher_suites_.begin(), | 
|  | 464                          disabled_cipher_suites_.end(), | 
|  | 465                          static_cast<uint16>(cipher_suite)); | 
|  | 466   } | 
|  | 467 | 
|  | 468   const std::vector<uint16>& disabled_cipher_suites_; | 
|  | 469 }; | 
|  | 470 | 
|  | 471 // Class to determine what cipher suites are available and which cipher | 
|  | 472 // suites should be enabled, based on the overall security policy. | 
| 455 class EnabledCipherSuites { | 473 class EnabledCipherSuites { | 
| 456  public: | 474  public: | 
| 457   EnabledCipherSuites(); | 475   const std::vector<SSLCipherSuite>& ciphers() const { return ciphers_; } | 
| 458 |  | 
| 459   const SSLCipherSuite* ciphers() const { |  | 
| 460     return ciphers_.empty() ? NULL : &ciphers_[0]; |  | 
| 461   } |  | 
| 462   size_t num_ciphers() const { return ciphers_.size(); } |  | 
| 463 | 476 | 
| 464  private: | 477  private: | 
|  | 478   friend struct DefaultSingletonTraits<EnabledCipherSuites>; | 
|  | 479   EnabledCipherSuites(); | 
|  | 480   ~EnabledCipherSuites() {} | 
|  | 481 | 
| 465   std::vector<SSLCipherSuite> ciphers_; | 482   std::vector<SSLCipherSuite> ciphers_; | 
| 466 | 483 | 
| 467   DISALLOW_COPY_AND_ASSIGN(EnabledCipherSuites); | 484   DISALLOW_COPY_AND_ASSIGN(EnabledCipherSuites); | 
| 468 }; | 485 }; | 
| 469 | 486 | 
| 470 EnabledCipherSuites::EnabledCipherSuites() { | 487 EnabledCipherSuites::EnabledCipherSuites() { | 
| 471   SSLContextRef ssl_context; | 488   SSLContextRef ssl_context; | 
| 472   OSStatus status = SSLNewContext(false, &ssl_context); | 489   OSStatus status = SSLNewContext(false, &ssl_context); | 
| 473   if (status != noErr) | 490   if (status != noErr) | 
| 474     return; | 491     return; | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 513       user_read_callback_(NULL), | 530       user_read_callback_(NULL), | 
| 514       user_write_callback_(NULL), | 531       user_write_callback_(NULL), | 
| 515       user_read_buf_len_(0), | 532       user_read_buf_len_(0), | 
| 516       user_write_buf_len_(0), | 533       user_write_buf_len_(0), | 
| 517       next_handshake_state_(STATE_NONE), | 534       next_handshake_state_(STATE_NONE), | 
| 518       renegotiating_(false), | 535       renegotiating_(false), | 
| 519       client_cert_requested_(false), | 536       client_cert_requested_(false), | 
| 520       ssl_context_(NULL), | 537       ssl_context_(NULL), | 
| 521       pending_send_error_(OK), | 538       pending_send_error_(OK), | 
| 522       net_log_(transport_socket->socket()->NetLog()) { | 539       net_log_(transport_socket->socket()->NetLog()) { | 
|  | 540   // Sort the list of ciphers to disable, since disabling ciphers on Mac | 
|  | 541   // requires subtracting from a list of enabled ciphers while maintaining | 
|  | 542   // ordering, as opposed to merely needing to iterate them as with NSS. | 
|  | 543   sort(ssl_config_.disabled_cipher_suites.begin(), | 
|  | 544        ssl_config_.disabled_cipher_suites.end()); | 
| 523 } | 545 } | 
| 524 | 546 | 
| 525 SSLClientSocketMac::~SSLClientSocketMac() { | 547 SSLClientSocketMac::~SSLClientSocketMac() { | 
| 526   Disconnect(); | 548   Disconnect(); | 
| 527 } | 549 } | 
| 528 | 550 | 
| 529 int SSLClientSocketMac::Connect(CompletionCallback* callback) { | 551 int SSLClientSocketMac::Connect(CompletionCallback* callback) { | 
| 530   DCHECK(transport_.get()); | 552   DCHECK(transport_.get()); | 
| 531   DCHECK(next_handshake_state_ == STATE_NONE); | 553   DCHECK(next_handshake_state_ == STATE_NONE); | 
| 532   DCHECK(!user_connect_callback_); | 554   DCHECK(!user_connect_callback_); | 
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 754                                         ssl_config_.ssl3_enabled); | 776                                         ssl_config_.ssl3_enabled); | 
| 755   if (status) | 777   if (status) | 
| 756     return NetErrorFromOSStatus(status); | 778     return NetErrorFromOSStatus(status); | 
| 757 | 779 | 
| 758   status = SSLSetProtocolVersionEnabled(ssl_context_, | 780   status = SSLSetProtocolVersionEnabled(ssl_context_, | 
| 759                                         kTLSProtocol1, | 781                                         kTLSProtocol1, | 
| 760                                         ssl_config_.tls1_enabled); | 782                                         ssl_config_.tls1_enabled); | 
| 761   if (status) | 783   if (status) | 
| 762     return NetErrorFromOSStatus(status); | 784     return NetErrorFromOSStatus(status); | 
| 763 | 785 | 
| 764   const EnabledCipherSuites* enabled_ciphers = | 786   std::vector<SSLCipherSuite> enabled_ciphers = | 
| 765       Singleton<EnabledCipherSuites>::get(); | 787       Singleton<EnabledCipherSuites>::get()->ciphers(); | 
| 766   status = SSLSetEnabledCiphers(ssl_context_, enabled_ciphers->ciphers(), | 788 | 
| 767                                 enabled_ciphers->num_ciphers()); | 789   CipherSuiteIsDisabledFunctor is_disabled_cipher( | 
|  | 790       ssl_config_.disabled_cipher_suites); | 
|  | 791   std::vector<SSLCipherSuite>::iterator new_end = | 
|  | 792       std::remove_if(enabled_ciphers.begin(), enabled_ciphers.end(), | 
|  | 793                      is_disabled_cipher); | 
|  | 794   if (new_end != enabled_ciphers.end()) | 
|  | 795     enabled_ciphers.erase(new_end, enabled_ciphers.end()); | 
|  | 796 | 
|  | 797   status = SSLSetEnabledCiphers( | 
|  | 798       ssl_context_, | 
|  | 799       enabled_ciphers.empty() ? NULL : &enabled_ciphers[0], | 
|  | 800       enabled_ciphers.size()); | 
|  | 801 | 
| 768   if (status) | 802   if (status) | 
| 769     return NetErrorFromOSStatus(status); | 803     return NetErrorFromOSStatus(status); | 
| 770 | 804 | 
| 771   status = SSLSetIOFuncs(ssl_context_, SSLReadCallback, SSLWriteCallback); | 805   status = SSLSetIOFuncs(ssl_context_, SSLReadCallback, SSLWriteCallback); | 
| 772   if (status) | 806   if (status) | 
| 773     return NetErrorFromOSStatus(status); | 807     return NetErrorFromOSStatus(status); | 
| 774 | 808 | 
| 775   status = SSLSetConnection(ssl_context_, this); | 809   status = SSLSetConnection(ssl_context_, this); | 
| 776   if (status) | 810   if (status) | 
| 777     return NetErrorFromOSStatus(status); | 811     return NetErrorFromOSStatus(status); | 
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 963   client_cert_requested_ = false; | 997   client_cert_requested_ = false; | 
| 964 | 998 | 
| 965   OSStatus status = SSLHandshake(ssl_context_); | 999   OSStatus status = SSLHandshake(ssl_context_); | 
| 966 | 1000 | 
| 967   SSLClientCertificateState client_cert_state; | 1001   SSLClientCertificateState client_cert_state; | 
| 968   if (SSLGetClientCertificateState(ssl_context_, &client_cert_state) != noErr) | 1002   if (SSLGetClientCertificateState(ssl_context_, &client_cert_state) != noErr) | 
| 969     client_cert_state = kSSLClientCertNone; | 1003     client_cert_state = kSSLClientCertNone; | 
| 970   if (client_cert_state > kSSLClientCertNone) | 1004   if (client_cert_state > kSSLClientCertNone) | 
| 971     client_cert_requested_ = true; | 1005     client_cert_requested_ = true; | 
| 972 | 1006 | 
|  | 1007   int net_error = ERR_FAILED; | 
| 973   switch (status) { | 1008   switch (status) { | 
| 974     case noErr: | 1009     case noErr: | 
| 975       return DidCompleteHandshake(); | 1010       return DidCompleteHandshake(); | 
| 976     case errSSLWouldBlock: | 1011     case errSSLWouldBlock: | 
| 977       next_handshake_state_ = STATE_HANDSHAKE; | 1012       next_handshake_state_ = STATE_HANDSHAKE; | 
| 978       break; | 1013       return ERR_IO_PENDING; | 
| 979     case errSSLClosedGraceful: | 1014     case errSSLClosedGraceful: | 
| 980       // The server unexpectedly closed on us. | 1015       // The server unexpectedly closed on us. | 
| 981       return ERR_SSL_PROTOCOL_ERROR; | 1016       net_error = ERR_SSL_PROTOCOL_ERROR; | 
|  | 1017       break; | 
| 982     case errSSLClosedAbort: | 1018     case errSSLClosedAbort: | 
| 983     case errSSLPeerHandshakeFail: | 1019     case errSSLPeerHandshakeFail: | 
| 984       if (client_cert_requested_) { | 1020       if (client_cert_requested_) { | 
| 985         // See if the server aborted due to client cert checking. |  | 
| 986         if (!ssl_config_.send_client_cert) { | 1021         if (!ssl_config_.send_client_cert) { | 
|  | 1022           // The server aborted, likely due to requiring a client certificate | 
|  | 1023           // and one wasn't sent. | 
| 987           VLOG(1) << "Server requested SSL cert during handshake"; | 1024           VLOG(1) << "Server requested SSL cert during handshake"; | 
| 988           return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | 1025           net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | 
|  | 1026         } else { | 
|  | 1027           // The server aborted, likely due to not liking the client | 
|  | 1028           // certificate that was sent. | 
|  | 1029           LOG(WARNING) << "Server aborted SSL handshake"; | 
|  | 1030           net_error = ERR_BAD_SSL_CLIENT_AUTH_CERT; | 
| 989         } | 1031         } | 
| 990         LOG(WARNING) << "Server aborted SSL handshake"; | 1032         // Don't fall through - the error was intentionally remapped. | 
| 991         return ERR_BAD_SSL_CLIENT_AUTH_CERT; | 1033         break; | 
|  | 1034       } | 
|  | 1035       // Fall through if a client cert wasn't requested. | 
|  | 1036     default: | 
|  | 1037       net_error = NetErrorFromOSStatus(status); | 
|  | 1038       DCHECK(!IsCertificateError(net_error)); | 
|  | 1039       if (!ssl_config_.send_client_cert && | 
|  | 1040          (client_cert_state == kSSLClientCertRejected || | 
|  | 1041           net_error == ERR_BAD_SSL_CLIENT_AUTH_CERT)) { | 
|  | 1042         // The server unexpectedly sent a peer certificate error alert when no | 
|  | 1043         // certificate had been sent. | 
|  | 1044         net_error = ERR_SSL_PROTOCOL_ERROR; | 
| 992       } | 1045       } | 
| 993       break; | 1046       break; | 
| 994   } | 1047   } | 
| 995 | 1048 | 
| 996   int net_error = NetErrorFromOSStatus(status); | 1049   net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR, | 
| 997   DCHECK(!IsCertificateError(net_error)); | 1050                     new SSLErrorParams(net_error, status)); | 
| 998 |  | 
| 999   if (!ssl_config_.send_client_cert && |  | 
| 1000      (client_cert_state == kSSLClientCertRejected || |  | 
| 1001       net_error == ERR_BAD_SSL_CLIENT_AUTH_CERT)) { |  | 
| 1002     // The server unexpectedly sent a peer certificate error alert when no |  | 
| 1003     // certificate had been sent. |  | 
| 1004     net_error = ERR_SSL_PROTOCOL_ERROR; |  | 
| 1005   } |  | 
| 1006   return net_error; | 1051   return net_error; | 
| 1007 } | 1052 } | 
| 1008 | 1053 | 
| 1009 int SSLClientSocketMac::DoVerifyCert() { | 1054 int SSLClientSocketMac::DoVerifyCert() { | 
| 1010   next_handshake_state_ = STATE_VERIFY_CERT_COMPLETE; | 1055   next_handshake_state_ = STATE_VERIFY_CERT_COMPLETE; | 
| 1011 | 1056 | 
| 1012   DCHECK(server_cert_); | 1057   DCHECK(server_cert_); | 
| 1013 | 1058 | 
| 1014   VLOG(1) << "DoVerifyCert..."; | 1059   VLOG(1) << "DoVerifyCert..."; | 
| 1015   int flags = 0; | 1060   int flags = 0; | 
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1273   if (rv < 0 && rv != ERR_IO_PENDING) { | 1318   if (rv < 0 && rv != ERR_IO_PENDING) { | 
| 1274     us->write_io_buf_ = NULL; | 1319     us->write_io_buf_ = NULL; | 
| 1275     return OSStatusFromNetError(rv); | 1320     return OSStatusFromNetError(rv); | 
| 1276   } | 1321   } | 
| 1277 | 1322 | 
| 1278   // always lie to our caller | 1323   // always lie to our caller | 
| 1279   return noErr; | 1324   return noErr; | 
| 1280 } | 1325 } | 
| 1281 | 1326 | 
| 1282 }  // namespace net | 1327 }  // namespace net | 
| OLD | NEW | 
|---|