diff options
Diffstat (limited to 'net/socket/ssl_client_socket_nss.cc')
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 232 |
1 files changed, 11 insertions, 221 deletions
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index 3f56b59..49e065f 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -63,7 +63,6 @@ #include "base/compiler_specific.h" #include "base/metrics/histogram.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/nss_util.h" #include "base/string_number_conversions.h" @@ -88,6 +87,7 @@ #include "net/ocsp/nss_ocsp.h" #include "net/socket/client_socket_handle.h" #include "net/socket/dns_cert_provenance_checker.h" +#include "net/socket/nss_ssl_util.h" #include "net/socket/ssl_error_params.h" #include "net/socket/ssl_host_info.h" @@ -139,183 +139,6 @@ namespace net { namespace { -class NSSSSLInitSingleton { - public: - NSSSSLInitSingleton() { - base::EnsureNSSInit(); - - NSS_SetDomesticPolicy(); - -#if defined(USE_SYSTEM_SSL) - // Use late binding to avoid scary but benign warning - // "Symbol `SSL_ImplementedCiphers' has different size in shared object, - // consider re-linking" - // TODO(wtc): Use the new SSL_GetImplementedCiphers and - // SSL_GetNumImplementedCiphers functions when we require NSS 3.12.6. - // See https://bugzilla.mozilla.org/show_bug.cgi?id=496993. - const PRUint16* pSSL_ImplementedCiphers = static_cast<const PRUint16*>( - dlsym(RTLD_DEFAULT, "SSL_ImplementedCiphers")); - if (pSSL_ImplementedCiphers == NULL) { - NOTREACHED() << "Can't get list of supported ciphers"; - return; - } -#else -#define pSSL_ImplementedCiphers SSL_ImplementedCiphers -#endif - - // Explicitly enable exactly those ciphers with keys of at least 80 bits - for (int i = 0; i < SSL_NumImplementedCiphers; i++) { - SSLCipherSuiteInfo info; - if (SSL_GetCipherSuiteInfo(pSSL_ImplementedCiphers[i], &info, - sizeof(info)) == SECSuccess) { - SSL_CipherPrefSetDefault(pSSL_ImplementedCiphers[i], - (info.effectiveKeyBits >= 80)); - } - } - - // Enable SSL. - SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE); - - // All other SSL options are set per-session by SSLClientSocket. - } - - ~NSSSSLInitSingleton() { - // Have to clear the cache, or NSS_Shutdown fails with SEC_ERROR_BUSY. - SSL_ClearSessionCache(); - } -}; - -static base::LazyInstance<NSSSSLInitSingleton> g_nss_ssl_init_singleton( - base::LINKER_INITIALIZED); - -// Initialize the NSS SSL library if it isn't already initialized. This must -// be called before any other NSS SSL functions. This function is -// thread-safe, and the NSS SSL library will only ever be initialized once. -// The NSS SSL library will be properly shut down on program exit. -void EnsureNSSSSLInit() { - // Initializing SSL causes us to do blocking IO. - // Temporarily allow it until we fix - // http://code.google.com/p/chromium/issues/detail?id=59847 - base::ThreadRestrictions::ScopedAllowIO allow_io; - - g_nss_ssl_init_singleton.Get(); -} - -// The default error mapping function. -// Maps an NSPR error code to a network error code. -int MapNSPRError(PRErrorCode err) { - // TODO(port): fill this out as we learn what's important - switch (err) { - case PR_WOULD_BLOCK_ERROR: - return ERR_IO_PENDING; - case PR_ADDRESS_NOT_SUPPORTED_ERROR: // For connect. - case PR_NO_ACCESS_RIGHTS_ERROR: - return ERR_ACCESS_DENIED; - case PR_IO_TIMEOUT_ERROR: - return ERR_TIMED_OUT; - case PR_CONNECT_RESET_ERROR: - return ERR_CONNECTION_RESET; - case PR_CONNECT_ABORTED_ERROR: - return ERR_CONNECTION_ABORTED; - case PR_CONNECT_REFUSED_ERROR: - return ERR_CONNECTION_REFUSED; - case PR_HOST_UNREACHABLE_ERROR: - case PR_NETWORK_UNREACHABLE_ERROR: - return ERR_ADDRESS_UNREACHABLE; - case PR_ADDRESS_NOT_AVAILABLE_ERROR: - return ERR_ADDRESS_INVALID; - case PR_INVALID_ARGUMENT_ERROR: - return ERR_INVALID_ARGUMENT; - case PR_END_OF_FILE_ERROR: - return ERR_CONNECTION_CLOSED; - case PR_NOT_IMPLEMENTED_ERROR: - return ERR_NOT_IMPLEMENTED; - - case SEC_ERROR_INVALID_ARGS: - return ERR_INVALID_ARGUMENT; - - case SSL_ERROR_SSL_DISABLED: - return ERR_NO_SSL_VERSIONS_ENABLED; - case SSL_ERROR_NO_CYPHER_OVERLAP: - case SSL_ERROR_UNSUPPORTED_VERSION: - return ERR_SSL_VERSION_OR_CIPHER_MISMATCH; - case SSL_ERROR_HANDSHAKE_FAILURE_ALERT: - case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT: - case SSL_ERROR_ILLEGAL_PARAMETER_ALERT: - return ERR_SSL_PROTOCOL_ERROR; - case SSL_ERROR_DECOMPRESSION_FAILURE_ALERT: - return ERR_SSL_DECOMPRESSION_FAILURE_ALERT; - case SSL_ERROR_BAD_MAC_ALERT: - return ERR_SSL_BAD_RECORD_MAC_ALERT; - case SSL_ERROR_UNSAFE_NEGOTIATION: - return ERR_SSL_UNSAFE_NEGOTIATION; - case SSL_ERROR_WEAK_SERVER_KEY: - return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY; - - default: { - if (IS_SSL_ERROR(err)) { - LOG(WARNING) << "Unknown SSL error " << err << - " mapped to net::ERR_SSL_PROTOCOL_ERROR"; - return ERR_SSL_PROTOCOL_ERROR; - } - LOG(WARNING) << "Unknown error " << err << - " mapped to net::ERR_FAILED"; - return ERR_FAILED; - } - } -} - -// Context-sensitive error mapping functions. - -int MapHandshakeError(PRErrorCode err) { - switch (err) { - // If the server closed on us, it is a protocol error. - // Some TLS-intolerant servers do this when we request TLS. - case PR_END_OF_FILE_ERROR: - // The handshake may fail because some signature (for example, the - // signature in the ServerKeyExchange message for an ephemeral - // Diffie-Hellman cipher suite) is invalid. - case SEC_ERROR_BAD_SIGNATURE: - return ERR_SSL_PROTOCOL_ERROR; - default: - return MapNSPRError(err); - } -} - -// Extra parameters to attach to the NetLog when we receive an error in response -// to a call to an NSS function. Used instead of SSLErrorParams with -// events of type TYPE_SSL_NSS_ERROR. Automatically looks up last PR error. -class SSLFailedNSSFunctionParams : public NetLog::EventParameters { - public: - // |param| is ignored if it has a length of 0. - SSLFailedNSSFunctionParams(const std::string& function, - const std::string& param) - : function_(function), param_(param), ssl_lib_error_(PR_GetError()) { - } - - virtual Value* ToValue() const { - DictionaryValue* dict = new DictionaryValue(); - dict->SetString("function", function_); - if (!param_.empty()) - dict->SetString("param", param_); - dict->SetInteger("ssl_lib_error", ssl_lib_error_); - return dict; - } - - private: - const std::string function_; - const std::string param_; - const PRErrorCode ssl_lib_error_; -}; - -void LogFailedNSSFunction(const BoundNetLog& net_log, - const char* function, - const char* param) { - net_log.AddEvent( - NetLog::TYPE_SSL_NSS_ERROR, - make_scoped_refptr(new SSLFailedNSSFunctionParams(function, param))); -} - #if defined(OS_WIN) // This callback is intended to be used with CertFindChainInStore. In addition @@ -736,6 +559,13 @@ int SSLClientSocketNSS::InitializeSSLOptions() { #error "You need to install NSS-3.12 or later to build chromium" #endif + rv = SSL_OptionSet(nss_fd_, SSL_NO_CACHE, + ssl_config_.session_resume_disabled); + if (rv != SECSuccess) { + LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_NO_CACHE"); + return ERR_UNEXPECTED; + } + #ifdef SSL_ENABLE_DEFLATE // Some web servers have been found to break if TLS is used *or* if DEFLATE // is advertised. Thus, if TLS is disabled (probably because we are doing @@ -1363,46 +1193,6 @@ void SSLClientSocketNSS::OnRecvComplete(int result) { LeaveFunction(""); } -// Map a Chromium net error code to an NSS error code. -// See _MD_unix_map_default_error in the NSS source -// tree for inspiration. -static PRErrorCode MapErrorToNSS(int result) { - if (result >=0) - return result; - - switch (result) { - case ERR_IO_PENDING: - return PR_WOULD_BLOCK_ERROR; - case ERR_ACCESS_DENIED: - case ERR_NETWORK_ACCESS_DENIED: - // For connect, this could be mapped to PR_ADDRESS_NOT_SUPPORTED_ERROR. - return PR_NO_ACCESS_RIGHTS_ERROR; - case ERR_NOT_IMPLEMENTED: - return PR_NOT_IMPLEMENTED_ERROR; - case ERR_INTERNET_DISCONNECTED: // Equivalent to ENETDOWN. - return PR_NETWORK_UNREACHABLE_ERROR; // Best approximation. - case ERR_CONNECTION_TIMED_OUT: - case ERR_TIMED_OUT: - return PR_IO_TIMEOUT_ERROR; - case ERR_CONNECTION_RESET: - return PR_CONNECT_RESET_ERROR; - case ERR_CONNECTION_ABORTED: - return PR_CONNECT_ABORTED_ERROR; - case ERR_CONNECTION_REFUSED: - return PR_CONNECT_REFUSED_ERROR; - case ERR_ADDRESS_UNREACHABLE: - return PR_HOST_UNREACHABLE_ERROR; // Also PR_NETWORK_UNREACHABLE_ERROR. - case ERR_ADDRESS_INVALID: - return PR_ADDRESS_NOT_AVAILABLE_ERROR; - case ERR_NAME_NOT_RESOLVED: - return PR_DIRECTORY_LOOKUP_ERROR; - default: - LOG(WARNING) << "MapErrorToNSS " << result - << " mapped to PR_UNKNOWN_ERROR"; - return PR_UNKNOWN_ERROR; - } -} - // Do network I/O between the given buffer and the given socket. // Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING) bool SSLClientSocketNSS::DoTransportIO() { @@ -2191,7 +1981,7 @@ int SSLClientSocketNSS::DoHandshake() { } } else { PRErrorCode prerr = PR_GetError(); - net_error = MapHandshakeError(prerr); + net_error = MapNSSHandshakeError(prerr); // If not done, stay in this state if (net_error == ERR_IO_PENDING) { @@ -2580,7 +2370,7 @@ int SSLClientSocketNSS::DoPayloadRead() { return ERR_IO_PENDING; } LeaveFunction(""); - rv = MapNSPRError(prerr); + rv = MapNSSError(prerr); net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR, make_scoped_refptr(new SSLErrorParams(rv, prerr))); return rv; @@ -2601,7 +2391,7 @@ int SSLClientSocketNSS::DoPayloadWrite() { return ERR_IO_PENDING; } LeaveFunction(""); - rv = MapNSPRError(prerr); + rv = MapNSSError(prerr); net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR, make_scoped_refptr(new SSLErrorParams(rv, prerr))); return rv; |