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()))),
49 &transport_security_state_
,
50 make_scoped_ptr((QuicServerInfo
*)nullptr),
53 base::MessageLoop::current()->message_loop_proxy().get(),
55 session_
.InitializeSession(QuicServerId(kServerHostname
, kServerPort
,
57 PRIVACY_MODE_DISABLED
),
58 &crypto_config_
, nullptr);
59 // Advance the time, because timers do not like uninitialized times.
60 connection_
->AdvanceTime(QuicTime::Delta::FromSeconds(1));
63 void TearDown() override
{ session_
.CloseSessionOnError(ERR_ABORTED
); }
65 scoped_ptr
<DatagramClientSocket
> GetSocket() {
66 socket_factory_
.AddSocketDataProvider(&socket_data_
);
67 return socket_factory_
.CreateDatagramClientSocket(
68 DatagramSocket::DEFAULT_BIND
, base::Bind(&base::RandInt
),
69 &net_log_
, NetLog::Source());
72 void CompleteCryptoHandshake() {
73 ASSERT_EQ(ERR_IO_PENDING
,
74 session_
.CryptoConnect(false, callback_
.callback()));
75 CryptoTestUtils::HandshakeWithFakeServer(
76 connection_
, session_
.GetCryptoStream());
77 ASSERT_EQ(OK
, callback_
.WaitForResult());
80 PacketSavingConnection
* connection_
;
81 CapturingNetLog net_log_
;
82 MockClientSocketFactory socket_factory_
;
83 StaticSocketDataProvider socket_data_
;
84 TransportSecurityState transport_security_state_
;
85 QuicClientSession session_
;
88 QuicConnectionVisitorInterface
* visitor_
;
89 TestCompletionCallback callback_
;
90 QuicCryptoClientConfig crypto_config_
;
93 INSTANTIATE_TEST_CASE_P(Tests
, QuicClientSessionTest
,
94 ::testing::ValuesIn(QuicSupportedVersions()));
96 TEST_P(QuicClientSessionTest
, CryptoConnect
) {
97 CompleteCryptoHandshake();
100 TEST_P(QuicClientSessionTest
, MaxNumStreams
) {
101 CompleteCryptoHandshake();
103 std::vector
<QuicReliableClientStream
*> streams
;
104 for (size_t i
= 0; i
< kDefaultMaxStreamsPerConnection
; i
++) {
105 QuicReliableClientStream
* stream
= session_
.CreateOutgoingDataStream();
107 streams
.push_back(stream
);
109 EXPECT_FALSE(session_
.CreateOutgoingDataStream());
111 // Close a stream and ensure I can now open a new one.
112 session_
.CloseStream(streams
[0]->id());
113 EXPECT_TRUE(session_
.CreateOutgoingDataStream());
116 TEST_P(QuicClientSessionTest
, MaxNumStreamsViaRequest
) {
117 CompleteCryptoHandshake();
119 std::vector
<QuicReliableClientStream
*> streams
;
120 for (size_t i
= 0; i
< kDefaultMaxStreamsPerConnection
; i
++) {
121 QuicReliableClientStream
* stream
= session_
.CreateOutgoingDataStream();
123 streams
.push_back(stream
);
126 QuicReliableClientStream
* stream
;
127 QuicClientSession::StreamRequest stream_request
;
128 TestCompletionCallback callback
;
129 ASSERT_EQ(ERR_IO_PENDING
,
130 stream_request
.StartRequest(session_
.GetWeakPtr(), &stream
,
131 callback
.callback()));
133 // Close a stream and ensure I can now open a new one.
134 session_
.CloseStream(streams
[0]->id());
135 ASSERT_TRUE(callback
.have_result());
136 EXPECT_EQ(OK
, callback
.WaitForResult());
137 EXPECT_TRUE(stream
!= nullptr);
140 TEST_P(QuicClientSessionTest
, GoAwayReceived
) {
141 CompleteCryptoHandshake();
143 // After receiving a GoAway, I should no longer be able to create outgoing
145 session_
.OnGoAway(QuicGoAwayFrame(QUIC_PEER_GOING_AWAY
, 1u, "Going away."));
146 EXPECT_EQ(nullptr, session_
.CreateOutgoingDataStream());
149 TEST_P(QuicClientSessionTest
, CanPool
) {
150 // Load a cert that is valid for:
155 ProofVerifyDetailsChromium details
;
156 details
.cert_verify_result
.verified_cert
=
157 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
158 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
160 session_
.OnProofVerifyDetailsAvailable(details
);
161 CompleteCryptoHandshake();
163 EXPECT_TRUE(session_
.CanPool("www.example.org", PRIVACY_MODE_DISABLED
));
164 EXPECT_FALSE(session_
.CanPool("www.example.org", PRIVACY_MODE_ENABLED
));
165 EXPECT_TRUE(session_
.CanPool("mail.example.org", PRIVACY_MODE_DISABLED
));
166 EXPECT_TRUE(session_
.CanPool("mail.example.com", PRIVACY_MODE_DISABLED
));
167 EXPECT_FALSE(session_
.CanPool("mail.google.com", PRIVACY_MODE_DISABLED
));
170 TEST_P(QuicClientSessionTest
, ConnectionPooledWithTlsChannelId
) {
171 // Load a cert that is valid for:
176 ProofVerifyDetailsChromium details
;
177 details
.cert_verify_result
.verified_cert
=
178 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
179 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
181 session_
.OnProofVerifyDetailsAvailable(details
);
182 CompleteCryptoHandshake();
183 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
185 EXPECT_TRUE(session_
.CanPool("www.example.org", PRIVACY_MODE_DISABLED
));
186 EXPECT_TRUE(session_
.CanPool("mail.example.org", PRIVACY_MODE_DISABLED
));
187 EXPECT_FALSE(session_
.CanPool("mail.example.com", PRIVACY_MODE_DISABLED
));
188 EXPECT_FALSE(session_
.CanPool("mail.google.com", PRIVACY_MODE_DISABLED
));
191 TEST_P(QuicClientSessionTest
, ConnectionNotPooledWithDifferentPin
) {
192 uint8 primary_pin
= 1;
193 uint8 backup_pin
= 2;
195 AddPin(&transport_security_state_
, "mail.example.org", primary_pin
,
198 ProofVerifyDetailsChromium details
;
199 details
.cert_verify_result
.verified_cert
=
200 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
201 details
.cert_verify_result
.is_issued_by_known_root
= true;
202 details
.cert_verify_result
.public_key_hashes
.push_back(
203 GetTestHashValue(bad_pin
));
205 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
207 session_
.OnProofVerifyDetailsAvailable(details
);
208 CompleteCryptoHandshake();
209 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
211 EXPECT_FALSE(session_
.CanPool("mail.example.org", PRIVACY_MODE_DISABLED
));
214 TEST_P(QuicClientSessionTest
, ConnectionPooledWithMatchingPin
) {
215 uint8 primary_pin
= 1;
216 uint8 backup_pin
= 2;
217 AddPin(&transport_security_state_
, "mail.example.org", primary_pin
,
220 ProofVerifyDetailsChromium details
;
221 details
.cert_verify_result
.verified_cert
=
222 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
223 details
.cert_verify_result
.is_issued_by_known_root
= true;
224 details
.cert_verify_result
.public_key_hashes
.push_back(
225 GetTestHashValue(primary_pin
));
227 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
229 session_
.OnProofVerifyDetailsAvailable(details
);
230 CompleteCryptoHandshake();
231 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
233 EXPECT_TRUE(session_
.CanPool("mail.example.org", PRIVACY_MODE_DISABLED
));