| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_server_socket_nss.h" | 5 #include "net/socket/ssl_server_socket_nss.h" |
| 6 | 6 |
| 7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
| 8 #include <winsock2.h> | 8 #include <winsock2.h> |
| 9 #endif | 9 #endif |
| 10 | 10 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 #include <limits> | 30 #include <limits> |
| 31 | 31 |
| 32 #include "base/callback_helpers.h" | 32 #include "base/callback_helpers.h" |
| 33 #include "base/lazy_instance.h" | 33 #include "base/lazy_instance.h" |
| 34 #include "base/logging.h" | 34 #include "base/logging.h" |
| 35 #include "base/memory/ref_counted.h" | 35 #include "base/memory/ref_counted.h" |
| 36 #include "crypto/nss_util_internal.h" | 36 #include "crypto/nss_util_internal.h" |
| 37 #include "crypto/rsa_private_key.h" | 37 #include "crypto/rsa_private_key.h" |
| 38 #include "net/base/io_buffer.h" | 38 #include "net/base/io_buffer.h" |
| 39 #include "net/base/net_errors.h" | 39 #include "net/base/net_errors.h" |
| 40 #include "net/cert/cert_verifier.h" |
| 40 #include "net/log/net_log.h" | 41 #include "net/log/net_log.h" |
| 41 #include "net/socket/nss_ssl_util.h" | 42 #include "net/socket/nss_ssl_util.h" |
| 42 | 43 |
| 43 // SSL plaintext fragments are shorter than 16KB. Although the record layer | 44 // SSL plaintext fragments are shorter than 16KB. Although the record layer |
| 44 // overhead is allowed to be 2K + 5 bytes, in practice the overhead is much | 45 // overhead is allowed to be 2K + 5 bytes, in practice the overhead is much |
| 45 // smaller than 1KB. So a 17KB buffer should be large enough to hold an | 46 // smaller than 1KB. So a 17KB buffer should be large enough to hold an |
| 46 // entire SSL record. | 47 // entire SSL record. |
| 47 static const int kRecvBufferSize = 17 * 1024; | 48 static const int kRecvBufferSize = 17 * 1024; |
| 48 static const int kSendBufferSize = 17 * 1024; | 49 static const int kSendBufferSize = 17 * 1024; |
| 49 | 50 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 74 g_nss_ssl_server_init_singleton = LAZY_INSTANCE_INITIALIZER; | 75 g_nss_ssl_server_init_singleton = LAZY_INSTANCE_INITIALIZER; |
| 75 | 76 |
| 76 } // namespace | 77 } // namespace |
| 77 | 78 |
| 78 void EnableSSLServerSockets() { | 79 void EnableSSLServerSockets() { |
| 79 g_nss_ssl_server_init_singleton.Get(); | 80 g_nss_ssl_server_init_singleton.Get(); |
| 80 } | 81 } |
| 81 | 82 |
| 82 scoped_ptr<SSLServerSocket> CreateSSLServerSocket( | 83 scoped_ptr<SSLServerSocket> CreateSSLServerSocket( |
| 83 scoped_ptr<StreamSocket> socket, | 84 scoped_ptr<StreamSocket> socket, |
| 84 X509Certificate* cert, | 85 X509Certificate* certificate, |
| 85 crypto::RSAPrivateKey* key, | 86 crypto::RSAPrivateKey* key, |
| 86 const SSLServerConfig& ssl_config) { | 87 const SSLServerConfig& ssl_server_config) { |
| 87 DCHECK(g_nss_server_sockets_init) << "EnableSSLServerSockets() has not been" | 88 DCHECK(g_nss_server_sockets_init) << "EnableSSLServerSockets() has not been" |
| 88 << " called yet!"; | 89 << " called yet!"; |
| 89 | 90 |
| 90 return scoped_ptr<SSLServerSocket>( | 91 return scoped_ptr<SSLServerSocket>(new SSLServerSocketNSS( |
| 91 new SSLServerSocketNSS(socket.Pass(), cert, key, ssl_config)); | 92 socket.Pass(), certificate, key, ssl_server_config)); |
| 93 } |
| 94 |
| 95 scoped_ptr<SSLServerSocket> CreateSSLServerSocket( |
| 96 scoped_ptr<StreamSocket> socket, |
| 97 X509Certificate* certificate, |
| 98 crypto::RSAPrivateKey* key, |
| 99 const SSLServerConfig& ssl_server_config, |
| 100 const SSLServerSocketContext context) { |
| 101 return CreateSSLServerSocket(socket, certificate, key, ssl_server_config); |
| 92 } | 102 } |
| 93 | 103 |
| 94 SSLServerSocketNSS::SSLServerSocketNSS( | 104 SSLServerSocketNSS::SSLServerSocketNSS( |
| 95 scoped_ptr<StreamSocket> transport_socket, | 105 scoped_ptr<StreamSocket> transport_socket, |
| 96 scoped_refptr<X509Certificate> cert, | 106 scoped_refptr<X509Certificate> cert, |
| 97 crypto::RSAPrivateKey* key, | 107 crypto::RSAPrivateKey* key, |
| 98 const SSLServerConfig& ssl_config) | 108 const SSLServerConfig& ssl_server_config) |
| 99 : transport_send_busy_(false), | 109 : transport_send_busy_(false), |
| 100 transport_recv_busy_(false), | 110 transport_recv_busy_(false), |
| 101 user_read_buf_len_(0), | 111 user_read_buf_len_(0), |
| 102 user_write_buf_len_(0), | 112 user_write_buf_len_(0), |
| 103 nss_fd_(NULL), | 113 nss_fd_(NULL), |
| 104 nss_bufs_(NULL), | 114 nss_bufs_(NULL), |
| 105 transport_socket_(transport_socket.Pass()), | 115 transport_socket_(transport_socket.Pass()), |
| 106 ssl_config_(ssl_config), | 116 ssl_server_config_(ssl_server_config), |
| 107 cert_(cert), | 117 cert_(cert), |
| 108 next_handshake_state_(STATE_NONE), | 118 next_handshake_state_(STATE_NONE), |
| 109 completed_handshake_(false) { | 119 completed_handshake_(false) { |
| 110 // TODO(hclam): Need a better way to clone a key. | 120 // TODO(hclam): Need a better way to clone a key. |
| 111 std::vector<uint8> key_bytes; | 121 std::vector<uint8> key_bytes; |
| 112 CHECK(key->ExportPrivateKey(&key_bytes)); | 122 CHECK(key->ExportPrivateKey(&key_bytes)); |
| 113 key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes)); | 123 key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes)); |
| 114 CHECK(key_.get()); | 124 CHECK(key_.get()); |
| 115 } | 125 } |
| 116 | 126 |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 /* Push SSL onto our fake I/O socket */ | 341 /* Push SSL onto our fake I/O socket */ |
| 332 nss_fd_ = SSL_ImportFD(NULL, nss_fd_); | 342 nss_fd_ = SSL_ImportFD(NULL, nss_fd_); |
| 333 if (nss_fd_ == NULL) { | 343 if (nss_fd_ == NULL) { |
| 334 LogFailedNSSFunction(net_log_, "SSL_ImportFD", ""); | 344 LogFailedNSSFunction(net_log_, "SSL_ImportFD", ""); |
| 335 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR/NSS error code. | 345 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR/NSS error code. |
| 336 } | 346 } |
| 337 // TODO(port): set more ssl options! Check errors! | 347 // TODO(port): set more ssl options! Check errors! |
| 338 | 348 |
| 339 int rv; | 349 int rv; |
| 340 | 350 |
| 341 if (ssl_config_.require_client_cert) { | 351 if (ssl_server_config_.require_client_cert) { |
| 342 rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_TRUE); | 352 rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_TRUE); |
| 343 if (rv != SECSuccess) { | 353 if (rv != SECSuccess) { |
| 344 LogFailedNSSFunction(net_log_, "SSL_OptionSet", | 354 LogFailedNSSFunction(net_log_, "SSL_OptionSet", |
| 345 "SSL_REQUEST_CERTIFICATE"); | 355 "SSL_REQUEST_CERTIFICATE"); |
| 346 return ERR_UNEXPECTED; | 356 return ERR_UNEXPECTED; |
| 347 } | 357 } |
| 348 } | 358 } |
| 349 | 359 |
| 350 rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE); | 360 rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE); |
| 351 if (rv != SECSuccess) { | 361 if (rv != SECSuccess) { |
| 352 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY"); | 362 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY"); |
| 353 return ERR_UNEXPECTED; | 363 return ERR_UNEXPECTED; |
| 354 } | 364 } |
| 355 | 365 |
| 356 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE); | 366 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE); |
| 357 if (rv != SECSuccess) { | 367 if (rv != SECSuccess) { |
| 358 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2"); | 368 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2"); |
| 359 return ERR_UNEXPECTED; | 369 return ERR_UNEXPECTED; |
| 360 } | 370 } |
| 361 | 371 |
| 362 SSLVersionRange version_range; | 372 SSLVersionRange version_range; |
| 363 version_range.min = ssl_config_.version_min; | 373 version_range.min = ssl_server_config_.version_min; |
| 364 version_range.max = ssl_config_.version_max; | 374 version_range.max = ssl_server_config_.version_max; |
| 365 rv = SSL_VersionRangeSet(nss_fd_, &version_range); | 375 rv = SSL_VersionRangeSet(nss_fd_, &version_range); |
| 366 if (rv != SECSuccess) { | 376 if (rv != SECSuccess) { |
| 367 LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", ""); | 377 LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", ""); |
| 368 return ERR_NO_SSL_VERSIONS_ENABLED; | 378 return ERR_NO_SSL_VERSIONS_ENABLED; |
| 369 } | 379 } |
| 370 | 380 |
| 371 if (ssl_config_.require_ecdhe) { | 381 if (ssl_server_config_.require_ecdhe) { |
| 372 const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers(); | 382 const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers(); |
| 373 const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers(); | 383 const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers(); |
| 374 | 384 |
| 375 // Iterate over the cipher suites and disable those that don't use ECDHE. | 385 // Iterate over the cipher suites and disable those that don't use ECDHE. |
| 376 for (unsigned i = 0; i < num_ciphers; i++) { | 386 for (unsigned i = 0; i < num_ciphers; i++) { |
| 377 SSLCipherSuiteInfo info; | 387 SSLCipherSuiteInfo info; |
| 378 if (SSL_GetCipherSuiteInfo(ssl_ciphers[i], &info, sizeof(info)) == | 388 if (SSL_GetCipherSuiteInfo(ssl_ciphers[i], &info, sizeof(info)) == |
| 379 SECSuccess) { | 389 SECSuccess) { |
| 380 if (strcmp(info.keaTypeName, "ECDHE") != 0) { | 390 if (strcmp(info.keaTypeName, "ECDHE") != 0) { |
| 381 SSL_CipherPrefSet(nss_fd_, ssl_ciphers[i], PR_FALSE); | 391 SSL_CipherPrefSet(nss_fd_, ssl_ciphers[i], PR_FALSE); |
| 382 } | 392 } |
| 383 } | 393 } |
| 384 } | 394 } |
| 385 } | 395 } |
| 386 | 396 |
| 387 for (std::vector<uint16>::const_iterator it = | 397 for (std::vector<uint16>::const_iterator it = |
| 388 ssl_config_.disabled_cipher_suites.begin(); | 398 ssl_server_config_.disabled_cipher_suites.begin(); |
| 389 it != ssl_config_.disabled_cipher_suites.end(); ++it) { | 399 it != ssl_server_config_.disabled_cipher_suites.end(); ++it) { |
| 390 // This will fail if the specified cipher is not implemented by NSS, but | 400 // This will fail if the specified cipher is not implemented by NSS, but |
| 391 // the failure is harmless. | 401 // the failure is harmless. |
| 392 SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE); | 402 SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE); |
| 393 } | 403 } |
| 394 | 404 |
| 395 // Server socket doesn't need session tickets. | 405 // Server socket doesn't need session tickets. |
| 396 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_FALSE); | 406 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_FALSE); |
| 397 if (rv != SECSuccess) { | 407 if (rv != SECSuccess) { |
| 398 LogFailedNSSFunction( | 408 LogFailedNSSFunction( |
| 399 net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS"); | 409 net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS"); |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 848 // initializes the NSS base library. | 858 // initializes the NSS base library. |
| 849 EnsureNSSSSLInit(); | 859 EnsureNSSSSLInit(); |
| 850 if (!NSS_IsInitialized()) | 860 if (!NSS_IsInitialized()) |
| 851 return ERR_UNEXPECTED; | 861 return ERR_UNEXPECTED; |
| 852 | 862 |
| 853 EnableSSLServerSockets(); | 863 EnableSSLServerSockets(); |
| 854 return OK; | 864 return OK; |
| 855 } | 865 } |
| 856 | 866 |
| 857 } // namespace net | 867 } // namespace net |
| OLD | NEW |