1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/quic/quic_client_session.h"
9 #include "base/base64.h"
10 #include "base/files/file_path.h"
11 #include "base/rand_util.h"
12 #include "net/base/capturing_net_log.h"
13 #include "net/base/test_completion_callback.h"
14 #include "net/base/test_data_directory.h"
15 #include "net/cert/cert_verify_result.h"
16 #include "net/http/transport_security_state.h"
17 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
18 #include "net/quic/crypto/crypto_protocol.h"
19 #include "net/quic/crypto/proof_verifier_chromium.h"
20 #include "net/quic/crypto/quic_decrypter.h"
21 #include "net/quic/crypto/quic_encrypter.h"
22 #include "net/quic/crypto/quic_server_info.h"
23 #include "net/quic/test_tools/crypto_test_utils.h"
24 #include "net/quic/test_tools/quic_client_session_peer.h"
25 #include "net/quic/test_tools/quic_test_utils.h"
26 #include "net/quic/test_tools/simple_quic_framer.h"
27 #include "net/socket/socket_test_util.h"
28 #include "net/spdy/spdy_test_utils.h"
29 #include "net/test/cert_test_util.h"
30 #include "net/udp/datagram_client_socket.h"
38 const char kServerHostname
[] = "www.example.org";
39 const uint16 kServerPort
= 80;
41 class QuicClientSessionTest
: public ::testing::TestWithParam
<QuicVersion
> {
43 QuicClientSessionTest()
45 new PacketSavingConnection(false, SupportedVersions(GetParam()))),
46 session_(connection_
, GetSocket().Pass(), nullptr,
47 &transport_security_state_
,
48 make_scoped_ptr((QuicServerInfo
*)nullptr), DefaultQuicConfig(),
49 base::MessageLoop::current()->message_loop_proxy().get(),
51 session_
.InitializeSession(QuicServerId(kServerHostname
, kServerPort
, false,
52 PRIVACY_MODE_DISABLED
),
53 &crypto_config_
, nullptr);
56 void TearDown() override
{ session_
.CloseSessionOnError(ERR_ABORTED
); }
58 scoped_ptr
<DatagramClientSocket
> GetSocket() {
59 socket_factory_
.AddSocketDataProvider(&socket_data_
);
60 return socket_factory_
.CreateDatagramClientSocket(
61 DatagramSocket::DEFAULT_BIND
, base::Bind(&base::RandInt
),
62 &net_log_
, NetLog::Source());
65 void CompleteCryptoHandshake() {
66 ASSERT_EQ(ERR_IO_PENDING
,
67 session_
.CryptoConnect(false, callback_
.callback()));
68 CryptoTestUtils::HandshakeWithFakeServer(
69 connection_
, session_
.GetCryptoStream());
70 ASSERT_EQ(OK
, callback_
.WaitForResult());
73 PacketSavingConnection
* connection_
;
74 CapturingNetLog net_log_
;
75 MockClientSocketFactory socket_factory_
;
76 StaticSocketDataProvider socket_data_
;
77 TransportSecurityState transport_security_state_
;
78 QuicClientSession session_
;
81 QuicConnectionVisitorInterface
* visitor_
;
82 TestCompletionCallback callback_
;
83 QuicCryptoClientConfig crypto_config_
;
86 INSTANTIATE_TEST_CASE_P(Tests
, QuicClientSessionTest
,
87 ::testing::ValuesIn(QuicSupportedVersions()));
89 TEST_P(QuicClientSessionTest
, CryptoConnect
) {
90 CompleteCryptoHandshake();
93 TEST_P(QuicClientSessionTest
, MaxNumStreams
) {
94 CompleteCryptoHandshake();
96 std::vector
<QuicReliableClientStream
*> streams
;
97 for (size_t i
= 0; i
< kDefaultMaxStreamsPerConnection
; i
++) {
98 QuicReliableClientStream
* stream
= session_
.CreateOutgoingDataStream();
100 streams
.push_back(stream
);
102 EXPECT_FALSE(session_
.CreateOutgoingDataStream());
104 // Close a stream and ensure I can now open a new one.
105 session_
.CloseStream(streams
[0]->id());
106 EXPECT_TRUE(session_
.CreateOutgoingDataStream());
109 TEST_P(QuicClientSessionTest
, MaxNumStreamsViaRequest
) {
110 CompleteCryptoHandshake();
112 std::vector
<QuicReliableClientStream
*> streams
;
113 for (size_t i
= 0; i
< kDefaultMaxStreamsPerConnection
; i
++) {
114 QuicReliableClientStream
* stream
= session_
.CreateOutgoingDataStream();
116 streams
.push_back(stream
);
119 QuicReliableClientStream
* stream
;
120 QuicClientSession::StreamRequest stream_request
;
121 TestCompletionCallback callback
;
122 ASSERT_EQ(ERR_IO_PENDING
,
123 stream_request
.StartRequest(session_
.GetWeakPtr(), &stream
,
124 callback
.callback()));
126 // Close a stream and ensure I can now open a new one.
127 session_
.CloseStream(streams
[0]->id());
128 ASSERT_TRUE(callback
.have_result());
129 EXPECT_EQ(OK
, callback
.WaitForResult());
130 EXPECT_TRUE(stream
!= nullptr);
133 TEST_P(QuicClientSessionTest
, GoAwayReceived
) {
134 CompleteCryptoHandshake();
136 // After receiving a GoAway, I should no longer be able to create outgoing
138 session_
.OnGoAway(QuicGoAwayFrame(QUIC_PEER_GOING_AWAY
, 1u, "Going away."));
139 EXPECT_EQ(nullptr, session_
.CreateOutgoingDataStream());
142 TEST_P(QuicClientSessionTest
, CanPool
) {
143 // Load a cert that is valid for:
148 ProofVerifyDetailsChromium details
;
149 details
.cert_verify_result
.verified_cert
=
150 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
151 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
153 session_
.OnProofVerifyDetailsAvailable(details
);
154 CompleteCryptoHandshake();
157 EXPECT_TRUE(session_
.CanPool("www.example.org"));
158 EXPECT_TRUE(session_
.CanPool("mail.example.org"));
159 EXPECT_TRUE(session_
.CanPool("mail.example.com"));
160 EXPECT_FALSE(session_
.CanPool("mail.google.com"));
163 TEST_P(QuicClientSessionTest
, ConnectionPooledWithTlsChannelId
) {
164 // Load a cert that is valid for:
169 ProofVerifyDetailsChromium details
;
170 details
.cert_verify_result
.verified_cert
=
171 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
172 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
174 session_
.OnProofVerifyDetailsAvailable(details
);
175 CompleteCryptoHandshake();
176 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
178 EXPECT_TRUE(session_
.CanPool("www.example.org"));
179 EXPECT_TRUE(session_
.CanPool("mail.example.org"));
180 EXPECT_FALSE(session_
.CanPool("mail.example.com"));
181 EXPECT_FALSE(session_
.CanPool("mail.google.com"));
184 TEST_P(QuicClientSessionTest
, ConnectionNotPooledWithDifferentPin
) {
185 uint8 primary_pin
= 1;
186 uint8 backup_pin
= 2;
188 AddPin(&transport_security_state_
, "mail.example.org", primary_pin
,
191 ProofVerifyDetailsChromium details
;
192 details
.cert_verify_result
.verified_cert
=
193 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
194 details
.cert_verify_result
.is_issued_by_known_root
= true;
195 details
.cert_verify_result
.public_key_hashes
.push_back(
196 GetTestHashValue(bad_pin
));
198 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
200 session_
.OnProofVerifyDetailsAvailable(details
);
201 CompleteCryptoHandshake();
202 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
204 EXPECT_FALSE(session_
.CanPool("mail.example.org"));
207 TEST_P(QuicClientSessionTest
, ConnectionPooledWithMatchingPin
) {
208 uint8 primary_pin
= 1;
209 uint8 backup_pin
= 2;
210 AddPin(&transport_security_state_
, "mail.example.org", primary_pin
,
213 ProofVerifyDetailsChromium details
;
214 details
.cert_verify_result
.verified_cert
=
215 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
216 details
.cert_verify_result
.is_issued_by_known_root
= true;
217 details
.cert_verify_result
.public_key_hashes
.push_back(
218 GetTestHashValue(primary_pin
));
220 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
222 session_
.OnProofVerifyDetailsAvailable(details
);
223 CompleteCryptoHandshake();
224 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
226 EXPECT_TRUE(session_
.CanPool("mail.example.org"));