| 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 |