1 // Copyright (c) 2020 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/third_party/quiche/src/quic/core/tls_chlo_extractor.h"
6 #include <memory>
7
8 #include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h"
9 #include "net/third_party/quiche/src/quic/core/quic_connection.h"
10 #include "net/third_party/quiche/src/quic/core/quic_packet_writer_wrapper.h"
11 #include "net/third_party/quiche/src/quic/core/quic_versions.h"
12 #include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
13 #include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
14 #include "net/third_party/quiche/src/quic/test_tools/first_flight.h"
15 #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
16
17 namespace quic {
18 namespace test {
19 namespace {
20
21 class TlsChloExtractorTest : public QuicTestWithParam<ParsedQuicVersion> {
22 protected:
TlsChloExtractorTest()23 TlsChloExtractorTest() : version_(GetParam()) {}
24
Initialize()25 void Initialize() { packets_ = GetFirstFlightOfPackets(version_, config_); }
26
IngestPackets()27 void IngestPackets() {
28 for (const std::unique_ptr<QuicReceivedPacket>& packet : packets_) {
29 ReceivedPacketInfo packet_info(
30 QuicSocketAddress(TestPeerIPAddress(), kTestPort),
31 QuicSocketAddress(TestPeerIPAddress(), kTestPort), *packet);
32 std::string detailed_error;
33 bool retry_token_present;
34 absl::string_view retry_token;
35 const QuicErrorCode error = QuicFramer::ParsePublicHeaderDispatcher(
36 *packet, /*expected_destination_connection_id_length=*/0,
37 &packet_info.form, &packet_info.long_packet_type,
38 &packet_info.version_flag, &packet_info.use_length_prefix,
39 &packet_info.version_label, &packet_info.version,
40 &packet_info.destination_connection_id,
41 &packet_info.source_connection_id, &retry_token_present, &retry_token,
42 &detailed_error);
43 ASSERT_THAT(error, IsQuicNoError()) << detailed_error;
44 tls_chlo_extractor_.IngestPacket(packet_info.version, packet_info.packet);
45 }
46 packets_.clear();
47 }
48
ValidateChloDetails()49 void ValidateChloDetails() {
50 EXPECT_TRUE(tls_chlo_extractor_.HasParsedFullChlo());
51 std::vector<std::string> alpns = tls_chlo_extractor_.alpns();
52 ASSERT_EQ(alpns.size(), 1u);
53 EXPECT_EQ(alpns[0], AlpnForVersion(version_));
54 EXPECT_EQ(tls_chlo_extractor_.server_name(), TestHostname());
55 }
56
IncreaseSizeOfChlo()57 void IncreaseSizeOfChlo() {
58 // Add a 2000-byte custom parameter to increase the length of the CHLO.
59 constexpr auto kCustomParameterId =
60 static_cast<TransportParameters::TransportParameterId>(0xff33);
61 std::string kCustomParameterValue(2000, '-');
62 config_.custom_transport_parameters_to_send()[kCustomParameterId] =
63 kCustomParameterValue;
64 }
65
66 ParsedQuicVersion version_;
67 TlsChloExtractor tls_chlo_extractor_;
68 QuicConfig config_;
69 std::vector<std::unique_ptr<QuicReceivedPacket>> packets_;
70 };
71
72 INSTANTIATE_TEST_SUITE_P(TlsChloExtractorTests,
73 TlsChloExtractorTest,
74 ::testing::ValuesIn(AllSupportedVersionsWithTls()),
75 ::testing::PrintToStringParamName());
76
TEST_P(TlsChloExtractorTest,Simple)77 TEST_P(TlsChloExtractorTest, Simple) {
78 Initialize();
79 EXPECT_EQ(packets_.size(), 1u);
80 IngestPackets();
81 ValidateChloDetails();
82 EXPECT_EQ(tls_chlo_extractor_.state(),
83 TlsChloExtractor::State::kParsedFullSinglePacketChlo);
84 }
85
TEST_P(TlsChloExtractorTest,MultiPacket)86 TEST_P(TlsChloExtractorTest, MultiPacket) {
87 IncreaseSizeOfChlo();
88 Initialize();
89 EXPECT_EQ(packets_.size(), 2u);
90 IngestPackets();
91 ValidateChloDetails();
92 EXPECT_EQ(tls_chlo_extractor_.state(),
93 TlsChloExtractor::State::kParsedFullMultiPacketChlo);
94 }
95
TEST_P(TlsChloExtractorTest,MultiPacketReordered)96 TEST_P(TlsChloExtractorTest, MultiPacketReordered) {
97 IncreaseSizeOfChlo();
98 Initialize();
99 ASSERT_EQ(packets_.size(), 2u);
100 // Artifically reorder both packets.
101 std::swap(packets_[0], packets_[1]);
102 IngestPackets();
103 ValidateChloDetails();
104 EXPECT_EQ(tls_chlo_extractor_.state(),
105 TlsChloExtractor::State::kParsedFullMultiPacketChlo);
106 }
107
TEST_P(TlsChloExtractorTest,MoveAssignment)108 TEST_P(TlsChloExtractorTest, MoveAssignment) {
109 Initialize();
110 EXPECT_EQ(packets_.size(), 1u);
111 TlsChloExtractor other_extractor;
112 tls_chlo_extractor_ = std::move(other_extractor);
113 IngestPackets();
114 ValidateChloDetails();
115 EXPECT_EQ(tls_chlo_extractor_.state(),
116 TlsChloExtractor::State::kParsedFullSinglePacketChlo);
117 }
118
TEST_P(TlsChloExtractorTest,MoveAssignmentBetweenPackets)119 TEST_P(TlsChloExtractorTest, MoveAssignmentBetweenPackets) {
120 IncreaseSizeOfChlo();
121 Initialize();
122 ASSERT_EQ(packets_.size(), 2u);
123 TlsChloExtractor other_extractor;
124
125 // Have |other_extractor| parse the first packet.
126 ReceivedPacketInfo packet_info(
127 QuicSocketAddress(TestPeerIPAddress(), kTestPort),
128 QuicSocketAddress(TestPeerIPAddress(), kTestPort), *packets_[0]);
129 std::string detailed_error;
130 bool retry_token_present;
131 absl::string_view retry_token;
132 const QuicErrorCode error = QuicFramer::ParsePublicHeaderDispatcher(
133 *packets_[0], /*expected_destination_connection_id_length=*/0,
134 &packet_info.form, &packet_info.long_packet_type,
135 &packet_info.version_flag, &packet_info.use_length_prefix,
136 &packet_info.version_label, &packet_info.version,
137 &packet_info.destination_connection_id, &packet_info.source_connection_id,
138 &retry_token_present, &retry_token, &detailed_error);
139 ASSERT_THAT(error, IsQuicNoError()) << detailed_error;
140 other_extractor.IngestPacket(packet_info.version, packet_info.packet);
141 // Remove the first packet from the list.
142 packets_.erase(packets_.begin());
143 EXPECT_EQ(packets_.size(), 1u);
144
145 // Move the extractor.
146 tls_chlo_extractor_ = std::move(other_extractor);
147
148 // Have |tls_chlo_extractor_| parse the second packet.
149 IngestPackets();
150
151 ValidateChloDetails();
152 EXPECT_EQ(tls_chlo_extractor_.state(),
153 TlsChloExtractor::State::kParsedFullMultiPacketChlo);
154 }
155
156 } // namespace
157 } // namespace test
158 } // namespace quic
159