Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: net/socket/ssl_client_socket_mac.cc

Issue 3845005: Add support for restricting the cipher suites that SSLClientSocket(Mac,NSS) use (Closed)
Patch Set: Upload before commit Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698