OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/tools/quic/stateless_rejector.h" | 5 #include "net/tools/quic/stateless_rejector.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
| 10 #include "base/memory/ptr_util.h" |
10 #include "base/strings/stringprintf.h" | 11 #include "base/strings/stringprintf.h" |
11 #include "net/quic/core/crypto/crypto_handshake_message.h" | 12 #include "net/quic/core/crypto/crypto_handshake_message.h" |
12 #include "net/quic/core/crypto/proof_source.h" | 13 #include "net/quic/core/crypto/proof_source.h" |
13 #include "net/quic/core/quic_utils.h" | 14 #include "net/quic/core/quic_utils.h" |
14 #include "net/quic/test_tools/crypto_test_utils.h" | 15 #include "net/quic/test_tools/crypto_test_utils.h" |
15 #include "net/quic/test_tools/quic_crypto_server_config_peer.h" | 16 #include "net/quic/test_tools/quic_crypto_server_config_peer.h" |
16 #include "net/quic/test_tools/quic_test_utils.h" | 17 #include "net/quic/test_tools/quic_test_utils.h" |
17 | 18 |
18 using std::ostream; | 19 using std::ostream; |
19 using std::string; | 20 using std::string; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 class StatelessRejectorTest : public ::testing::TestWithParam<TestParams> { | 74 class StatelessRejectorTest : public ::testing::TestWithParam<TestParams> { |
74 public: | 75 public: |
75 StatelessRejectorTest() | 76 StatelessRejectorTest() |
76 : proof_source_(CryptoTestUtils::ProofSourceForTesting()), | 77 : proof_source_(CryptoTestUtils::ProofSourceForTesting()), |
77 config_(QuicCryptoServerConfig::TESTING, | 78 config_(QuicCryptoServerConfig::TESTING, |
78 QuicRandom::GetInstance(), | 79 QuicRandom::GetInstance(), |
79 CryptoTestUtils::ProofSourceForTesting()), | 80 CryptoTestUtils::ProofSourceForTesting()), |
80 config_peer_(&config_), | 81 config_peer_(&config_), |
81 compressed_certs_cache_( | 82 compressed_certs_cache_( |
82 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize), | 83 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize), |
83 rejector_(GetParam().version, | 84 rejector_(base::MakeUnique<StatelessRejector>( |
84 AllSupportedVersions(), | 85 GetParam().version, |
85 &config_, | 86 AllSupportedVersions(), |
86 &compressed_certs_cache_, | 87 &config_, |
87 &clock_, | 88 &compressed_certs_cache_, |
88 QuicRandom::GetInstance(), | 89 &clock_, |
89 kDefaultMaxPacketSize, | 90 QuicRandom::GetInstance(), |
90 IPEndPoint(net::test::Loopback4(), 12345), | 91 kDefaultMaxPacketSize, |
91 IPEndPoint(net::test::Loopback4(), 443)) { | 92 IPEndPoint(net::test::Loopback4(), 12345), |
| 93 IPEndPoint(net::test::Loopback4(), 443))) { |
92 FLAGS_enable_quic_stateless_reject_support = | 94 FLAGS_enable_quic_stateless_reject_support = |
93 GetParam().flags == ENABLED || GetParam().flags == CHEAP_DISABLED; | 95 GetParam().flags == ENABLED || GetParam().flags == CHEAP_DISABLED; |
94 FLAGS_quic_use_cheap_stateless_rejects = | 96 FLAGS_quic_use_cheap_stateless_rejects = |
95 GetParam().flags == ENABLED || GetParam().flags == STATELESS_DISABLED; | 97 GetParam().flags == ENABLED || GetParam().flags == STATELESS_DISABLED; |
96 | 98 |
97 // Add a new primary config. | 99 // Add a new primary config. |
98 std::unique_ptr<CryptoHandshakeMessage> msg(config_.AddDefaultConfig( | 100 std::unique_ptr<CryptoHandshakeMessage> msg(config_.AddDefaultConfig( |
99 QuicRandom::GetInstance(), &clock_, config_options_)); | 101 QuicRandom::GetInstance(), &clock_, config_options_)); |
100 | 102 |
101 // Save the server config. | 103 // Save the server config. |
(...skipping 21 matching lines...) Expand all Loading... |
123 SourceAddressTokens previous_tokens; | 125 SourceAddressTokens previous_tokens; |
124 IPAddress ip = net::test::Loopback4(); | 126 IPAddress ip = net::test::Loopback4(); |
125 MockRandom rand; | 127 MockRandom rand; |
126 string stk = config_peer_.NewSourceAddressToken( | 128 string stk = config_peer_.NewSourceAddressToken( |
127 config_peer_.GetPrimaryConfig()->id, previous_tokens, ip, &rand, | 129 config_peer_.GetPrimaryConfig()->id, previous_tokens, ip, &rand, |
128 clock_.WallNow(), nullptr); | 130 clock_.WallNow(), nullptr); |
129 stk_hex_ = "#" + QuicUtils::HexEncode(stk); | 131 stk_hex_ = "#" + QuicUtils::HexEncode(stk); |
130 } | 132 } |
131 | 133 |
132 protected: | 134 protected: |
| 135 class ProcessDoneCallback : public StatelessRejector::ProcessDoneCallback { |
| 136 public: |
| 137 explicit ProcessDoneCallback(StatelessRejectorTest* test) : test_(test) {} |
| 138 void Run(std::unique_ptr<StatelessRejector> rejector) override { |
| 139 test_->rejector_ = std::move(rejector); |
| 140 } |
| 141 |
| 142 private: |
| 143 StatelessRejectorTest* test_; |
| 144 }; |
| 145 |
133 QuicFlagSaver flags_; // Save/restore all QUIC flag values. | 146 QuicFlagSaver flags_; // Save/restore all QUIC flag values. |
| 147 |
134 std::unique_ptr<ProofSource> proof_source_; | 148 std::unique_ptr<ProofSource> proof_source_; |
135 MockClock clock_; | 149 MockClock clock_; |
136 QuicCryptoServerConfig config_; | 150 QuicCryptoServerConfig config_; |
137 QuicCryptoServerConfigPeer config_peer_; | 151 QuicCryptoServerConfigPeer config_peer_; |
138 QuicCompressedCertsCache compressed_certs_cache_; | 152 QuicCompressedCertsCache compressed_certs_cache_; |
139 QuicCryptoServerConfig::ConfigOptions config_options_; | 153 QuicCryptoServerConfig::ConfigOptions config_options_; |
140 StatelessRejector rejector_; | 154 std::unique_ptr<StatelessRejector> rejector_; |
141 | 155 |
142 // Values used in CHLO messages | 156 // Values used in CHLO messages |
143 string scid_hex_; | 157 string scid_hex_; |
144 string nonc_hex_; | 158 string nonc_hex_; |
145 string pubs_hex_; | 159 string pubs_hex_; |
146 string ver_hex_; | 160 string ver_hex_; |
147 string stk_hex_; | 161 string stk_hex_; |
148 }; | 162 }; |
149 | 163 |
150 INSTANTIATE_TEST_CASE_P(Flags, | 164 INSTANTIATE_TEST_CASE_P(Flags, |
151 StatelessRejectorTest, | 165 StatelessRejectorTest, |
152 ::testing::ValuesIn(GetTestParams()), | 166 ::testing::ValuesIn(GetTestParams()), |
153 TestParamToString); | 167 TestParamToString); |
154 | 168 |
155 TEST_P(StatelessRejectorTest, InvalidChlo) { | 169 TEST_P(StatelessRejectorTest, InvalidChlo) { |
156 // clang-format off | 170 // clang-format off |
157 const CryptoHandshakeMessage client_hello = CryptoTestUtils::Message( | 171 const CryptoHandshakeMessage client_hello = CryptoTestUtils::Message( |
158 "CHLO", | 172 "CHLO", |
159 "PDMD", "X509", | 173 "PDMD", "X509", |
160 "COPT", "SREJ", | 174 "COPT", "SREJ", |
161 nullptr); | 175 nullptr); |
162 // clang-format on | 176 // clang-format on |
163 rejector_.OnChlo(GetParam().version, kConnectionId, | 177 rejector_->OnChlo(GetParam().version, kConnectionId, |
164 kServerDesignateConnectionId, client_hello); | 178 kServerDesignateConnectionId, client_hello); |
165 | 179 |
166 if (GetParam().flags != ENABLED || GetParam().version <= QUIC_VERSION_32) { | 180 if (GetParam().flags != ENABLED || GetParam().version <= QUIC_VERSION_32) { |
167 EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_.state()); | 181 EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state()); |
168 return; | 182 return; |
169 } | 183 } |
170 | 184 |
171 EXPECT_EQ(StatelessRejector::FAILED, rejector_.state()); | 185 // The StatelessRejector is undecided - proceed with async processing |
172 EXPECT_EQ(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, rejector_.error()); | 186 ASSERT_EQ(StatelessRejector::UNKNOWN, rejector_->state()); |
| 187 StatelessRejector::Process(std::move(rejector_), |
| 188 base::MakeUnique<ProcessDoneCallback>(this)); |
| 189 |
| 190 EXPECT_EQ(StatelessRejector::FAILED, rejector_->state()); |
| 191 EXPECT_EQ(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, rejector_->error()); |
173 } | 192 } |
174 | 193 |
175 TEST_P(StatelessRejectorTest, ValidChloWithoutSrejSupport) { | 194 TEST_P(StatelessRejectorTest, ValidChloWithoutSrejSupport) { |
176 // clang-format off | 195 // clang-format off |
177 const CryptoHandshakeMessage client_hello = CryptoTestUtils::Message( | 196 const CryptoHandshakeMessage client_hello = CryptoTestUtils::Message( |
178 "CHLO", | 197 "CHLO", |
179 "PDMD", "X509", | 198 "PDMD", "X509", |
180 "AEAD", "AESG", | 199 "AEAD", "AESG", |
181 "KEXS", "C255", | 200 "KEXS", "C255", |
182 "PUBS", pubs_hex_.c_str(), | 201 "PUBS", pubs_hex_.c_str(), |
183 "NONC", nonc_hex_.c_str(), | 202 "NONC", nonc_hex_.c_str(), |
184 "VER\0", ver_hex_.c_str(), | 203 "VER\0", ver_hex_.c_str(), |
185 "$padding", static_cast<int>(kClientHelloMinimumSize), | 204 "$padding", static_cast<int>(kClientHelloMinimumSize), |
186 nullptr); | 205 nullptr); |
187 // clang-format on | 206 // clang-format on |
188 | 207 |
189 rejector_.OnChlo(GetParam().version, kConnectionId, | 208 rejector_->OnChlo(GetParam().version, kConnectionId, |
190 kServerDesignateConnectionId, client_hello); | 209 kServerDesignateConnectionId, client_hello); |
191 EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_.state()); | 210 EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state()); |
192 } | 211 } |
193 | 212 |
194 TEST_P(StatelessRejectorTest, RejectChlo) { | 213 TEST_P(StatelessRejectorTest, RejectChlo) { |
195 // clang-format off | 214 // clang-format off |
196 const CryptoHandshakeMessage client_hello = CryptoTestUtils::Message( | 215 const CryptoHandshakeMessage client_hello = CryptoTestUtils::Message( |
197 "CHLO", | 216 "CHLO", |
198 "PDMD", "X509", | 217 "PDMD", "X509", |
199 "AEAD", "AESG", | 218 "AEAD", "AESG", |
200 "KEXS", "C255", | 219 "KEXS", "C255", |
201 "COPT", "SREJ", | 220 "COPT", "SREJ", |
202 "SCID", scid_hex_.c_str(), | 221 "SCID", scid_hex_.c_str(), |
203 "PUBS", pubs_hex_.c_str(), | 222 "PUBS", pubs_hex_.c_str(), |
204 "NONC", nonc_hex_.c_str(), | 223 "NONC", nonc_hex_.c_str(), |
205 "#004b5453", stk_hex_.c_str(), | 224 "#004b5453", stk_hex_.c_str(), |
206 "VER\0", ver_hex_.c_str(), | 225 "VER\0", ver_hex_.c_str(), |
207 "$padding", static_cast<int>(kClientHelloMinimumSize), | 226 "$padding", static_cast<int>(kClientHelloMinimumSize), |
208 nullptr); | 227 nullptr); |
209 // clang-format on | 228 // clang-format on |
210 | 229 |
211 rejector_.OnChlo(GetParam().version, kConnectionId, | 230 rejector_->OnChlo(GetParam().version, kConnectionId, |
212 kServerDesignateConnectionId, client_hello); | 231 kServerDesignateConnectionId, client_hello); |
213 if (GetParam().flags != ENABLED || GetParam().version <= QUIC_VERSION_32) { | 232 if (GetParam().flags != ENABLED || GetParam().version <= QUIC_VERSION_32) { |
214 EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_.state()); | 233 EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state()); |
215 return; | 234 return; |
216 } | 235 } |
217 ASSERT_EQ(StatelessRejector::REJECTED, rejector_.state()); | 236 |
218 const CryptoHandshakeMessage& reply = rejector_.reply(); | 237 // The StatelessRejector is undecided - proceed with async processing |
| 238 ASSERT_EQ(StatelessRejector::UNKNOWN, rejector_->state()); |
| 239 StatelessRejector::Process(std::move(rejector_), |
| 240 base::MakeUnique<ProcessDoneCallback>(this)); |
| 241 |
| 242 ASSERT_EQ(StatelessRejector::REJECTED, rejector_->state()); |
| 243 const CryptoHandshakeMessage& reply = rejector_->reply(); |
219 EXPECT_EQ(kSREJ, reply.tag()); | 244 EXPECT_EQ(kSREJ, reply.tag()); |
220 const uint32_t* reject_reasons; | 245 const uint32_t* reject_reasons; |
221 size_t num_reject_reasons; | 246 size_t num_reject_reasons; |
222 EXPECT_EQ(QUIC_NO_ERROR, | 247 EXPECT_EQ(QUIC_NO_ERROR, |
223 reply.GetTaglist(kRREJ, &reject_reasons, &num_reject_reasons)); | 248 reply.GetTaglist(kRREJ, &reject_reasons, &num_reject_reasons)); |
224 EXPECT_EQ(1u, num_reject_reasons); | 249 EXPECT_EQ(1u, num_reject_reasons); |
225 EXPECT_EQ(INVALID_EXPECTED_LEAF_CERTIFICATE, | 250 EXPECT_EQ(INVALID_EXPECTED_LEAF_CERTIFICATE, |
226 static_cast<HandshakeFailureReason>(reject_reasons[0])); | 251 static_cast<HandshakeFailureReason>(reject_reasons[0])); |
227 } | 252 } |
228 | 253 |
(...skipping 12 matching lines...) Expand all Loading... |
241 "SCID", scid_hex_.c_str(), | 266 "SCID", scid_hex_.c_str(), |
242 "PUBS", pubs_hex_.c_str(), | 267 "PUBS", pubs_hex_.c_str(), |
243 "NONC", nonc_hex_.c_str(), | 268 "NONC", nonc_hex_.c_str(), |
244 "#004b5453", stk_hex_.c_str(), | 269 "#004b5453", stk_hex_.c_str(), |
245 "VER\0", ver_hex_.c_str(), | 270 "VER\0", ver_hex_.c_str(), |
246 "XLCT", xlct_hex.c_str(), | 271 "XLCT", xlct_hex.c_str(), |
247 "$padding", static_cast<int>(kClientHelloMinimumSize), | 272 "$padding", static_cast<int>(kClientHelloMinimumSize), |
248 nullptr); | 273 nullptr); |
249 // clang-format on | 274 // clang-format on |
250 | 275 |
251 rejector_.OnChlo(GetParam().version, kConnectionId, | 276 rejector_->OnChlo(GetParam().version, kConnectionId, |
252 kServerDesignateConnectionId, client_hello); | 277 kServerDesignateConnectionId, client_hello); |
253 if (GetParam().flags != ENABLED || GetParam().version <= QUIC_VERSION_32) { | 278 if (GetParam().flags != ENABLED || GetParam().version <= QUIC_VERSION_32) { |
254 EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_.state()); | 279 EXPECT_EQ(StatelessRejector::UNSUPPORTED, rejector_->state()); |
255 return; | 280 return; |
256 } | 281 } |
257 EXPECT_EQ(StatelessRejector::ACCEPTED, rejector_.state()); | 282 |
| 283 // The StatelessRejector is undecided - proceed with async processing |
| 284 ASSERT_EQ(StatelessRejector::UNKNOWN, rejector_->state()); |
| 285 StatelessRejector::Process(std::move(rejector_), |
| 286 base::MakeUnique<ProcessDoneCallback>(this)); |
| 287 |
| 288 EXPECT_EQ(StatelessRejector::ACCEPTED, rejector_->state()); |
258 } | 289 } |
259 | 290 |
260 } // namespace | 291 } // namespace |
261 } // namespace test | 292 } // namespace test |
262 } // namespace net | 293 } // namespace net |
OLD | NEW |