| Index: net/http/http_network_transaction_ssl_unittest.cc
|
| 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 0000000000000000000000000000000000000000..b2a81713c5f4462d2fa51c9f49bf084cf30bf20a
|
| --- /dev/null
|
| +++ b/net/http/http_network_transaction_ssl_unittest.cc
|
| @@ -0,0 +1,224 @@
|
| +// 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 TLS1OnlySSLConfigService : public SSLConfigService {
|
| + public:
|
| + TLS1OnlySSLConfigService() {
|
| + 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 ~TLS1OnlySSLConfigService() {}
|
| +
|
| + SSLConfig ssl_config_;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +class HttpNetworkTransactionSSLTest : public testing::Test {
|
| + protected:
|
| + virtual void SetUp() {
|
| + ssl_config_service_ = new TLS1OnlySSLConfigService;
|
| + 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);
|
| +// * SSL 3.0 fallback is disabled.
|
| +TEST_F(HttpNetworkTransactionSSLTest, SSL3VersionFallbackDisabled_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 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);
|
| +// * SSL 3.0 fallback is enabled.
|
| +TEST_F(HttpNetworkTransactionSSLTest, SSL3VersionFallbackEnabled_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.ssl3_version_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
|
| + // |ssl3_version_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 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, SSL3VersionFallbackDisabled_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);
|
| +}
|
| +
|
| +} // namespace net
|
| +
|
|
|