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()); |