1 // Copyright (c) 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/crypto_handshake.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_server_config.h" 12 #include "net/quic/crypto/crypto_server_config_protobuf.h" 13 #include "net/quic/crypto/quic_random.h" 14 #include "net/quic/quic_time.h" 15 #include "net/quic/test_tools/mock_clock.h" 16 #include "testing/gmock/include/gmock/gmock.h" 17 #include "testing/gtest/include/gtest/gtest.h" 18 19 using base::StringPiece; 20 using std::make_pair; 21 using std::map; 22 using std::pair; 23 using std::string; 24 using std::vector; 25 26 namespace net { 27 namespace test { 28 29 class QuicCryptoServerConfigPeer { 30 public: 31 explicit QuicCryptoServerConfigPeer(QuicCryptoServerConfig* server_config) 32 : server_config_(server_config) {} 33 34 string NewSourceAddressToken(IPEndPoint ip, 35 QuicRandom* rand, 36 QuicWallTime now) { 37 return server_config_->NewSourceAddressToken(ip, rand, now); 38 } 39 40 bool ValidateSourceAddressToken(StringPiece srct, 41 IPEndPoint ip, 42 QuicWallTime now) { 43 return server_config_->ValidateSourceAddressToken(srct, ip, now); 44 } 45 46 // CheckConfigs compares the state of the Configs in |server_config_| to the 47 // description given as arguments. The arguments are given as NULL-terminated 48 // pairs. The first of each pair is the server config ID of a Config. The 49 // second is a boolean describing whether the config is the primary. For 50 // example: 51 // CheckConfigs(NULL); // checks that no Configs are loaded. 52 // 53 // // Checks that exactly three Configs are loaded with the given IDs and 54 // // status. 55 // CheckConfigs( 56 // "id1", false, 57 // "id2", true, 58 // "id3", false, 59 // NULL); 60 void CheckConfigs(const char* server_config_id1, ...) { 61 va_list ap; 62 va_start(ap, server_config_id1); 63 64 vector<pair<ServerConfigID, bool> > expected; 65 bool first = true; 66 for (;;) { 67 const char* server_config_id; 68 if (first) { 69 server_config_id = server_config_id1; 70 first = false; 71 } else { 72 server_config_id = va_arg(ap, const char*); 73 } 74 75 if (!server_config_id) { 76 break; 77 } 78 79 // varargs will promote the value to an int so we have to read that from 80 // the stack and cast down. 81 const bool is_primary = static_cast<bool>(va_arg(ap, int)); 82 expected.push_back(make_pair(server_config_id, is_primary)); 83 } 84 85 va_end(ap); 86 87 base::AutoLock locked(server_config_->configs_lock_); 88 89 ASSERT_EQ(expected.size(), server_config_->configs_.size()) 90 << ConfigsDebug(); 91 92 for (QuicCryptoServerConfig::ConfigMap::const_iterator 93 i = server_config_->configs_.begin(); 94 i != server_config_->configs_.end(); ++i) { 95 bool found = false; 96 for (vector<pair<ServerConfigID, bool> >::iterator j = expected.begin(); 97 j != expected.end(); ++j) { 98 if (i->first == j->first && i->second->is_primary == j->second) { 99 found = true; 100 j->first.clear(); 101 break; 102 } 103 } 104 105 ASSERT_TRUE(found) << "Failed to find match for " << i->first 106 << " in configs:\n" << ConfigsDebug(); 107 } 108 } 109 110 // ConfigsDebug returns a string that contains debugging information about 111 // the set of Configs loaded in |server_config_| and their status. 112 // ConfigsDebug() should be called after acquiring 113 // server_config_->configs_lock_. 114 string ConfigsDebug() { 115 if (server_config_->configs_.empty()) { 116 return "No Configs in QuicCryptoServerConfig"; 117 } 118 119 string s; 120 121 for (QuicCryptoServerConfig::ConfigMap::const_iterator 122 i = server_config_->configs_.begin(); 123 i != server_config_->configs_.end(); ++i) { 124 const scoped_refptr<QuicCryptoServerConfig::Config> config = i->second; 125 if (config->is_primary) { 126 s += "(primary) "; 127 } else { 128 s += " "; 129 } 130 s += config->id; 131 s += "\n"; 132 } 133 134 return s; 135 } 136 137 void SelectNewPrimaryConfig(int seconds) { 138 base::AutoLock locked(server_config_->configs_lock_); 139 server_config_->SelectNewPrimaryConfig( 140 QuicWallTime::FromUNIXSeconds(seconds)); 141 } 142 143 private: 144 const QuicCryptoServerConfig* server_config_; 145 }; 146 147 TEST(QuicCryptoServerConfigTest, ServerConfig) { 148 QuicRandom* rand = QuicRandom::GetInstance(); 149 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand); 150 MockClock clock; 151 152 scoped_ptr<CryptoHandshakeMessage>( 153 server.AddDefaultConfig(rand, &clock, 154 QuicCryptoServerConfig::ConfigOptions())); 155 } 156 157 TEST(QuicCryptoServerConfigTest, SourceAddressTokens) { 158 if (!Aes128Gcm12Encrypter::IsSupported()) { 159 LOG(INFO) << "AES GCM not supported. Test skipped."; 160 return; 161 } 162 163 QuicRandom* rand = QuicRandom::GetInstance(); 164 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand); 165 IPAddressNumber ip; 166 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip)); 167 IPEndPoint ip4 = IPEndPoint(ip, 1); 168 CHECK(ParseIPLiteralToNumber("2001:db8:0::42", &ip)); 169 IPEndPoint ip6 = IPEndPoint(ip, 2); 170 MockClock clock; 171 clock.AdvanceTime(QuicTime::Delta::FromSeconds(1000000)); 172 QuicCryptoServerConfigPeer peer(&server); 173 174 QuicWallTime now = clock.WallNow(); 175 const QuicWallTime original_time = now; 176 177 const string token4 = peer.NewSourceAddressToken(ip4, rand, now); 178 const string token6 = peer.NewSourceAddressToken(ip6, rand, now); 179 EXPECT_TRUE(peer.ValidateSourceAddressToken(token4, ip4, now)); 180 EXPECT_FALSE(peer.ValidateSourceAddressToken(token4, ip6, now)); 181 EXPECT_TRUE(peer.ValidateSourceAddressToken(token6, ip6, now)); 182 183 now = original_time.Add(QuicTime::Delta::FromSeconds(86400 * 7)); 184 EXPECT_FALSE(peer.ValidateSourceAddressToken(token4, ip4, now)); 185 186 now = original_time.Subtract(QuicTime::Delta::FromSeconds(3600 * 2)); 187 EXPECT_FALSE(peer.ValidateSourceAddressToken(token4, ip4, now)); 188 } 189 190 class CryptoServerConfigsTest : public ::testing::Test { 191 public: 192 CryptoServerConfigsTest() 193 : rand_(QuicRandom::GetInstance()), 194 config_(QuicCryptoServerConfig::TESTING, rand_), 195 test_peer_(&config_) {} 196 197 virtual void SetUp() { 198 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1000)); 199 } 200 201 // SetConfigs constructs suitable config protobufs and calls SetConfigs on 202 // |config_|. The arguments are given as NULL-terminated pairs. The first of 203 // each pair is the server config ID of a Config. The second is the 204 // |primary_time| of that Config, given in epoch seconds. (Although note 205 // that, in these tests, time is set to 1000 seconds since the epoch.) For 206 // example: 207 // SetConfigs(NULL); // calls |config_.SetConfigs| with no protobufs. 208 // 209 // // Calls |config_.SetConfigs| with two protobufs: one for a Config with 210 // // a |primary_time| of 900, and another with a |primary_time| of 1000. 211 // CheckConfigs( 212 // "id1", 900, 213 // "id2", 1000, 214 // NULL); 215 // 216 // If the server config id starts with "INVALID" then the generated protobuf 217 // will be invalid. 218 void SetConfigs(const char* server_config_id1, ...) { 219 va_list ap; 220 va_start(ap, server_config_id1); 221 bool has_invalid = false; 222 223 vector<QuicServerConfigProtobuf*> protobufs; 224 bool first = true; 225 for (;;) { 226 const char* server_config_id; 227 if (first) { 228 server_config_id = server_config_id1; 229 first = false; 230 } else { 231 server_config_id = va_arg(ap, const char*); 232 } 233 234 if (!server_config_id) { 235 break; 236 } 237 238 int primary_time = va_arg(ap, int); 239 240 QuicCryptoServerConfig::ConfigOptions options; 241 options.id = server_config_id; 242 QuicServerConfigProtobuf* protobuf( 243 QuicCryptoServerConfig::DefaultConfig(rand_, &clock_, options)); 244 protobuf->set_primary_time(primary_time); 245 if (string(server_config_id).find("INVALID") == 0) { 246 protobuf->clear_key(); 247 has_invalid = true; 248 } 249 protobufs.push_back(protobuf); 250 } 251 252 ASSERT_EQ(!has_invalid, config_.SetConfigs(protobufs, clock_.WallNow())); 253 STLDeleteElements(&protobufs); 254 } 255 256 protected: 257 QuicRandom* const rand_; 258 MockClock clock_; 259 QuicCryptoServerConfig config_; 260 QuicCryptoServerConfigPeer test_peer_; 261 }; 262 263 TEST_F(CryptoServerConfigsTest, NoConfigs) { 264 test_peer_.CheckConfigs(NULL); 265 } 266 267 TEST_F(CryptoServerConfigsTest, MakePrimaryFirst) { 268 // Make sure that "b" is primary even though "a" comes first. 269 SetConfigs("a", 1100, 270 "b", 900, 271 NULL); 272 test_peer_.CheckConfigs( 273 "a", false, 274 "b", true, 275 NULL); 276 } 277 278 TEST_F(CryptoServerConfigsTest, MakePrimarySecond) { 279 // Make sure that a remains primary after b is added. 280 SetConfigs("a", 900, 281 "b", 1100, 282 NULL); 283 test_peer_.CheckConfigs( 284 "a", true, 285 "b", false, 286 NULL); 287 } 288 289 TEST_F(CryptoServerConfigsTest, Delete) { 290 // Ensure that configs get deleted when removed. 291 SetConfigs("a", 800, 292 "b", 900, 293 "c", 1100, 294 NULL); 295 SetConfigs("b", 900, 296 "c", 1100, 297 NULL); 298 test_peer_.CheckConfigs( 299 "b", true, 300 "c", false, 301 NULL); 302 } 303 304 TEST_F(CryptoServerConfigsTest, DontDeletePrimary) { 305 // Ensure that the primary config isn't deleted when removed. 306 SetConfigs("a", 800, 307 "b", 900, 308 "c", 1100, 309 NULL); 310 SetConfigs("a", 800, 311 "c", 1100, 312 NULL); 313 test_peer_.CheckConfigs( 314 "a", false, 315 "b", true, 316 "c", false, 317 NULL); 318 } 319 320 TEST_F(CryptoServerConfigsTest, AdvancePrimary) { 321 // Check that a new primary config is enabled at the right time. 322 SetConfigs("a", 900, 323 "b", 1100, 324 NULL); 325 test_peer_.SelectNewPrimaryConfig(1000); 326 test_peer_.CheckConfigs( 327 "a", true, 328 "b", false, 329 NULL); 330 test_peer_.SelectNewPrimaryConfig(1101); 331 test_peer_.CheckConfigs( 332 "a", false, 333 "b", true, 334 NULL); 335 } 336 337 TEST_F(CryptoServerConfigsTest, InvalidConfigs) { 338 // Ensure that invalid configs don't change anything. 339 SetConfigs("a", 800, 340 "b", 900, 341 "c", 1100, 342 NULL); 343 test_peer_.CheckConfigs( 344 "a", false, 345 "b", true, 346 "c", false, 347 NULL); 348 SetConfigs("a", 800, 349 "c", 1100, 350 "INVALID1", 1000, 351 NULL); 352 test_peer_.CheckConfigs( 353 "a", false, 354 "b", true, 355 "c", false, 356 NULL); 357 } 358 359 } // namespace test 360 } // namespace net 361