Chromium Code Reviews| Index: net/http/http_network_transaction_unittest.cc |
| diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc |
| index 6c59954575dcda26c39faff24f96a32f756a3b97..023bc4ab4e2769705b519bf58431fa9d12281056 100644 |
| --- a/net/http/http_network_transaction_unittest.cc |
| +++ b/net/http/http_network_transaction_unittest.cc |
| @@ -18,6 +18,7 @@ |
| #include "base/memory/scoped_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/run_loop.h" |
| +#include "base/stl_util.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/test_file_util.h" |
| @@ -30,7 +31,6 @@ |
| #include "net/base/net_errors.h" |
| #include "net/base/request_priority.h" |
| #include "net/base/test_completion_callback.h" |
| -#include "net/base/test_data_directory.h" |
| #include "net/base/upload_bytes_element_reader.h" |
| #include "net/base/upload_file_element_reader.h" |
| #include "net/cert/mock_cert_verifier.h" |
| @@ -72,7 +72,6 @@ |
| #include "net/ssl/ssl_config_service.h" |
| #include "net/ssl/ssl_config_service_defaults.h" |
| #include "net/ssl/ssl_info.h" |
| -#include "net/test/cert_test_util.h" |
| #include "net/websockets/websocket_handshake_stream_base.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "testing/platform_test.h" |
| @@ -9214,6 +9213,7 @@ TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) { |
| SSLSocketDataProvider ssl(ASYNC, OK); |
| ssl.SetNextProto(GetParam()); |
| + ssl.SetCertFromFile("spdy.pem"); |
|
Ryan Hamilton
2015/04/15 21:24:34
Clever!
Bence
2015/04/23 17:17:07
Thanks. Too bad that it was vetoed in https://crr
|
| session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); |
| scoped_ptr<SpdyFrame> req( |
| @@ -9314,6 +9314,7 @@ TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) { |
| SSLSocketDataProvider ssl(ASYNC, OK); |
| ssl.SetNextProto(GetParam()); |
| + ssl.SetCertFromFile("spdy.pem"); |
| session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); |
| scoped_ptr<SpdyFrame> req1( |
| @@ -9549,6 +9550,7 @@ TEST_P(HttpNetworkTransactionTest, |
| SSLSocketDataProvider ssl(ASYNC, OK); |
| ssl.SetNextProto(GetParam()); |
| + ssl.SetCertFromFile("spdy.pem"); |
| session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); |
| scoped_ptr<SpdyFrame> req( |
| @@ -9658,6 +9660,7 @@ TEST_P(HttpNetworkTransactionTest, |
| SSLSocketDataProvider ssl(ASYNC, OK); |
| ssl.SetNextProto(GetParam()); |
| + ssl.SetCertFromFile("spdy.pem"); |
| session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); |
| scoped_ptr<SpdyFrame> req( |
| @@ -10557,6 +10560,7 @@ TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) { |
| SSLSocketDataProvider ssl(ASYNC, OK); |
| ssl.SetNextProto(GetParam()); |
| + ssl.SetCertFromFile("spdy.pem"); |
| MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING); |
| StaticSocketDataProvider hanging_non_alternate_protocol_socket( |
| @@ -11764,6 +11768,158 @@ TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) { |
| EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy); |
| } |
| +class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest { |
| + public: |
| + void Run(bool pooling, bool valid) { |
| + HostPortPair origin(valid ? "mail.example.org" : "invalid.example.org", |
| + 443); |
| + HostPortPair alternative("www.example.org", 443); |
| + |
| + SSLSocketDataProvider ssl(ASYNC, OK); |
| + ssl.SetNextProto(GetParam()); |
| + ssl.SetCertFromFile("spdy_pooling.pem"); |
| + bool common_name_fallback_used; |
| + EXPECT_EQ(valid, ssl.cert->VerifyNameMatch(origin.host(), |
| + &common_name_fallback_used)); |
| + EXPECT_TRUE(ssl.cert->VerifyNameMatch(alternative.host(), |
| + &common_name_fallback_used)); |
| + session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); |
| + |
| + // If pooling, then start a request to alternative first to create a |
| + // SpdySession. |
| + std::string url0 = "https://www.example.org:443"; |
| + // Second request to origin, which has an alternative service, and could |
| + // open a connection to the alternative host or pool to the existing one. |
| + std::string url1("https://"); |
| + url1.append(origin.host()); |
| + url1.append(":443"); |
| + |
| + scoped_ptr<SpdyFrame> req0; |
| + scoped_ptr<SpdyFrame> req1; |
| + scoped_ptr<SpdyFrame> resp0; |
| + scoped_ptr<SpdyFrame> body0; |
| + scoped_ptr<SpdyFrame> resp1; |
| + scoped_ptr<SpdyFrame> body1; |
| + std::vector<MockWrite> writes; |
| + std::vector<MockRead> reads; |
| + |
| + if (pooling) { |
| + req0.reset(spdy_util_.ConstructSpdyGet(url0.c_str(), false, 1, LOWEST)); |
| + req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 3, LOWEST)); |
| + |
| + writes.push_back(CreateMockWrite(*req0, 0)); |
| + writes.push_back(CreateMockWrite(*req1, 3)); |
| + |
| + resp0.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| + body0.reset(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| + resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); |
| + body1.reset(spdy_util_.ConstructSpdyBodyFrame(3, true)); |
| + |
| + reads.push_back(CreateMockRead(*resp0, 1)); |
| + reads.push_back(CreateMockRead(*body0, 2)); |
| + reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 4)); |
| + reads.push_back(CreateMockRead(*resp1, 5)); |
| + reads.push_back(CreateMockRead(*body1, 6)); |
| + reads.push_back(MockRead(ASYNC, OK, 7)); |
| + } else { |
| + req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), false, 1, LOWEST)); |
| + |
| + writes.push_back(CreateMockWrite(*req1, 0)); |
| + |
| + resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); |
| + body1.reset(spdy_util_.ConstructSpdyBodyFrame(1, true)); |
| + |
| + reads.push_back(CreateMockRead(*resp1, 1)); |
| + reads.push_back(CreateMockRead(*body1, 2)); |
| + reads.push_back(MockRead(ASYNC, OK, 3)); |
| + } |
| + |
| + OrderedSocketData data(vector_as_array(&reads), reads.size(), |
| + vector_as_array(&writes), writes.size()); |
| + session_deps_.socket_factory->AddSocketDataProvider(&data); |
| + |
| + // Connection to the origin fails. |
| + MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); |
| + StaticSocketDataProvider data_refused; |
| + data_refused.set_connect_data(mock_connect); |
| + session_deps_.socket_factory->AddSocketDataProvider(&data_refused); |
| + |
| + session_deps_.use_alternate_protocols = true; |
| + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); |
| + base::WeakPtr<HttpServerProperties> http_server_properties = |
| + session->http_server_properties(); |
| + AlternativeService alternative_service( |
| + AlternateProtocolFromNextProto(GetParam()), alternative); |
| + http_server_properties->SetAlternativeService(origin, alternative_service, |
| + 1.0); |
| + |
| + // First request to alternative. |
| + if (pooling) { |
| + scoped_ptr<HttpTransaction> trans0( |
| + new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); |
| + HttpRequestInfo request0; |
| + request0.method = "GET"; |
| + request0.url = GURL(url0); |
| + request0.load_flags = 0; |
| + TestCompletionCallback callback0; |
| + |
| + int rv = trans0->Start(&request0, callback0.callback(), BoundNetLog()); |
| + EXPECT_EQ(ERR_IO_PENDING, rv); |
| + rv = callback0.WaitForResult(); |
| + EXPECT_EQ(OK, rv); |
| + } |
| + |
| + // Second request to origin. |
| + scoped_ptr<HttpTransaction> trans1( |
| + new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); |
| + HttpRequestInfo request1; |
| + request1.method = "GET"; |
| + request1.url = GURL(url1); |
| + request1.load_flags = 0; |
| + TestCompletionCallback callback1; |
| + |
| + int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog()); |
| + EXPECT_EQ(ERR_IO_PENDING, rv); |
| + rv = callback1.WaitForResult(); |
| + if (valid) { |
| + EXPECT_EQ(OK, rv); |
| + } else { |
| + if (pooling) { |
| + EXPECT_EQ(ERR_CONNECTION_REFUSED, rv); |
| + } else { |
| + EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN, rv); |
| + } |
| + } |
| + } |
| +}; |
| + |
| +INSTANTIATE_TEST_CASE_P(NextProto, |
| + AltSvcCertificateVerificationTest, |
| + testing::Values(kProtoSPDY31, |
| + kProtoSPDY4_14, |
| + kProtoSPDY4)); |
| + |
| +// The alternative service host must exhibit a certificate that is valid for the |
| +// origin host. Test that this is enforced when pooling to an existing |
| +// connection. |
| +TEST_P(AltSvcCertificateVerificationTest, PoolingValid) { |
| + Run(true, true); |
| +} |
| + |
| +TEST_P(AltSvcCertificateVerificationTest, PoolingInvalid) { |
| + Run(true, false); |
| +} |
| + |
| +// The alternative service host must exhibit a certificate that is valid for the |
| +// origin host. Test that this is enforced when opening a new connection. |
| +TEST_P(AltSvcCertificateVerificationTest, NewConnectionValid) { |
| + Run(false, true); |
| +} |
| + |
| +TEST_P(AltSvcCertificateVerificationTest, NewConnectionInvalid) { |
| + Run(false, false); |
| +} |
| + |
| TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) { |
| const std::string https_url = "https://www.google.com:8080/"; |
| const std::string http_url = "http://www.google.com:8080/"; |
| @@ -11941,18 +12097,13 @@ TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) { |
| session_deps_.proxy_service.reset(new ProxyService( |
| new ProxyConfigServiceFixed(proxy_config), nullptr, NULL)); |
| + SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy |
| + ssl1.SetNextProto(GetParam()); |
| // Load a valid cert. Note, that this does not need to |
| // be valid for proxy because the MockSSLClientSocket does |
| // not actually verify it. But SpdySession will use this |
| // to see if it is valid for the new origin |
| - base::FilePath certs_dir = GetTestCertsDirectory(); |
| - scoped_refptr<X509Certificate> server_cert( |
| - ImportCertFromFile(certs_dir, "ok_cert.pem")); |
| - ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert.get()); |
| - |
| - SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy |
| - ssl1.SetNextProto(GetParam()); |
| - ssl1.cert = server_cert; |
| + ssl1.SetCertFromFile("ok_cert.pem"); |
| session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1); |
| session_deps_.deterministic_socket_factory->AddSocketDataProvider( |
| data1.get()); |