diff options
Diffstat (limited to 'net/http/http_network_transaction_ssl_unittest.cc')
-rw-r--r-- | net/http/http_network_transaction_ssl_unittest.cc | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/net/http/http_network_transaction_ssl_unittest.cc b/net/http/http_network_transaction_ssl_unittest.cc new file mode 100644 index 0000000..de5a3fd --- /dev/null +++ b/net/http/http_network_transaction_ssl_unittest.cc @@ -0,0 +1,292 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "net/base/net_util.h" +#include "net/base/request_priority.h" +#include "net/dns/mock_host_resolver.h" +#include "net/http/http_auth_handler_mock.h" +#include "net/http/http_network_session.h" +#include "net/http/http_network_transaction.h" +#include "net/http/http_request_info.h" +#include "net/http/http_server_properties_impl.h" +#include "net/http/transport_security_state.h" +#include "net/proxy/proxy_service.h" +#include "net/socket/socket_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +namespace { + +class TLS10SSLConfigService : public SSLConfigService { + public: + TLS10SSLConfigService() { + ssl_config_.version_min = SSL_PROTOCOL_VERSION_SSL3; + ssl_config_.version_max = SSL_PROTOCOL_VERSION_TLS1; + } + + virtual void GetSSLConfig(SSLConfig* config) OVERRIDE { + *config = ssl_config_; + } + + private: + virtual ~TLS10SSLConfigService() {} + + SSLConfig ssl_config_; +}; + +class TLS11SSLConfigService : public SSLConfigService { + public: + TLS11SSLConfigService() { + ssl_config_.version_min = SSL_PROTOCOL_VERSION_SSL3; + ssl_config_.version_max = SSL_PROTOCOL_VERSION_TLS1_1; + } + + virtual void GetSSLConfig(SSLConfig* config) OVERRIDE { + *config = ssl_config_; + } + + private: + virtual ~TLS11SSLConfigService() {} + + SSLConfig ssl_config_; +}; + +} // namespace + +class HttpNetworkTransactionSSLTest : public testing::Test { + protected: + virtual void SetUp() { + ssl_config_service_ = new TLS10SSLConfigService; + session_params_.ssl_config_service = ssl_config_service_.get(); + + auth_handler_factory_.reset(new HttpAuthHandlerMock::Factory()); + session_params_.http_auth_handler_factory = auth_handler_factory_.get(); + + proxy_service_.reset(ProxyService::CreateDirect()); + session_params_.proxy_service = proxy_service_.get(); + + session_params_.client_socket_factory = &mock_socket_factory_; + session_params_.host_resolver = &mock_resolver_; + session_params_.http_server_properties = &http_server_properties_; + session_params_.transport_security_state = &transport_security_state_; + } + + HttpRequestInfo* GetRequestInfo(std::string url) { + HttpRequestInfo* request_info = new HttpRequestInfo; + request_info->url = GURL(url); + request_info->method = "GET"; + return request_info; + } + + SSLConfig& GetServerSSLConfig(HttpNetworkTransaction* trans) { + return trans->server_ssl_config_; + } + + scoped_refptr<SSLConfigService> ssl_config_service_; + scoped_ptr<HttpAuthHandlerMock::Factory> auth_handler_factory_; + scoped_ptr<ProxyService> proxy_service_; + + MockClientSocketFactory mock_socket_factory_; + MockHostResolver mock_resolver_; + HttpServerPropertiesImpl http_server_properties_; + TransportSecurityState transport_security_state_; + HttpNetworkSession::Params session_params_; +}; + +// Tests that HttpNetworkTransaction does not attempt to +// fallback to SSL 3.0 when a TLS 1.0 handshake fails and: +// * the site is pinned to the Google pin list (indicating that +// it is a Google site); +// * unrestricted SSL 3.0 fallback is disabled. +TEST_F(HttpNetworkTransactionSSLTest, SSL3FallbackDisabled_Google) { + // |ssl_data1| is for the first handshake (TLS 1.0), which will fail for + // protocol reasons (e.g., simulating a version rollback attack). + // Because unrestricted SSL 3.0 fallback is disabled, only this simulated + // SSL handshake is consumed. + SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_PROTOCOL_ERROR); + mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data1); + StaticSocketDataProvider data1(NULL, 0, NULL, 0); + mock_socket_factory_.AddSocketDataProvider(&data1); + + // This extra handshake, which should be unconsumed, is provided to ensure + // that even if the behaviour being tested here ever breaks (and Google + // properties begin SSL 3.0 fallbacks), this test will not crash (and bring + // down all of net_unittests), but it will fail gracefully. + SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR); + mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data2); + StaticSocketDataProvider data2(NULL, 0, NULL, 0); + mock_socket_factory_.AddSocketDataProvider(&data2); + + scoped_refptr<HttpNetworkSession> session( + new HttpNetworkSession(session_params_)); + scoped_ptr<HttpNetworkTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); + + TestCompletionCallback callback; + // This will consume only |ssl_data1|. |ssl_data2| will not be consumed. + int rv = callback.GetResult( + trans->Start(GetRequestInfo("https://www.google.com/"), + callback.callback(), BoundNetLog())); + EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, rv); + + SocketDataProviderArray<SocketDataProvider>& mock_data = + mock_socket_factory_.mock_data(); + // Confirms that only |ssl_data1| is consumed. + EXPECT_EQ(1u, mock_data.next_index()); + + SSLConfig& ssl_config = GetServerSSLConfig(trans.get()); + // |version_max| never fallbacks to SSLv3 for Google properties. + EXPECT_EQ(SSL_PROTOCOL_VERSION_TLS1, ssl_config.version_max); + EXPECT_FALSE(ssl_config.version_fallback); +} + +// Tests that HttpNetworkTransaction attempts to fallback to SSL 3.0 +// when a TLS 1.0 handshake fails and: +// * the site is pinned to the Google pin list (indicating that +// it is a Google site); +// * unrestricted SSL 3.0 fallback is enabled. +TEST_F(HttpNetworkTransactionSSLTest, SSL3FallbackEnabled_Google) { + // |ssl_data1| is for the first handshake (TLS 1.0), which will fail + // for protocol reasons (e.g., simulating a version rollback attack). + SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_PROTOCOL_ERROR); + mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data1); + StaticSocketDataProvider data1(NULL, 0, NULL, 0); + mock_socket_factory_.AddSocketDataProvider(&data1); + + // |ssl_data2| contains the handshake result for a SSL 3.0 + // handshake which will be attempted after the TLS 1.0 + // handshake fails. + SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR); + mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data2); + StaticSocketDataProvider data2(NULL, 0, NULL, 0); + mock_socket_factory_.AddSocketDataProvider(&data2); + + scoped_refptr<HttpNetworkSession> session( + new HttpNetworkSession(session_params_)); + scoped_ptr<HttpNetworkTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); + + SSLConfig& ssl_config = GetServerSSLConfig(trans.get()); + ssl_config.unrestricted_ssl3_fallback_enabled = true; + + TestCompletionCallback callback; + // This will consume |ssl_data1| and |ssl_data2|. + int rv = callback.GetResult( + trans->Start(GetRequestInfo("https://www.google.com/"), + callback.callback(), BoundNetLog())); + EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, rv); + + SocketDataProviderArray<SocketDataProvider>& mock_data = + mock_socket_factory_.mock_data(); + // Confirms that both |ssl_data1| and |ssl_data2| are consumed. + EXPECT_EQ(2u, mock_data.next_index()); + + // |version_max| fallbacks to SSL 3.0 for Google properties when + // |unrestricted_ssl3_fallback_enabled| is true. + EXPECT_EQ(SSL_PROTOCOL_VERSION_SSL3, ssl_config.version_max); + EXPECT_TRUE(ssl_config.version_fallback); +} + +// Tests that HttpNetworkTransaction attempts to fallback to SSL 3.0 +// when a TLS 1.0 handshake fails and the site is not a Google domain, +// even if unrestricted SSL 3.0 fallback is disabled. +// TODO(thaidn): revise the above comment and this test when the +// SSL 3.0 fallback experiment is applied for non-Google domains. +TEST_F(HttpNetworkTransactionSSLTest, SSL3FallbackDisabled_Paypal) { + // |ssl_data1| is for the first handshake (TLS 1.0), which will fail + // for protocol reasons (e.g., simulating a version rollback attack). + SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_PROTOCOL_ERROR); + mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data1); + StaticSocketDataProvider data1(NULL, 0, NULL, 0); + mock_socket_factory_.AddSocketDataProvider(&data1); + + // |ssl_data2| contains the handshake result for a SSL 3.0 + // handshake which will be attempted after the TLS 1.0 + // handshake fails. + SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR); + mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data2); + StaticSocketDataProvider data2(NULL, 0, NULL, 0); + mock_socket_factory_.AddSocketDataProvider(&data2); + + scoped_refptr<HttpNetworkSession> session( + new HttpNetworkSession(session_params_)); + scoped_ptr<HttpNetworkTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); + + TestCompletionCallback callback; + // This will consume |ssl_data1| and |ssl_data2|. + int rv = callback.GetResult( + trans->Start(GetRequestInfo("https://www.paypal.com/"), + callback.callback(), BoundNetLog())); + EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, rv); + + SocketDataProviderArray<SocketDataProvider>& mock_data = + mock_socket_factory_.mock_data(); + // Confirms that both |ssl_data1| and |ssl_data2| are consumed. + EXPECT_EQ(2u, mock_data.next_index()); + + SSLConfig& ssl_config = GetServerSSLConfig(trans.get()); + // |version_max| fallbacks to SSL 3.0. + EXPECT_EQ(SSL_PROTOCOL_VERSION_SSL3, ssl_config.version_max); + EXPECT_TRUE(ssl_config.version_fallback); +} + +// Tests that HttpNetworkTransaction attempts to fallback from +// TLS 1.1 to TLS 1.0, then from TLS 1.0 to SSL 3.0. +TEST_F(HttpNetworkTransactionSSLTest, SSLFallback) { + ssl_config_service_ = new TLS11SSLConfigService; + session_params_.ssl_config_service = ssl_config_service_.get(); + // |ssl_data1| is for the first handshake (TLS 1.1), which will fail + // for protocol reasons (e.g., simulating a version rollback attack). + SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_PROTOCOL_ERROR); + mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data1); + StaticSocketDataProvider data1(NULL, 0, NULL, 0); + mock_socket_factory_.AddSocketDataProvider(&data1); + + // |ssl_data2| contains the handshake result for a TLS 1.0 + // handshake which will be attempted after the TLS 1.1 + // handshake fails. + SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR); + mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data2); + StaticSocketDataProvider data2(NULL, 0, NULL, 0); + mock_socket_factory_.AddSocketDataProvider(&data2); + + // |ssl_data3| contains the handshake result for a SSL 3.0 + // handshake which will be attempted after the TLS 1.0 + // handshake fails. + SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR); + mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data3); + StaticSocketDataProvider data3(NULL, 0, NULL, 0); + mock_socket_factory_.AddSocketDataProvider(&data3); + + scoped_refptr<HttpNetworkSession> session( + new HttpNetworkSession(session_params_)); + scoped_ptr<HttpNetworkTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); + + TestCompletionCallback callback; + // This will consume |ssl_data1|, |ssl_data2| and |ssl_data3|. + int rv = callback.GetResult( + trans->Start(GetRequestInfo("https://www.paypal.com/"), + callback.callback(), BoundNetLog())); + EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, rv); + + SocketDataProviderArray<SocketDataProvider>& mock_data = + mock_socket_factory_.mock_data(); + // Confirms that |ssl_data1|, |ssl_data2| and |ssl_data3| are consumed. + EXPECT_EQ(3u, mock_data.next_index()); + + SSLConfig& ssl_config = GetServerSSLConfig(trans.get()); + // |version_max| fallbacks to SSL 3.0. + EXPECT_EQ(SSL_PROTOCOL_VERSION_SSL3, ssl_config.version_max); + EXPECT_TRUE(ssl_config.version_fallback); +} + +} // namespace net + |