OLD | NEW |
| (Empty) |
1 // Copyright 2013 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/crypto/quic_crypto_server_config.h" | |
6 | |
7 #include <stdarg.h> | |
8 | |
9 #include "base/stl_util.h" | |
10 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h" | |
11 #include "net/quic/crypto/crypto_handshake_message.h" | |
12 #include "net/quic/crypto/crypto_secret_boxer.h" | |
13 #include "net/quic/crypto/crypto_server_config_protobuf.h" | |
14 #include "net/quic/crypto/quic_random.h" | |
15 #include "net/quic/crypto/strike_register_client.h" | |
16 #include "net/quic/quic_flags.h" | |
17 #include "net/quic/quic_time.h" | |
18 #include "net/quic/test_tools/mock_clock.h" | |
19 #include "net/quic/test_tools/quic_test_utils.h" | |
20 #include "testing/gmock/include/gmock/gmock.h" | |
21 #include "testing/gtest/include/gtest/gtest.h" | |
22 | |
23 using base::StringPiece; | |
24 using std::map; | |
25 using std::pair; | |
26 using std::string; | |
27 using std::vector; | |
28 | |
29 namespace net { | |
30 namespace test { | |
31 | |
32 class QuicCryptoServerConfigPeer { | |
33 public: | |
34 explicit QuicCryptoServerConfigPeer(QuicCryptoServerConfig* server_config) | |
35 : server_config_(server_config) {} | |
36 | |
37 scoped_refptr<QuicCryptoServerConfig::Config> GetConfig(string config_id) { | |
38 base::AutoLock locked(server_config_->configs_lock_); | |
39 if (config_id == "<primary>") { | |
40 return scoped_refptr<QuicCryptoServerConfig::Config>( | |
41 server_config_->primary_config_); | |
42 } else { | |
43 return server_config_->GetConfigWithScid(config_id); | |
44 } | |
45 } | |
46 | |
47 bool ConfigHasDefaultSourceAddressTokenBoxer(string config_id) { | |
48 scoped_refptr<QuicCryptoServerConfig::Config> config = GetConfig(config_id); | |
49 return config->source_address_token_boxer == | |
50 &(server_config_->default_source_address_token_boxer_); | |
51 } | |
52 | |
53 string NewSourceAddressToken(string config_id, | |
54 SourceAddressTokens previous_tokens, | |
55 const IPEndPoint& ip, | |
56 QuicRandom* rand, | |
57 QuicWallTime now, | |
58 CachedNetworkParameters* cached_network_params) { | |
59 return server_config_->NewSourceAddressToken(*GetConfig(config_id), | |
60 previous_tokens, ip, rand, now, | |
61 cached_network_params); | |
62 } | |
63 | |
64 HandshakeFailureReason ValidateSourceAddressToken(string config_id, | |
65 StringPiece srct, | |
66 const IPEndPoint& ip, | |
67 QuicWallTime now) { | |
68 return ValidateSourceAddressToken(config_id, srct, ip, now, NULL); | |
69 } | |
70 | |
71 HandshakeFailureReason ValidateSourceAddressToken( | |
72 string config_id, | |
73 StringPiece srct, | |
74 const IPEndPoint& ip, | |
75 QuicWallTime now, | |
76 CachedNetworkParameters* cached_network_params) { | |
77 return server_config_->ValidateSourceAddressToken( | |
78 *GetConfig(config_id), srct, ip, now, cached_network_params); | |
79 } | |
80 | |
81 HandshakeFailureReason ValidateSourceAddressTokens(string config_id, | |
82 StringPiece srct, | |
83 const IPEndPoint& ip, | |
84 QuicWallTime now) { | |
85 return ValidateSourceAddressTokens(config_id, srct, ip, now, NULL); | |
86 } | |
87 | |
88 HandshakeFailureReason ValidateSourceAddressTokens( | |
89 string config_id, | |
90 StringPiece srct, | |
91 const IPEndPoint& ip, | |
92 QuicWallTime now, | |
93 CachedNetworkParameters* cached_network_params) { | |
94 SourceAddressTokens tokens; | |
95 HandshakeFailureReason reason = server_config_->ParseSourceAddressToken( | |
96 *GetConfig(config_id), srct, &tokens); | |
97 if (reason != HANDSHAKE_OK) { | |
98 return reason; | |
99 } | |
100 | |
101 return server_config_->ValidateSourceAddressTokens(tokens, ip, now, | |
102 cached_network_params); | |
103 } | |
104 | |
105 string NewServerNonce(QuicRandom* rand, QuicWallTime now) const { | |
106 return server_config_->NewServerNonce(rand, now); | |
107 } | |
108 | |
109 HandshakeFailureReason ValidateServerNonce(StringPiece token, | |
110 QuicWallTime now) { | |
111 return server_config_->ValidateServerNonce(token, now); | |
112 } | |
113 | |
114 base::Lock* GetStrikeRegisterClientLock() { | |
115 return &server_config_->strike_register_client_lock_; | |
116 } | |
117 | |
118 // CheckConfigs compares the state of the Configs in |server_config_| to the | |
119 // description given as arguments. The arguments are given as | |
120 // nullptr-terminated pairs. The first of each pair is the server config ID of | |
121 // a Config. The second is a boolean describing whether the config is the | |
122 // primary. For example: | |
123 // CheckConfigs(nullptr); // checks that no Configs are loaded. | |
124 // | |
125 // // Checks that exactly three Configs are loaded with the given IDs and | |
126 // // status. | |
127 // CheckConfigs( | |
128 // "id1", false, | |
129 // "id2", true, | |
130 // "id3", false, | |
131 // nullptr); | |
132 void CheckConfigs(const char* server_config_id1, ...) { | |
133 va_list ap; | |
134 va_start(ap, server_config_id1); | |
135 | |
136 vector<pair<ServerConfigID, bool> > expected; | |
137 bool first = true; | |
138 for (;;) { | |
139 const char* server_config_id; | |
140 if (first) { | |
141 server_config_id = server_config_id1; | |
142 first = false; | |
143 } else { | |
144 server_config_id = va_arg(ap, const char*); | |
145 } | |
146 | |
147 if (!server_config_id) { | |
148 break; | |
149 } | |
150 | |
151 // varargs will promote the value to an int so we have to read that from | |
152 // the stack and cast down. | |
153 const bool is_primary = static_cast<bool>(va_arg(ap, int)); | |
154 expected.push_back(std::make_pair(server_config_id, is_primary)); | |
155 } | |
156 | |
157 va_end(ap); | |
158 | |
159 base::AutoLock locked(server_config_->configs_lock_); | |
160 | |
161 ASSERT_EQ(expected.size(), server_config_->configs_.size()) | |
162 << ConfigsDebug(); | |
163 | |
164 for (QuicCryptoServerConfig::ConfigMap::const_iterator | |
165 i = server_config_->configs_.begin(); | |
166 i != server_config_->configs_.end(); ++i) { | |
167 bool found = false; | |
168 for (vector<pair<ServerConfigID, bool> >::iterator j = expected.begin(); | |
169 j != expected.end(); ++j) { | |
170 if (i->first == j->first && i->second->is_primary == j->second) { | |
171 found = true; | |
172 j->first.clear(); | |
173 break; | |
174 } | |
175 } | |
176 | |
177 ASSERT_TRUE(found) << "Failed to find match for " << i->first | |
178 << " in configs:\n" << ConfigsDebug(); | |
179 } | |
180 } | |
181 | |
182 // ConfigsDebug returns a string that contains debugging information about | |
183 // the set of Configs loaded in |server_config_| and their status. | |
184 // ConfigsDebug() should be called after acquiring | |
185 // server_config_->configs_lock_. | |
186 string ConfigsDebug() { | |
187 if (server_config_->configs_.empty()) { | |
188 return "No Configs in QuicCryptoServerConfig"; | |
189 } | |
190 | |
191 string s; | |
192 | |
193 for (QuicCryptoServerConfig::ConfigMap::const_iterator | |
194 i = server_config_->configs_.begin(); | |
195 i != server_config_->configs_.end(); ++i) { | |
196 const scoped_refptr<QuicCryptoServerConfig::Config> config = i->second; | |
197 if (config->is_primary) { | |
198 s += "(primary) "; | |
199 } else { | |
200 s += " "; | |
201 } | |
202 s += config->id; | |
203 s += "\n"; | |
204 } | |
205 | |
206 return s; | |
207 } | |
208 | |
209 void SelectNewPrimaryConfig(int seconds) { | |
210 base::AutoLock locked(server_config_->configs_lock_); | |
211 server_config_->SelectNewPrimaryConfig( | |
212 QuicWallTime::FromUNIXSeconds(seconds)); | |
213 } | |
214 | |
215 private: | |
216 const QuicCryptoServerConfig* server_config_; | |
217 }; | |
218 | |
219 class TestStrikeRegisterClient : public StrikeRegisterClient { | |
220 public: | |
221 explicit TestStrikeRegisterClient(QuicCryptoServerConfig* config) | |
222 : config_(config), | |
223 is_known_orbit_called_(false) { | |
224 } | |
225 | |
226 bool IsKnownOrbit(StringPiece orbit) const override { | |
227 // Ensure that the strike register client lock is not held. | |
228 QuicCryptoServerConfigPeer peer(config_); | |
229 base::Lock* m = peer.GetStrikeRegisterClientLock(); | |
230 // In Chromium, we will dead lock if the lock is held by the current thread. | |
231 // Chromium doesn't have AssertNotHeld API call. | |
232 // m->AssertNotHeld(); | |
233 base::AutoLock lock(*m); | |
234 | |
235 is_known_orbit_called_ = true; | |
236 return true; | |
237 } | |
238 | |
239 void VerifyNonceIsValidAndUnique(StringPiece nonce, | |
240 QuicWallTime now, | |
241 ResultCallback* cb) override { | |
242 LOG(FATAL) << "Not implemented"; | |
243 } | |
244 | |
245 bool is_known_orbit_called() { return is_known_orbit_called_; } | |
246 | |
247 private: | |
248 QuicCryptoServerConfig* config_; | |
249 mutable bool is_known_orbit_called_; | |
250 }; | |
251 | |
252 TEST(QuicCryptoServerConfigTest, ServerConfig) { | |
253 QuicRandom* rand = QuicRandom::GetInstance(); | |
254 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand); | |
255 MockClock clock; | |
256 | |
257 scoped_ptr<CryptoHandshakeMessage>( | |
258 server.AddDefaultConfig(rand, &clock, | |
259 QuicCryptoServerConfig::ConfigOptions())); | |
260 } | |
261 | |
262 TEST(QuicCryptoServerConfigTest, GetOrbitIsCalledWithoutTheStrikeRegisterLock) { | |
263 QuicRandom* rand = QuicRandom::GetInstance(); | |
264 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand); | |
265 MockClock clock; | |
266 | |
267 TestStrikeRegisterClient* strike_register = | |
268 new TestStrikeRegisterClient(&server); | |
269 server.SetStrikeRegisterClient(strike_register); | |
270 | |
271 QuicCryptoServerConfig::ConfigOptions options; | |
272 scoped_ptr<CryptoHandshakeMessage>( | |
273 server.AddDefaultConfig(rand, &clock, options)); | |
274 EXPECT_TRUE(strike_register->is_known_orbit_called()); | |
275 } | |
276 | |
277 class SourceAddressTokenTest : public ::testing::Test { | |
278 public: | |
279 SourceAddressTokenTest() | |
280 : ip4_(IPEndPoint(Loopback4(), 1)), | |
281 ip4_dual_(ConvertIPv4NumberToIPv6Number(ip4_.address()), 1), | |
282 ip6_(IPEndPoint(Loopback6(), 2)), | |
283 original_time_(QuicWallTime::Zero()), | |
284 rand_(QuicRandom::GetInstance()), | |
285 server_(QuicCryptoServerConfig::TESTING, rand_), | |
286 peer_(&server_) { | |
287 // Advance the clock to some non-zero time. | |
288 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1000000)); | |
289 original_time_ = clock_.WallNow(); | |
290 | |
291 primary_config_.reset(server_.AddDefaultConfig( | |
292 rand_, &clock_, QuicCryptoServerConfig::ConfigOptions())); | |
293 | |
294 // Add a config that overrides the default boxer. | |
295 QuicCryptoServerConfig::ConfigOptions options; | |
296 options.id = kOverride; | |
297 override_config_protobuf_.reset( | |
298 QuicCryptoServerConfig::GenerateConfig(rand_, &clock_, options)); | |
299 override_config_protobuf_->set_source_address_token_secret_override( | |
300 "a secret key"); | |
301 // Lower priority than the default config. | |
302 override_config_protobuf_->set_priority(1); | |
303 override_config_.reset( | |
304 server_.AddConfig(override_config_protobuf_.get(), original_time_)); | |
305 } | |
306 | |
307 string NewSourceAddressToken(string config_id, const IPEndPoint& ip) { | |
308 return NewSourceAddressToken(config_id, ip, NULL); | |
309 } | |
310 | |
311 string NewSourceAddressToken(string config_id, | |
312 const IPEndPoint& ip, | |
313 const SourceAddressTokens& previous_tokens) { | |
314 return peer_.NewSourceAddressToken(config_id, previous_tokens, ip, rand_, | |
315 clock_.WallNow(), NULL); | |
316 } | |
317 | |
318 string NewSourceAddressToken(string config_id, | |
319 const IPEndPoint& ip, | |
320 CachedNetworkParameters* cached_network_params) { | |
321 SourceAddressTokens previous_tokens; | |
322 return peer_.NewSourceAddressToken(config_id, previous_tokens, ip, rand_, | |
323 clock_.WallNow(), cached_network_params); | |
324 } | |
325 | |
326 HandshakeFailureReason ValidateSourceAddressToken(string config_id, | |
327 StringPiece srct, | |
328 const IPEndPoint& ip) { | |
329 return ValidateSourceAddressToken(config_id, srct, ip, NULL); | |
330 } | |
331 | |
332 HandshakeFailureReason ValidateSourceAddressToken( | |
333 string config_id, | |
334 StringPiece srct, | |
335 const IPEndPoint& ip, | |
336 CachedNetworkParameters* cached_network_params) { | |
337 return peer_.ValidateSourceAddressToken( | |
338 config_id, srct, ip, clock_.WallNow(), cached_network_params); | |
339 } | |
340 | |
341 HandshakeFailureReason ValidateSourceAddressTokens(string config_id, | |
342 StringPiece srct, | |
343 const IPEndPoint& ip) { | |
344 return ValidateSourceAddressTokens(config_id, srct, ip, NULL); | |
345 } | |
346 | |
347 HandshakeFailureReason ValidateSourceAddressTokens( | |
348 string config_id, | |
349 StringPiece srct, | |
350 const IPEndPoint& ip, | |
351 CachedNetworkParameters* cached_network_params) { | |
352 return peer_.ValidateSourceAddressTokens( | |
353 config_id, srct, ip, clock_.WallNow(), cached_network_params); | |
354 } | |
355 | |
356 const string kPrimary = "<primary>"; | |
357 const string kOverride = "Config with custom source address token key"; | |
358 | |
359 IPEndPoint ip4_; | |
360 IPEndPoint ip4_dual_; | |
361 IPEndPoint ip6_; | |
362 | |
363 MockClock clock_; | |
364 QuicWallTime original_time_; | |
365 QuicRandom* rand_ = QuicRandom::GetInstance(); | |
366 QuicCryptoServerConfig server_; | |
367 QuicCryptoServerConfigPeer peer_; | |
368 // Stores the primary config. | |
369 scoped_ptr<CryptoHandshakeMessage> primary_config_; | |
370 scoped_ptr<QuicServerConfigProtobuf> override_config_protobuf_; | |
371 scoped_ptr<CryptoHandshakeMessage> override_config_; | |
372 }; | |
373 | |
374 TEST_F(SourceAddressTokenTest, SourceAddressToken) { | |
375 ValueRestore<bool> old_flag(&FLAGS_quic_use_multiple_address_in_source_tokens, | |
376 false); | |
377 | |
378 EXPECT_TRUE(peer_.ConfigHasDefaultSourceAddressTokenBoxer(kPrimary)); | |
379 EXPECT_FALSE(peer_.ConfigHasDefaultSourceAddressTokenBoxer(kOverride)); | |
380 | |
381 // Primary config generates configs that validate successfully. | |
382 const string token4 = NewSourceAddressToken(kPrimary, ip4_); | |
383 const string token4d = NewSourceAddressToken(kPrimary, ip4_dual_); | |
384 const string token6 = NewSourceAddressToken(kPrimary, ip6_); | |
385 EXPECT_EQ(HANDSHAKE_OK, ValidateSourceAddressToken(kPrimary, token4, ip4_)); | |
386 ASSERT_EQ(HANDSHAKE_OK, | |
387 ValidateSourceAddressToken(kPrimary, token4, ip4_dual_)); | |
388 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE, | |
389 ValidateSourceAddressToken(kPrimary, token4, ip6_)); | |
390 ASSERT_EQ(HANDSHAKE_OK, ValidateSourceAddressToken(kPrimary, token4d, ip4_)); | |
391 ASSERT_EQ(HANDSHAKE_OK, | |
392 ValidateSourceAddressToken(kPrimary, token4d, ip4_dual_)); | |
393 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE, | |
394 ValidateSourceAddressToken(kPrimary, token4d, ip6_)); | |
395 ASSERT_EQ(HANDSHAKE_OK, ValidateSourceAddressToken(kPrimary, token6, ip6_)); | |
396 | |
397 // Override config generates configs that validate successfully. | |
398 const string override_token4 = NewSourceAddressToken(kOverride, ip4_); | |
399 const string override_token6 = NewSourceAddressToken(kOverride, ip6_); | |
400 ASSERT_EQ(HANDSHAKE_OK, | |
401 ValidateSourceAddressToken(kOverride, override_token4, ip4_)); | |
402 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE, | |
403 ValidateSourceAddressToken(kOverride, override_token4, ip6_)); | |
404 ASSERT_EQ(HANDSHAKE_OK, | |
405 ValidateSourceAddressToken(kOverride, override_token6, ip6_)); | |
406 | |
407 // Tokens generated by the primary config do not validate | |
408 // successfully against the override config, and vice versa. | |
409 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, | |
410 ValidateSourceAddressToken(kOverride, token4, ip4_)); | |
411 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, | |
412 ValidateSourceAddressToken(kOverride, token6, ip6_)); | |
413 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, | |
414 ValidateSourceAddressToken(kPrimary, override_token4, ip4_)); | |
415 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, | |
416 ValidateSourceAddressToken(kPrimary, override_token6, ip6_)); | |
417 } | |
418 | |
419 TEST_F(SourceAddressTokenTest, SourceAddressTokenExpiration) { | |
420 ValueRestore<bool> old_flag(&FLAGS_quic_use_multiple_address_in_source_tokens, | |
421 false); | |
422 | |
423 const string token = NewSourceAddressToken(kPrimary, ip4_); | |
424 | |
425 // Validation fails if the token is from the future. | |
426 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(-3600 * 2)); | |
427 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE, | |
428 ValidateSourceAddressToken(kPrimary, token, ip4_)); | |
429 | |
430 // Validation fails after tokens expire. | |
431 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(86400 * 7)); | |
432 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE, | |
433 ValidateSourceAddressToken(kPrimary, token, ip4_)); | |
434 } | |
435 | |
436 TEST_F(SourceAddressTokenTest, SourceAddressTokenWithNetworkParams) { | |
437 ValueRestore<bool> old_flag(&FLAGS_quic_use_multiple_address_in_source_tokens, | |
438 false); | |
439 | |
440 // Make sure that if the source address token contains CachedNetworkParameters | |
441 // that this gets written to ValidateSourceAddressToken output argument. | |
442 CachedNetworkParameters cached_network_params_input; | |
443 cached_network_params_input.set_bandwidth_estimate_bytes_per_second(1234); | |
444 const string token4_with_cached_network_params = | |
445 NewSourceAddressToken(kPrimary, ip4_, &cached_network_params_input); | |
446 | |
447 CachedNetworkParameters cached_network_params_output; | |
448 #if 0 | |
449 // TODO(rtenneti): For server, enable the following check after serialization | |
450 // of optional CachedNetworkParameters is implemented. | |
451 EXPECT_NE(cached_network_params_output.DebugString(), | |
452 cached_network_params_input.DebugString()); | |
453 #endif | |
454 ValidateSourceAddressToken(kPrimary, token4_with_cached_network_params, ip4_, | |
455 &cached_network_params_output); | |
456 #if 0 | |
457 // TODO(rtenneti): For server, enable the following check after serialization | |
458 // of optional CachedNetworkParameters is implemented. | |
459 EXPECT_EQ(cached_network_params_output.DebugString(), | |
460 cached_network_params_input.DebugString()); | |
461 #endif | |
462 } | |
463 | |
464 // Test basic behavior of source address tokens including being specific | |
465 // to a single IP address and server config. | |
466 // | |
467 // TODO(rtenneti): For server, enable the following test after serialization of | |
468 // SourceAddressTokens is implemented. | |
469 TEST_F(SourceAddressTokenTest, DISABLED_NewSourceAddressToken) { | |
470 ValueRestore<bool> old_flag(&FLAGS_quic_use_multiple_address_in_source_tokens, | |
471 true); | |
472 | |
473 // Primary config generates configs that validate successfully. | |
474 const string token4 = NewSourceAddressToken(kPrimary, ip4_); | |
475 const string token4d = NewSourceAddressToken(kPrimary, ip4_dual_); | |
476 const string token6 = NewSourceAddressToken(kPrimary, ip6_); | |
477 EXPECT_EQ(HANDSHAKE_OK, ValidateSourceAddressTokens(kPrimary, token4, ip4_)); | |
478 ASSERT_EQ(HANDSHAKE_OK, | |
479 ValidateSourceAddressTokens(kPrimary, token4, ip4_dual_)); | |
480 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE, | |
481 ValidateSourceAddressTokens(kPrimary, token4, ip6_)); | |
482 ASSERT_EQ(HANDSHAKE_OK, ValidateSourceAddressTokens(kPrimary, token4d, ip4_)); | |
483 ASSERT_EQ(HANDSHAKE_OK, | |
484 ValidateSourceAddressTokens(kPrimary, token4d, ip4_dual_)); | |
485 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE, | |
486 ValidateSourceAddressTokens(kPrimary, token4d, ip6_)); | |
487 ASSERT_EQ(HANDSHAKE_OK, ValidateSourceAddressTokens(kPrimary, token6, ip6_)); | |
488 | |
489 // Override config generates configs that validate successfully. | |
490 const string override_token4 = NewSourceAddressToken(kOverride, ip4_); | |
491 const string override_token6 = NewSourceAddressToken(kOverride, ip6_); | |
492 ASSERT_EQ(HANDSHAKE_OK, | |
493 ValidateSourceAddressTokens(kOverride, override_token4, ip4_)); | |
494 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE, | |
495 ValidateSourceAddressTokens(kOverride, override_token4, ip6_)); | |
496 ASSERT_EQ(HANDSHAKE_OK, | |
497 ValidateSourceAddressTokens(kOverride, override_token6, ip6_)); | |
498 | |
499 // Tokens generated by the primary config do not validate | |
500 // successfully against the override config, and vice versa. | |
501 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, | |
502 ValidateSourceAddressTokens(kOverride, token4, ip4_)); | |
503 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, | |
504 ValidateSourceAddressTokens(kOverride, token6, ip6_)); | |
505 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, | |
506 ValidateSourceAddressTokens(kPrimary, override_token4, ip4_)); | |
507 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, | |
508 ValidateSourceAddressTokens(kPrimary, override_token6, ip6_)); | |
509 } | |
510 | |
511 // TODO(rtenneti): For server, enable the following test after serialization of | |
512 // SourceAddressTokens is implemented. | |
513 TEST_F(SourceAddressTokenTest, DISABLED_NewSourceAddressTokenExpiration) { | |
514 ValueRestore<bool> old_flag(&FLAGS_quic_use_multiple_address_in_source_tokens, | |
515 true); | |
516 | |
517 const string token = NewSourceAddressToken(kPrimary, ip4_); | |
518 | |
519 // Validation fails if the token is from the future. | |
520 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(-3600 * 2)); | |
521 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE, | |
522 ValidateSourceAddressTokens(kPrimary, token, ip4_)); | |
523 | |
524 // Validation fails after tokens expire. | |
525 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(86400 * 7)); | |
526 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE, | |
527 ValidateSourceAddressTokens(kPrimary, token, ip4_)); | |
528 } | |
529 | |
530 TEST_F(SourceAddressTokenTest, NewSourceAddressTokenWithNetworkParams) { | |
531 ValueRestore<bool> old_flag(&FLAGS_quic_use_multiple_address_in_source_tokens, | |
532 true); | |
533 | |
534 // Make sure that if the source address token contains CachedNetworkParameters | |
535 // that this gets written to ValidateSourceAddressToken output argument. | |
536 CachedNetworkParameters cached_network_params_input; | |
537 cached_network_params_input.set_bandwidth_estimate_bytes_per_second(1234); | |
538 const string token4_with_cached_network_params = | |
539 NewSourceAddressToken(kPrimary, ip4_, &cached_network_params_input); | |
540 | |
541 CachedNetworkParameters cached_network_params_output; | |
542 #if 0 | |
543 // TODO(rtenneti): For server, enable the following check after serialization | |
544 // of optional CachedNetworkParameters is implemented. | |
545 EXPECT_NE(cached_network_params_output.DebugString(), | |
546 cached_network_params_input.DebugString()); | |
547 #endif | |
548 ValidateSourceAddressTokens(kPrimary, token4_with_cached_network_params, ip4_, | |
549 &cached_network_params_output); | |
550 #if 0 | |
551 // TODO(rtenneti): For server, enable the following check after serialization | |
552 // of optional CachedNetworkParameters is implemented. | |
553 EXPECT_EQ(cached_network_params_output.DebugString(), | |
554 cached_network_params_input.DebugString()); | |
555 #endif | |
556 } | |
557 | |
558 // Test the ability for a source address token to be valid for multiple | |
559 // addresses. | |
560 // | |
561 // TODO(rtenneti): For server, enable the following test after serialization of | |
562 // SourceAddressTokens is implemented. | |
563 TEST_F(SourceAddressTokenTest, DISABLED_SourceAddressTokenMultipleAddresses) { | |
564 ValueRestore<bool> old_flag(&FLAGS_quic_use_multiple_address_in_source_tokens, | |
565 true); | |
566 | |
567 QuicWallTime now = clock_.WallNow(); | |
568 | |
569 // Now create a token which is usable for both addresses. | |
570 SourceAddressToken previous_token; | |
571 IPAddressNumber ip_address = ip6_.address(); | |
572 if (ip6_.GetSockAddrFamily() == AF_INET) { | |
573 ip_address = ConvertIPv4NumberToIPv6Number(ip_address); | |
574 } | |
575 previous_token.set_ip(IPAddressToPackedString(ip_address)); | |
576 previous_token.set_timestamp(now.ToUNIXSeconds()); | |
577 SourceAddressTokens previous_tokens; | |
578 (*previous_tokens.add_tokens()) = previous_token; | |
579 const string token4or6 = | |
580 NewSourceAddressToken(kPrimary, ip4_, previous_tokens); | |
581 | |
582 EXPECT_EQ(HANDSHAKE_OK, | |
583 ValidateSourceAddressTokens(kPrimary, token4or6, ip4_)); | |
584 ASSERT_EQ(HANDSHAKE_OK, | |
585 ValidateSourceAddressTokens(kPrimary, token4or6, ip6_)); | |
586 } | |
587 | |
588 TEST(QuicCryptoServerConfigTest, ValidateServerNonce) { | |
589 QuicRandom* rand = QuicRandom::GetInstance(); | |
590 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand); | |
591 QuicCryptoServerConfigPeer peer(&server); | |
592 | |
593 StringPiece message("hello world"); | |
594 const size_t key_size = CryptoSecretBoxer::GetKeySize(); | |
595 scoped_ptr<uint8[]> key(new uint8[key_size]); | |
596 memset(key.get(), 0x11, key_size); | |
597 | |
598 CryptoSecretBoxer boxer; | |
599 boxer.SetKey(StringPiece(reinterpret_cast<char*>(key.get()), key_size)); | |
600 const string box = boxer.Box(rand, message); | |
601 MockClock clock; | |
602 QuicWallTime now = clock.WallNow(); | |
603 const QuicWallTime original_time = now; | |
604 EXPECT_EQ(SERVER_NONCE_DECRYPTION_FAILURE, | |
605 peer.ValidateServerNonce(box, now)); | |
606 | |
607 string server_nonce = peer.NewServerNonce(rand, now); | |
608 EXPECT_EQ(HANDSHAKE_OK, peer.ValidateServerNonce(server_nonce, now)); | |
609 EXPECT_EQ(SERVER_NONCE_NOT_UNIQUE_FAILURE, | |
610 peer.ValidateServerNonce(server_nonce, now)); | |
611 | |
612 now = original_time.Add(QuicTime::Delta::FromSeconds(1000 * 7)); | |
613 server_nonce = peer.NewServerNonce(rand, now); | |
614 EXPECT_EQ(HANDSHAKE_OK, peer.ValidateServerNonce(server_nonce, now)); | |
615 } | |
616 | |
617 class CryptoServerConfigsTest : public ::testing::Test { | |
618 public: | |
619 CryptoServerConfigsTest() | |
620 : rand_(QuicRandom::GetInstance()), | |
621 config_(QuicCryptoServerConfig::TESTING, rand_), | |
622 test_peer_(&config_) {} | |
623 | |
624 void SetUp() override { | |
625 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1000)); | |
626 } | |
627 | |
628 // SetConfigs constructs suitable config protobufs and calls SetConfigs on | |
629 // |config_|. The arguments are given as nullptr-terminated pairs. The first | |
630 // of each pair is the server config ID of a Config. The second is the | |
631 // |primary_time| of that Config, given in epoch seconds. (Although note that, | |
632 // in these tests, time is set to 1000 seconds since the epoch.) For example: | |
633 // SetConfigs(nullptr); // calls |config_.SetConfigs| with no protobufs. | |
634 // | |
635 // // Calls |config_.SetConfigs| with two protobufs: one for a Config with | |
636 // // a |primary_time| of 900 and priority 1, and another with | |
637 // // a |primary_time| of 1000 and priority 2. | |
638 | |
639 // CheckConfigs( | |
640 // "id1", 900, 1, | |
641 // "id2", 1000, 2, | |
642 // nullptr); | |
643 // | |
644 // If the server config id starts with "INVALID" then the generated protobuf | |
645 // will be invalid. | |
646 void SetConfigs(const char* server_config_id1, ...) { | |
647 const char kOrbit[] = "12345678"; | |
648 | |
649 va_list ap; | |
650 va_start(ap, server_config_id1); | |
651 bool has_invalid = false; | |
652 bool is_empty = true; | |
653 | |
654 vector<QuicServerConfigProtobuf*> protobufs; | |
655 bool first = true; | |
656 for (;;) { | |
657 const char* server_config_id; | |
658 if (first) { | |
659 server_config_id = server_config_id1; | |
660 first = false; | |
661 } else { | |
662 server_config_id = va_arg(ap, const char*); | |
663 } | |
664 | |
665 if (!server_config_id) { | |
666 break; | |
667 } | |
668 | |
669 is_empty = false; | |
670 int primary_time = va_arg(ap, int); | |
671 int priority = va_arg(ap, int); | |
672 | |
673 QuicCryptoServerConfig::ConfigOptions options; | |
674 options.id = server_config_id; | |
675 options.orbit = kOrbit; | |
676 QuicServerConfigProtobuf* protobuf( | |
677 QuicCryptoServerConfig::GenerateConfig(rand_, &clock_, options)); | |
678 protobuf->set_primary_time(primary_time); | |
679 protobuf->set_priority(priority); | |
680 if (string(server_config_id).find("INVALID") == 0) { | |
681 protobuf->clear_key(); | |
682 has_invalid = true; | |
683 } | |
684 protobufs.push_back(protobuf); | |
685 } | |
686 | |
687 ASSERT_EQ(!has_invalid && !is_empty, | |
688 config_.SetConfigs(protobufs, clock_.WallNow())); | |
689 STLDeleteElements(&protobufs); | |
690 } | |
691 | |
692 protected: | |
693 QuicRandom* const rand_; | |
694 MockClock clock_; | |
695 QuicCryptoServerConfig config_; | |
696 QuicCryptoServerConfigPeer test_peer_; | |
697 }; | |
698 | |
699 TEST_F(CryptoServerConfigsTest, NoConfigs) { | |
700 test_peer_.CheckConfigs(nullptr); | |
701 } | |
702 | |
703 TEST_F(CryptoServerConfigsTest, MakePrimaryFirst) { | |
704 // Make sure that "b" is primary even though "a" comes first. | |
705 SetConfigs("a", 1100, 1, | |
706 "b", 900, 1, | |
707 nullptr); | |
708 test_peer_.CheckConfigs( | |
709 "a", false, | |
710 "b", true, | |
711 nullptr); | |
712 } | |
713 | |
714 TEST_F(CryptoServerConfigsTest, MakePrimarySecond) { | |
715 // Make sure that a remains primary after b is added. | |
716 SetConfigs("a", 900, 1, | |
717 "b", 1100, 1, | |
718 nullptr); | |
719 test_peer_.CheckConfigs( | |
720 "a", true, | |
721 "b", false, | |
722 nullptr); | |
723 } | |
724 | |
725 TEST_F(CryptoServerConfigsTest, Delete) { | |
726 // Ensure that configs get deleted when removed. | |
727 SetConfigs("a", 800, 1, | |
728 "b", 900, 1, | |
729 "c", 1100, 1, | |
730 nullptr); | |
731 test_peer_.CheckConfigs( | |
732 "a", false, | |
733 "b", true, | |
734 "c", false, | |
735 nullptr); | |
736 SetConfigs("b", 900, 1, | |
737 "c", 1100, 1, | |
738 nullptr); | |
739 test_peer_.CheckConfigs( | |
740 "b", true, | |
741 "c", false, | |
742 nullptr); | |
743 } | |
744 | |
745 TEST_F(CryptoServerConfigsTest, DeletePrimary) { | |
746 // Ensure that deleting the primary config works. | |
747 SetConfigs("a", 800, 1, | |
748 "b", 900, 1, | |
749 "c", 1100, 1, | |
750 nullptr); | |
751 test_peer_.CheckConfigs( | |
752 "a", false, | |
753 "b", true, | |
754 "c", false, | |
755 nullptr); | |
756 SetConfigs("a", 800, 1, | |
757 "c", 1100, 1, | |
758 nullptr); | |
759 test_peer_.CheckConfigs( | |
760 "a", true, | |
761 "c", false, | |
762 nullptr); | |
763 } | |
764 | |
765 TEST_F(CryptoServerConfigsTest, FailIfDeletingAllConfigs) { | |
766 // Ensure that configs get deleted when removed. | |
767 SetConfigs("a", 800, 1, | |
768 "b", 900, 1, | |
769 nullptr); | |
770 test_peer_.CheckConfigs( | |
771 "a", false, | |
772 "b", true, | |
773 nullptr); | |
774 SetConfigs(nullptr); | |
775 // Config change is rejected, still using old configs. | |
776 test_peer_.CheckConfigs( | |
777 "a", false, | |
778 "b", true, | |
779 nullptr); | |
780 } | |
781 | |
782 TEST_F(CryptoServerConfigsTest, ChangePrimaryTime) { | |
783 // Check that updates to primary time get picked up. | |
784 SetConfigs("a", 400, 1, | |
785 "b", 800, 1, | |
786 "c", 1200, 1, | |
787 nullptr); | |
788 test_peer_.SelectNewPrimaryConfig(500); | |
789 test_peer_.CheckConfigs( | |
790 "a", true, | |
791 "b", false, | |
792 "c", false, | |
793 nullptr); | |
794 SetConfigs("a", 1200, 1, | |
795 "b", 800, 1, | |
796 "c", 400, 1, | |
797 nullptr); | |
798 test_peer_.SelectNewPrimaryConfig(500); | |
799 test_peer_.CheckConfigs( | |
800 "a", false, | |
801 "b", false, | |
802 "c", true, | |
803 nullptr); | |
804 } | |
805 | |
806 TEST_F(CryptoServerConfigsTest, AllConfigsInThePast) { | |
807 // Check that the most recent config is selected. | |
808 SetConfigs("a", 400, 1, | |
809 "b", 800, 1, | |
810 "c", 1200, 1, | |
811 nullptr); | |
812 test_peer_.SelectNewPrimaryConfig(1500); | |
813 test_peer_.CheckConfigs( | |
814 "a", false, | |
815 "b", false, | |
816 "c", true, | |
817 nullptr); | |
818 } | |
819 | |
820 TEST_F(CryptoServerConfigsTest, AllConfigsInTheFuture) { | |
821 // Check that the first config is selected. | |
822 SetConfigs("a", 400, 1, | |
823 "b", 800, 1, | |
824 "c", 1200, 1, | |
825 nullptr); | |
826 test_peer_.SelectNewPrimaryConfig(100); | |
827 test_peer_.CheckConfigs( | |
828 "a", true, | |
829 "b", false, | |
830 "c", false, | |
831 nullptr); | |
832 } | |
833 | |
834 TEST_F(CryptoServerConfigsTest, SortByPriority) { | |
835 // Check that priority is used to decide on a primary config when | |
836 // configs have the same primary time. | |
837 SetConfigs("a", 900, 1, | |
838 "b", 900, 2, | |
839 "c", 900, 3, | |
840 nullptr); | |
841 test_peer_.CheckConfigs( | |
842 "a", true, | |
843 "b", false, | |
844 "c", false, | |
845 nullptr); | |
846 test_peer_.SelectNewPrimaryConfig(800); | |
847 test_peer_.CheckConfigs( | |
848 "a", true, | |
849 "b", false, | |
850 "c", false, | |
851 nullptr); | |
852 test_peer_.SelectNewPrimaryConfig(1000); | |
853 test_peer_.CheckConfigs( | |
854 "a", true, | |
855 "b", false, | |
856 "c", false, | |
857 nullptr); | |
858 | |
859 // Change priorities and expect sort order to change. | |
860 SetConfigs("a", 900, 2, | |
861 "b", 900, 1, | |
862 "c", 900, 0, | |
863 nullptr); | |
864 test_peer_.CheckConfigs( | |
865 "a", false, | |
866 "b", false, | |
867 "c", true, | |
868 nullptr); | |
869 test_peer_.SelectNewPrimaryConfig(800); | |
870 test_peer_.CheckConfigs( | |
871 "a", false, | |
872 "b", false, | |
873 "c", true, | |
874 nullptr); | |
875 test_peer_.SelectNewPrimaryConfig(1000); | |
876 test_peer_.CheckConfigs( | |
877 "a", false, | |
878 "b", false, | |
879 "c", true, | |
880 nullptr); | |
881 } | |
882 | |
883 TEST_F(CryptoServerConfigsTest, AdvancePrimary) { | |
884 // Check that a new primary config is enabled at the right time. | |
885 SetConfigs("a", 900, 1, | |
886 "b", 1100, 1, | |
887 nullptr); | |
888 test_peer_.SelectNewPrimaryConfig(1000); | |
889 test_peer_.CheckConfigs( | |
890 "a", true, | |
891 "b", false, | |
892 nullptr); | |
893 test_peer_.SelectNewPrimaryConfig(1101); | |
894 test_peer_.CheckConfigs( | |
895 "a", false, | |
896 "b", true, | |
897 nullptr); | |
898 } | |
899 | |
900 TEST_F(CryptoServerConfigsTest, InvalidConfigs) { | |
901 // Ensure that invalid configs don't change anything. | |
902 SetConfigs("a", 800, 1, | |
903 "b", 900, 1, | |
904 "c", 1100, 1, | |
905 nullptr); | |
906 test_peer_.CheckConfigs( | |
907 "a", false, | |
908 "b", true, | |
909 "c", false, | |
910 nullptr); | |
911 SetConfigs("a", 800, 1, | |
912 "c", 1100, 1, | |
913 "INVALID1", 1000, 1, | |
914 nullptr); | |
915 test_peer_.CheckConfigs( | |
916 "a", false, | |
917 "b", true, | |
918 "c", false, | |
919 nullptr); | |
920 } | |
921 | |
922 } // namespace test | |
923 } // namespace net | |
OLD | NEW |