Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(418)

Unified Diff: net/http/http_network_transaction_unittest.cc

Issue 1074193003: Verify alternative server certificate validity for origin. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Re: comments #7. Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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());

Powered by Google App Engine
This is Rietveld 408576698