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()))),
49 /*stream_factory=*/nullptr,
50 /*crypto_client_stream_factory=*/nullptr,
51 &transport_security_state_
,
52 make_scoped_ptr((QuicServerInfo
*)nullptr),
53 QuicServerId(kServerHostname
,
56 PRIVACY_MODE_DISABLED
),
60 base::TimeTicks::Now(),
61 base::ThreadTaskRunnerHandle::Get().get(),
63 session_
.Initialize();
64 // Advance the time, because timers do not like uninitialized times.
65 connection_
->AdvanceTime(QuicTime::Delta::FromSeconds(1));
68 void TearDown() override
{
69 session_
.CloseSessionOnError(ERR_ABORTED
, QUIC_INTERNAL_ERROR
);
72 scoped_ptr
<DatagramClientSocket
> GetSocket() {
73 socket_factory_
.AddSocketDataProvider(&socket_data_
);
74 return socket_factory_
.CreateDatagramClientSocket(
75 DatagramSocket::DEFAULT_BIND
, base::Bind(&base::RandInt
),
76 &net_log_
, NetLog::Source());
79 void CompleteCryptoHandshake() {
80 ASSERT_EQ(ERR_IO_PENDING
,
81 session_
.CryptoConnect(false, callback_
.callback()));
82 CryptoTestUtils::HandshakeWithFakeServer(
83 connection_
, session_
.GetCryptoStream());
84 ASSERT_EQ(OK
, callback_
.WaitForResult());
87 PacketSavingConnection
* connection_
;
89 MockClientSocketFactory socket_factory_
;
90 StaticSocketDataProvider socket_data_
;
91 TransportSecurityState transport_security_state_
;
92 QuicClientSession session_
;
95 QuicConnectionVisitorInterface
* visitor_
;
96 TestCompletionCallback callback_
;
97 QuicCryptoClientConfig crypto_config_
;
100 INSTANTIATE_TEST_CASE_P(Tests
, QuicClientSessionTest
,
101 ::testing::ValuesIn(QuicSupportedVersions()));
103 TEST_P(QuicClientSessionTest
, CryptoConnect
) {
104 CompleteCryptoHandshake();
107 TEST_P(QuicClientSessionTest
, MaxNumStreams
) {
108 CompleteCryptoHandshake();
110 std::vector
<QuicReliableClientStream
*> streams
;
111 for (size_t i
= 0; i
< kDefaultMaxStreamsPerConnection
; i
++) {
112 QuicReliableClientStream
* stream
= session_
.CreateOutgoingDataStream();
114 streams
.push_back(stream
);
116 EXPECT_FALSE(session_
.CreateOutgoingDataStream());
118 // Close a stream and ensure I can now open a new one.
119 session_
.CloseStream(streams
[0]->id());
120 EXPECT_TRUE(session_
.CreateOutgoingDataStream());
123 TEST_P(QuicClientSessionTest
, MaxNumStreamsViaRequest
) {
124 CompleteCryptoHandshake();
126 std::vector
<QuicReliableClientStream
*> streams
;
127 for (size_t i
= 0; i
< kDefaultMaxStreamsPerConnection
; i
++) {
128 QuicReliableClientStream
* stream
= session_
.CreateOutgoingDataStream();
130 streams
.push_back(stream
);
133 QuicReliableClientStream
* stream
;
134 QuicClientSession::StreamRequest stream_request
;
135 TestCompletionCallback callback
;
136 ASSERT_EQ(ERR_IO_PENDING
,
137 stream_request
.StartRequest(session_
.GetWeakPtr(), &stream
,
138 callback
.callback()));
140 // Close a stream and ensure I can now open a new one.
141 session_
.CloseStream(streams
[0]->id());
142 ASSERT_TRUE(callback
.have_result());
143 EXPECT_EQ(OK
, callback
.WaitForResult());
144 EXPECT_TRUE(stream
!= nullptr);
147 TEST_P(QuicClientSessionTest
, GoAwayReceived
) {
148 CompleteCryptoHandshake();
150 // After receiving a GoAway, I should no longer be able to create outgoing
152 session_
.OnGoAway(QuicGoAwayFrame(QUIC_PEER_GOING_AWAY
, 1u, "Going away."));
153 EXPECT_EQ(nullptr, session_
.CreateOutgoingDataStream());
156 TEST_P(QuicClientSessionTest
, CanPool
) {
157 // Load a cert that is valid for:
162 ProofVerifyDetailsChromium details
;
163 details
.cert_verify_result
.verified_cert
=
164 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
165 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
167 session_
.OnProofVerifyDetailsAvailable(details
);
168 CompleteCryptoHandshake();
170 EXPECT_TRUE(session_
.CanPool("www.example.org", PRIVACY_MODE_DISABLED
));
171 EXPECT_FALSE(session_
.CanPool("www.example.org", PRIVACY_MODE_ENABLED
));
172 EXPECT_TRUE(session_
.CanPool("mail.example.org", PRIVACY_MODE_DISABLED
));
173 EXPECT_TRUE(session_
.CanPool("mail.example.com", PRIVACY_MODE_DISABLED
));
174 EXPECT_FALSE(session_
.CanPool("mail.google.com", PRIVACY_MODE_DISABLED
));
177 TEST_P(QuicClientSessionTest
, ConnectionPooledWithTlsChannelId
) {
178 // Load a cert that is valid for:
183 ProofVerifyDetailsChromium details
;
184 details
.cert_verify_result
.verified_cert
=
185 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
186 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
188 session_
.OnProofVerifyDetailsAvailable(details
);
189 CompleteCryptoHandshake();
190 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
192 EXPECT_TRUE(session_
.CanPool("www.example.org", PRIVACY_MODE_DISABLED
));
193 EXPECT_TRUE(session_
.CanPool("mail.example.org", PRIVACY_MODE_DISABLED
));
194 EXPECT_FALSE(session_
.CanPool("mail.example.com", PRIVACY_MODE_DISABLED
));
195 EXPECT_FALSE(session_
.CanPool("mail.google.com", PRIVACY_MODE_DISABLED
));
198 TEST_P(QuicClientSessionTest
, ConnectionNotPooledWithDifferentPin
) {
199 uint8 primary_pin
= 1;
200 uint8 backup_pin
= 2;
202 AddPin(&transport_security_state_
, "mail.example.org", primary_pin
,
205 ProofVerifyDetailsChromium details
;
206 details
.cert_verify_result
.verified_cert
=
207 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
208 details
.cert_verify_result
.is_issued_by_known_root
= true;
209 details
.cert_verify_result
.public_key_hashes
.push_back(
210 GetTestHashValue(bad_pin
));
212 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
214 session_
.OnProofVerifyDetailsAvailable(details
);
215 CompleteCryptoHandshake();
216 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
218 EXPECT_FALSE(session_
.CanPool("mail.example.org", PRIVACY_MODE_DISABLED
));
221 TEST_P(QuicClientSessionTest
, ConnectionPooledWithMatchingPin
) {
222 uint8 primary_pin
= 1;
223 uint8 backup_pin
= 2;
224 AddPin(&transport_security_state_
, "mail.example.org", primary_pin
,
227 ProofVerifyDetailsChromium details
;
228 details
.cert_verify_result
.verified_cert
=
229 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
230 details
.cert_verify_result
.is_issued_by_known_root
= true;
231 details
.cert_verify_result
.public_key_hashes
.push_back(
232 GetTestHashValue(primary_pin
));
234 ASSERT_TRUE(details
.cert_verify_result
.verified_cert
.get());
236 session_
.OnProofVerifyDetailsAvailable(details
);
237 CompleteCryptoHandshake();
238 QuicClientSessionPeer::SetChannelIDSent(&session_
, true);
240 EXPECT_TRUE(session_
.CanPool("mail.example.org", PRIVACY_MODE_DISABLED
));