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. 4 5#include "net/quic/quic_client_session.h" 6 7#include <vector> 8 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" 31 32using testing::_; 33 34namespace net { 35namespace test { 36namespace { 37 38const char kServerHostname[] = "www.example.org"; 39const uint16 kServerPort = 80; 40 41class QuicClientSessionTest : public ::testing::TestWithParam<QuicVersion> { 42 protected: 43 QuicClientSessionTest() 44 : connection_( 45 new PacketSavingConnection(false, SupportedVersions(GetParam()))), 46 session_(connection_, GetSocket().Pass(), NULL, 47 &transport_security_state_, 48 make_scoped_ptr((QuicServerInfo*)NULL), DefaultQuicConfig(), 49 base::MessageLoop::current()->message_loop_proxy().get(), 50 &net_log_) { 51 session_.InitializeSession(QuicServerId(kServerHostname, kServerPort, false, 52 PRIVACY_MODE_DISABLED), 53 &crypto_config_, NULL); 54 session_.config()->SetDefaults(); 55 crypto_config_.SetDefaults(); 56 } 57 58 virtual void TearDown() OVERRIDE { 59 session_.CloseSessionOnError(ERR_ABORTED); 60 } 61 62 scoped_ptr<DatagramClientSocket> GetSocket() { 63 socket_factory_.AddSocketDataProvider(&socket_data_); 64 return socket_factory_.CreateDatagramClientSocket( 65 DatagramSocket::DEFAULT_BIND, base::Bind(&base::RandInt), 66 &net_log_, NetLog::Source()); 67 } 68 69 void CompleteCryptoHandshake() { 70 ASSERT_EQ(ERR_IO_PENDING, 71 session_.CryptoConnect(false, callback_.callback())); 72 CryptoTestUtils::HandshakeWithFakeServer( 73 connection_, session_.GetCryptoStream()); 74 ASSERT_EQ(OK, callback_.WaitForResult()); 75 } 76 77 PacketSavingConnection* connection_; 78 CapturingNetLog net_log_; 79 MockClientSocketFactory socket_factory_; 80 StaticSocketDataProvider socket_data_; 81 TransportSecurityState transport_security_state_; 82 QuicClientSession session_; 83 MockClock clock_; 84 MockRandom random_; 85 QuicConnectionVisitorInterface* visitor_; 86 TestCompletionCallback callback_; 87 QuicCryptoClientConfig crypto_config_; 88}; 89 90INSTANTIATE_TEST_CASE_P(Tests, QuicClientSessionTest, 91 ::testing::ValuesIn(QuicSupportedVersions())); 92 93TEST_P(QuicClientSessionTest, CryptoConnect) { 94 CompleteCryptoHandshake(); 95} 96 97TEST_P(QuicClientSessionTest, MaxNumStreams) { 98 CompleteCryptoHandshake(); 99 100 std::vector<QuicReliableClientStream*> streams; 101 for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; i++) { 102 QuicReliableClientStream* stream = session_.CreateOutgoingDataStream(); 103 EXPECT_TRUE(stream); 104 streams.push_back(stream); 105 } 106 EXPECT_FALSE(session_.CreateOutgoingDataStream()); 107 108 // Close a stream and ensure I can now open a new one. 109 session_.CloseStream(streams[0]->id()); 110 EXPECT_TRUE(session_.CreateOutgoingDataStream()); 111} 112 113TEST_P(QuicClientSessionTest, MaxNumStreamsViaRequest) { 114 CompleteCryptoHandshake(); 115 116 std::vector<QuicReliableClientStream*> streams; 117 for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; i++) { 118 QuicReliableClientStream* stream = session_.CreateOutgoingDataStream(); 119 EXPECT_TRUE(stream); 120 streams.push_back(stream); 121 } 122 123 QuicReliableClientStream* stream; 124 QuicClientSession::StreamRequest stream_request; 125 TestCompletionCallback callback; 126 ASSERT_EQ(ERR_IO_PENDING, 127 stream_request.StartRequest(session_.GetWeakPtr(), &stream, 128 callback.callback())); 129 130 // Close a stream and ensure I can now open a new one. 131 session_.CloseStream(streams[0]->id()); 132 ASSERT_TRUE(callback.have_result()); 133 EXPECT_EQ(OK, callback.WaitForResult()); 134 EXPECT_TRUE(stream != NULL); 135} 136 137TEST_P(QuicClientSessionTest, GoAwayReceived) { 138 CompleteCryptoHandshake(); 139 140 // After receiving a GoAway, I should no longer be able to create outgoing 141 // streams. 142 session_.OnGoAway(QuicGoAwayFrame(QUIC_PEER_GOING_AWAY, 1u, "Going away.")); 143 EXPECT_EQ(NULL, session_.CreateOutgoingDataStream()); 144} 145 146TEST_P(QuicClientSessionTest, CanPool) { 147 // Load a cert that is valid for: 148 // www.example.org 149 // mail.example.org 150 // www.example.com 151 152 ProofVerifyDetailsChromium details; 153 details.cert_verify_result.verified_cert = 154 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem"); 155 ASSERT_TRUE(details.cert_verify_result.verified_cert.get()); 156 157 session_.OnProofVerifyDetailsAvailable(details); 158 CompleteCryptoHandshake(); 159 160 161 EXPECT_TRUE(session_.CanPool("www.example.org")); 162 EXPECT_TRUE(session_.CanPool("mail.example.org")); 163 EXPECT_TRUE(session_.CanPool("mail.example.com")); 164 EXPECT_FALSE(session_.CanPool("mail.google.com")); 165} 166 167TEST_P(QuicClientSessionTest, ConnectionPooledWithTlsChannelId) { 168 // Load a cert that is valid for: 169 // www.example.org 170 // mail.example.org 171 // www.example.com 172 173 ProofVerifyDetailsChromium details; 174 details.cert_verify_result.verified_cert = 175 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem"); 176 ASSERT_TRUE(details.cert_verify_result.verified_cert.get()); 177 178 session_.OnProofVerifyDetailsAvailable(details); 179 CompleteCryptoHandshake(); 180 QuicClientSessionPeer::SetChannelIDSent(&session_, true); 181 182 EXPECT_TRUE(session_.CanPool("www.example.org")); 183 EXPECT_TRUE(session_.CanPool("mail.example.org")); 184 EXPECT_FALSE(session_.CanPool("mail.example.com")); 185 EXPECT_FALSE(session_.CanPool("mail.google.com")); 186} 187 188TEST_P(QuicClientSessionTest, ConnectionNotPooledWithDifferentPin) { 189 uint8 primary_pin = 1; 190 uint8 backup_pin = 2; 191 uint8 bad_pin = 3; 192 AddPin(&transport_security_state_, "mail.example.org", primary_pin, 193 backup_pin); 194 195 ProofVerifyDetailsChromium details; 196 details.cert_verify_result.verified_cert = 197 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem"); 198 details.cert_verify_result.is_issued_by_known_root = true; 199 details.cert_verify_result.public_key_hashes.push_back( 200 GetTestHashValue(bad_pin)); 201 202 ASSERT_TRUE(details.cert_verify_result.verified_cert.get()); 203 204 session_.OnProofVerifyDetailsAvailable(details); 205 CompleteCryptoHandshake(); 206 QuicClientSessionPeer::SetChannelIDSent(&session_, true); 207 208 EXPECT_FALSE(session_.CanPool("mail.example.org")); 209} 210 211TEST_P(QuicClientSessionTest, ConnectionPooledWithMatchingPin) { 212 uint8 primary_pin = 1; 213 uint8 backup_pin = 2; 214 AddPin(&transport_security_state_, "mail.example.org", primary_pin, 215 backup_pin); 216 217 ProofVerifyDetailsChromium details; 218 details.cert_verify_result.verified_cert = 219 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem"); 220 details.cert_verify_result.is_issued_by_known_root = true; 221 details.cert_verify_result.public_key_hashes.push_back( 222 GetTestHashValue(primary_pin)); 223 224 ASSERT_TRUE(details.cert_verify_result.verified_cert.get()); 225 226 session_.OnProofVerifyDetailsAvailable(details); 227 CompleteCryptoHandshake(); 228 QuicClientSessionPeer::SetChannelIDSent(&session_, true); 229 230 EXPECT_TRUE(session_.CanPool("mail.example.org")); 231} 232 233} // namespace 234} // namespace test 235} // namespace net 236