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 "base/thread_task_runner_handle.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/log/test_net_log.h"
18 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
19 #include "net/quic/crypto/crypto_protocol.h"
20 #include "net/quic/crypto/proof_verifier_chromium.h"
21 #include "net/quic/crypto/quic_decrypter.h"
22 #include "net/quic/crypto/quic_encrypter.h"
23 #include "net/quic/crypto/quic_server_info.h"
24 #include "net/quic/test_tools/crypto_test_utils.h"
25 #include "net/quic/test_tools/quic_client_session_peer.h"
26 #include "net/quic/test_tools/quic_test_utils.h"
27 #include "net/quic/test_tools/simple_quic_framer.h"
28 #include "net/socket/socket_test_util.h"
29 #include "net/spdy/spdy_test_utils.h"
30 #include "net/test/cert_test_util.h"
31 #include "net/udp/datagram_client_socket.h"
39 const char kServerHostname
[] = "www.example.org";
40 const uint16 kServerPort
= 80;
42 class QuicClientSessionTest
: public ::testing::TestWithParam
<QuicVersion
> {
44 QuicClientSessionTest()
45 : connection_(new PacketSavingConnection(Perspective::IS_CLIENT
,
46 SupportedVersions(GetParam()))),
50 &transport_security_state_
,
51 make_scoped_ptr((QuicServerInfo
*)nullptr),
54 base::TimeTicks::Now(),
55 base::ThreadTaskRunnerHandle::Get().get(),
57 session_
.InitializeSession(QuicServerId(kServerHostname
, kServerPort
,
59 PRIVACY_MODE_DISABLED
),
60 &crypto_config_
, nullptr);
61 // Advance the time, because timers do not like uninitialized times.
62 connection_
->AdvanceTime(QuicTime::Delta::FromSeconds(1));
65 void TearDown() override
{
66 session_
.CloseSessionOnError(ERR_ABORTED
, QUIC_INTERNAL_ERROR
);
69 scoped_ptr
<DatagramClientSocket
> GetSocket() {
70 socket_factory_
.AddSocketDataProvider(&socket_data_
);
71 return socket_factory_
.CreateDatagramClientSocket(
72 DatagramSocket::DEFAULT_BIND
, base::Bind(&base::RandInt
),
73 &net_log_
, NetLog::Source());
76 void CompleteCryptoHandshake() {
77 ASSERT_EQ(ERR_IO_PENDING
,
78 session_
.CryptoConnect(false, callback_
.callback()));
79 CryptoTestUtils::HandshakeWithFakeServer(
80 connection_
, session_
.GetCryptoStream());
81 ASSERT_EQ(OK
, callback_
.WaitForResult());
84 PacketSavingConnection
* connection_
;
86 MockClientSocketFactory socket_factory_
;
87 StaticSocketDataProvider socket_data_
;
88 TransportSecurityState transport_security_state_
;
89 QuicClientSession session_
;
92 QuicConnectionVisitorInterface
* visitor_
;
93 TestCompletionCallback callback_
;
94 QuicCryptoClientConfig crypto_config_
;
97 INSTANTIATE_TEST_CASE_P(Tests
, QuicClientSessionTest
,
98 ::testing::ValuesIn(QuicSupportedVersions()));
100 TEST_P(QuicClientSessionTest
, CryptoConnect
) {
101 CompleteCryptoHandshake();
104 TEST_P(QuicClientSessionTest
, MaxNumStreams
) {
105 CompleteCryptoHandshake();
107 std::vector
<QuicReliableClientStream
*> streams
;
108 for (size_t i
= 0; i
< kDefaultMaxStreamsPerConnection
; i
++) {
109 QuicReliableClientStream
* stream
= session_
.CreateOutgoingDataStream();
111 streams
.push_back(stream
);
113 EXPECT_FALSE(session_
.CreateOutgoingDataStream());
115 // Close a stream and ensure I can now open a new one.
116 session_
.CloseStream(streams
[0]->id());
117 EXPECT_TRUE(session_
.CreateOutgoingDataStream());
120 TEST_P(QuicClientSessionTest
, MaxNumStreamsViaRequest
) {
121 CompleteCryptoHandshake();
123 std::vector
<QuicReliableClientStream
*> streams
;
124 for (size_t i
= 0; i
< kDefaultMaxStreamsPerConnection
; i
++) {
125 QuicReliableClientStream
* stream
= session_
.CreateOutgoingDataStream();
127 streams
.push_back(stream
);
130 QuicReliableClientStream
* stream
;
131 QuicClientSession::StreamRequest stream_request
;
132 TestCompletionCallback callback
;
133 ASSERT_EQ(ERR_IO_PENDING
,
134 stream_request
.StartRequest(session_
.GetWeakPtr(), &stream
,
135 callback
.callback()));
137 // Close a stream and ensure I can now open a new one.
138 session_
.CloseStream(streams
[0]->id());
139 ASSERT_TRUE(callback
.have_result());
140 EXPECT_EQ(OK
, callback
.WaitForResult());
141 EXPECT_TRUE(stream
!= nullptr);
144 TEST_P(QuicClientSessionTest
, GoAwayReceived
) {
145 CompleteCryptoHandshake();
147 // After receiving a GoAway, I should no longer be able to create outgoing
149 session_
.OnGoAway(QuicGoAwayFrame(QUIC_PEER_GOING_AWAY
, 1u, "Going away."));
150 EXPECT_EQ(nullptr, session_
.CreateOutgoingDataStream());
153 TEST_P(QuicClientSessionTest
, CanPool
) {
154 // Load a cert that is valid for:
159 ProofVerifyDetailsChromium details
;
160 details
.cert_verify_result
.verified_cert
=
161 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
162 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
164 session_
.OnProofVerifyDetailsAvailable(details
);
165 CompleteCryptoHandshake();
167 EXPECT_TRUE(session_
.CanPool("www.example.org", PRIVACY_MODE_DISABLED
));
168 EXPECT_FALSE(session_
.CanPool("www.example.org", PRIVACY_MODE_ENABLED
));
169 EXPECT_TRUE(session_
.CanPool("mail.example.org", PRIVACY_MODE_DISABLED
));
170 EXPECT_TRUE(session_
.CanPool("mail.example.com", PRIVACY_MODE_DISABLED
));
171 EXPECT_FALSE(session_
.CanPool("mail.google.com", PRIVACY_MODE_DISABLED
));
174 TEST_P(QuicClientSessionTest
, ConnectionPooledWithTlsChannelId
) {
175 // Load a cert that is valid for:
180 ProofVerifyDetailsChromium details
;
181 details
.cert_verify_result
.verified_cert
=
182 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
183 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
185 session_
.OnProofVerifyDetailsAvailable(details
);
186 CompleteCryptoHandshake();
187 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
189 EXPECT_TRUE(session_
.CanPool("www.example.org", PRIVACY_MODE_DISABLED
));
190 EXPECT_TRUE(session_
.CanPool("mail.example.org", PRIVACY_MODE_DISABLED
));
191 EXPECT_FALSE(session_
.CanPool("mail.example.com", PRIVACY_MODE_DISABLED
));
192 EXPECT_FALSE(session_
.CanPool("mail.google.com", PRIVACY_MODE_DISABLED
));
195 TEST_P(QuicClientSessionTest
, ConnectionNotPooledWithDifferentPin
) {
196 uint8 primary_pin
= 1;
197 uint8 backup_pin
= 2;
199 AddPin(&transport_security_state_
, "mail.example.org", primary_pin
,
202 ProofVerifyDetailsChromium details
;
203 details
.cert_verify_result
.verified_cert
=
204 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
205 details
.cert_verify_result
.is_issued_by_known_root
= true;
206 details
.cert_verify_result
.public_key_hashes
.push_back(
207 GetTestHashValue(bad_pin
));
209 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
211 session_
.OnProofVerifyDetailsAvailable(details
);
212 CompleteCryptoHandshake();
213 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
215 EXPECT_FALSE(session_
.CanPool("mail.example.org", PRIVACY_MODE_DISABLED
));
218 TEST_P(QuicClientSessionTest
, ConnectionPooledWithMatchingPin
) {
219 uint8 primary_pin
= 1;
220 uint8 backup_pin
= 2;
221 AddPin(&transport_security_state_
, "mail.example.org", primary_pin
,
224 ProofVerifyDetailsChromium details
;
225 details
.cert_verify_result
.verified_cert
=
226 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
227 details
.cert_verify_result
.is_issued_by_known_root
= true;
228 details
.cert_verify_result
.public_key_hashes
.push_back(
229 GetTestHashValue(primary_pin
));
231 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
233 session_
.OnProofVerifyDetailsAvailable(details
);
234 CompleteCryptoHandshake();
235 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
237 EXPECT_TRUE(session_
.CanPool("mail.example.org", PRIVACY_MODE_DISABLED
));