|  | // 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 "base/memory/scoped_vector.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_TLS1; | 
|  | ssl_config_.version_max = SSL_PROTOCOL_VERSION_TLS1; | 
|  | } | 
|  |  | 
|  | void GetSSLConfig(SSLConfig* config) override { *config = ssl_config_; } | 
|  |  | 
|  | private: | 
|  | ~TLS10SSLConfigService() override {} | 
|  |  | 
|  | SSLConfig ssl_config_; | 
|  | }; | 
|  |  | 
|  | class TLS12SSLConfigService : public SSLConfigService { | 
|  | public: | 
|  | TLS12SSLConfigService() { | 
|  | ssl_config_.version_min = SSL_PROTOCOL_VERSION_TLS1; | 
|  | ssl_config_.version_max = SSL_PROTOCOL_VERSION_TLS1_2; | 
|  | } | 
|  |  | 
|  | void GetSSLConfig(SSLConfig* config) override { *config = ssl_config_; } | 
|  |  | 
|  | private: | 
|  | ~TLS12SSLConfigService() override {} | 
|  |  | 
|  | SSLConfig ssl_config_; | 
|  | }; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | class HttpNetworkTransactionSSLTest : public testing::Test { | 
|  | protected: | 
|  | void SetUp() override { | 
|  | 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_.GetWeakPtr(); | 
|  | session_params_.transport_security_state = &transport_security_state_; | 
|  | } | 
|  |  | 
|  | HttpRequestInfo* GetRequestInfo(const std::string& url) { | 
|  | HttpRequestInfo* request_info = new HttpRequestInfo; | 
|  | request_info->url = GURL(url); | 
|  | request_info->method = "GET"; | 
|  | request_info_vector_.push_back(request_info); | 
|  | 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_; | 
|  | ScopedVector<HttpRequestInfo> request_info_vector_; | 
|  | }; | 
|  |  | 
|  | // Tests that HttpNetworkTransaction attempts to fallback from | 
|  | // TLS 1.2 to TLS 1.1, then from TLS 1.1 to TLS 1.0. | 
|  | TEST_F(HttpNetworkTransactionSSLTest, SSLFallback) { | 
|  | ssl_config_service_ = new TLS12SSLConfigService; | 
|  | session_params_.ssl_config_service = ssl_config_service_.get(); | 
|  | // |ssl_data1| is for the first handshake (TLS 1.2), 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.1 | 
|  | // handshake which will be attempted after the TLS 1.2 | 
|  | // 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 TLS 1.0 | 
|  | // handshake which will be attempted after the TLS 1.1 | 
|  | // 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.get())); | 
|  |  | 
|  | 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 TLS 1.0. | 
|  | EXPECT_EQ(SSL_PROTOCOL_VERSION_TLS1, ssl_config.version_max); | 
|  | EXPECT_TRUE(ssl_config.version_fallback); | 
|  | } | 
|  |  | 
|  | }  // namespace net | 
|  |  |