| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/base/transport_security_state.h" | 5 #include "net/base/transport_security_state.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 class TransportSecurityStateTest : public testing::Test { | 38 class TransportSecurityStateTest : public testing::Test { |
| 39 virtual void SetUp() { | 39 virtual void SetUp() { |
| 40 #if defined(USE_OPENSSL) | 40 #if defined(USE_OPENSSL) |
| 41 crypto::EnsureOpenSSLInit(); | 41 crypto::EnsureOpenSSLInit(); |
| 42 #else | 42 #else |
| 43 crypto::EnsureNSSInit(); | 43 crypto::EnsureNSSInit(); |
| 44 #endif | 44 #endif |
| 45 } | 45 } |
| 46 }; | 46 }; |
| 47 | 47 |
| 48 TEST_F(TransportSecurityStateTest, BogusHeaders) { | |
| 49 TransportSecurityState::DomainState state; | |
| 50 base::Time now = base::Time::Now(); | |
| 51 | |
| 52 EXPECT_FALSE(state.ParseSTSHeader(now, "")); | |
| 53 EXPECT_FALSE(state.ParseSTSHeader(now, " ")); | |
| 54 EXPECT_FALSE(state.ParseSTSHeader(now, "abc")); | |
| 55 EXPECT_FALSE(state.ParseSTSHeader(now, " abc")); | |
| 56 EXPECT_FALSE(state.ParseSTSHeader(now, " abc ")); | |
| 57 EXPECT_FALSE(state.ParseSTSHeader(now, "max-age")); | |
| 58 EXPECT_FALSE(state.ParseSTSHeader(now, " max-age")); | |
| 59 EXPECT_FALSE(state.ParseSTSHeader(now, " max-age ")); | |
| 60 EXPECT_FALSE(state.ParseSTSHeader(now, "max-age=")); | |
| 61 EXPECT_FALSE(state.ParseSTSHeader(now, " max-age=")); | |
| 62 EXPECT_FALSE(state.ParseSTSHeader(now, " max-age =")); | |
| 63 EXPECT_FALSE(state.ParseSTSHeader(now, " max-age= ")); | |
| 64 EXPECT_FALSE(state.ParseSTSHeader(now, " max-age = ")); | |
| 65 EXPECT_FALSE(state.ParseSTSHeader(now, " max-age = xy")); | |
| 66 EXPECT_FALSE(state.ParseSTSHeader(now, " max-age = 3488a923")); | |
| 67 EXPECT_FALSE(state.ParseSTSHeader(now, "max-age=3488a923 ")); | |
| 68 EXPECT_FALSE(state.ParseSTSHeader(now, "max-ag=3488923")); | |
| 69 EXPECT_FALSE(state.ParseSTSHeader(now, "max-aged=3488923")); | |
| 70 EXPECT_FALSE(state.ParseSTSHeader(now, "max-age==3488923")); | |
| 71 EXPECT_FALSE(state.ParseSTSHeader(now, "amax-age=3488923")); | |
| 72 EXPECT_FALSE(state.ParseSTSHeader(now, "max-age=-3488923")); | |
| 73 EXPECT_FALSE(state.ParseSTSHeader(now, "max-age=3488923;")); | |
| 74 EXPECT_FALSE(state.ParseSTSHeader(now, "max-age=3488923 e")); | |
| 75 EXPECT_FALSE(state.ParseSTSHeader( | |
| 76 now, "max-age=3488923 includesubdomain")); | |
| 77 EXPECT_FALSE(state.ParseSTSHeader(now, "max-age=3488923includesubdomains")); | |
| 78 EXPECT_FALSE(state.ParseSTSHeader(now, "max-age=3488923=includesubdomains")); | |
| 79 EXPECT_FALSE(state.ParseSTSHeader(now, "max-age=3488923 includesubdomainx")); | |
| 80 EXPECT_FALSE(state.ParseSTSHeader(now, "max-age=3488923 includesubdomain=")); | |
| 81 EXPECT_FALSE(state.ParseSTSHeader( | |
| 82 now, "max-age=3488923 includesubdomain=true")); | |
| 83 EXPECT_FALSE(state.ParseSTSHeader(now, "max-age=3488923 includesubdomainsx")); | |
| 84 EXPECT_FALSE(state.ParseSTSHeader( | |
| 85 now, "max-age=3488923 includesubdomains x")); | |
| 86 EXPECT_FALSE(state.ParseSTSHeader(now, "max-age=34889.23 includesubdomains")); | |
| 87 EXPECT_FALSE(state.ParseSTSHeader(now, "max-age=34889 includesubdomains")); | |
| 88 | |
| 89 // Check that |state| was not updated by expecting the default | |
| 90 // values for its predictable fields. | |
| 91 EXPECT_EQ(state.upgrade_mode, | |
| 92 TransportSecurityState::DomainState::MODE_FORCE_HTTPS); | |
| 93 EXPECT_FALSE(state.include_subdomains); | |
| 94 } | |
| 95 | |
| 96 static bool GetPublicKeyHash(const net::X509Certificate::OSCertHandle& cert, | |
| 97 HashValue* hash) { | |
| 98 std::string der_bytes; | |
| 99 if (!net::X509Certificate::GetDEREncoded(cert, &der_bytes)) | |
| 100 return false; | |
| 101 | |
| 102 base::StringPiece spki; | |
| 103 if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki)) | |
| 104 return false; | |
| 105 | |
| 106 switch (hash->tag) { | |
| 107 case HASH_VALUE_SHA1: | |
| 108 base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(spki.data()), | |
| 109 spki.size(), hash->data()); | |
| 110 break; | |
| 111 case HASH_VALUE_SHA256: | |
| 112 crypto::SHA256HashString(spki, hash->data(), crypto::kSHA256Length); | |
| 113 break; | |
| 114 default: | |
| 115 NOTREACHED() << "Unknown HashValueTag " << hash->tag; | |
| 116 } | |
| 117 | |
| 118 return true; | |
| 119 } | |
| 120 | |
| 121 static std::string GetPinFromCert(X509Certificate* cert, HashValueTag tag) { | |
| 122 HashValue spki_hash(tag); | |
| 123 EXPECT_TRUE(GetPublicKeyHash(cert->os_cert_handle(), &spki_hash)); | |
| 124 | |
| 125 std::string base64; | |
| 126 base::Base64Encode(base::StringPiece( | |
| 127 reinterpret_cast<char*>(spki_hash.data()), spki_hash.size()), &base64); | |
| 128 | |
| 129 std::string label; | |
| 130 switch (tag) { | |
| 131 case HASH_VALUE_SHA1: | |
| 132 label = "pin-sha1="; | |
| 133 break; | |
| 134 case HASH_VALUE_SHA256: | |
| 135 label = "pin-sha256="; | |
| 136 break; | |
| 137 default: | |
| 138 NOTREACHED() << "Unknown HashValueTag " << tag; | |
| 139 } | |
| 140 | |
| 141 return label + HttpUtil::Quote(base64); | |
| 142 } | |
| 143 | |
| 144 static void TestBogusPinsHeaders(HashValueTag tag) { | |
| 145 TransportSecurityState::DomainState state; | |
| 146 SSLInfo ssl_info; | |
| 147 ssl_info.cert = | |
| 148 ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem"); | |
| 149 std::string good_pin = GetPinFromCert(ssl_info.cert, tag); | |
| 150 base::Time now = base::Time::Now(); | |
| 151 | |
| 152 // The backup pin is fake --- it just has to not be in the chain. | |
| 153 std::string backup_pin = "pin-sha1=" + | |
| 154 HttpUtil::Quote("6dcfXufJLW3J6S/9rRe4vUlBj5g="); | |
| 155 | |
| 156 EXPECT_FALSE(state.ParsePinsHeader(now, "", ssl_info)); | |
| 157 EXPECT_FALSE(state.ParsePinsHeader(now, " ", ssl_info)); | |
| 158 EXPECT_FALSE(state.ParsePinsHeader(now, "abc", ssl_info)); | |
| 159 EXPECT_FALSE(state.ParsePinsHeader(now, " abc", ssl_info)); | |
| 160 EXPECT_FALSE(state.ParsePinsHeader(now, " abc ", ssl_info)); | |
| 161 EXPECT_FALSE(state.ParsePinsHeader(now, "max-age", ssl_info)); | |
| 162 EXPECT_FALSE(state.ParsePinsHeader(now, " max-age", ssl_info)); | |
| 163 EXPECT_FALSE(state.ParsePinsHeader(now, " max-age ", ssl_info)); | |
| 164 EXPECT_FALSE(state.ParsePinsHeader(now, "max-age=", ssl_info)); | |
| 165 EXPECT_FALSE(state.ParsePinsHeader(now, " max-age=", ssl_info)); | |
| 166 EXPECT_FALSE(state.ParsePinsHeader(now, " max-age =", ssl_info)); | |
| 167 EXPECT_FALSE(state.ParsePinsHeader(now, " max-age= ", ssl_info)); | |
| 168 EXPECT_FALSE(state.ParsePinsHeader(now, " max-age = ", ssl_info)); | |
| 169 EXPECT_FALSE(state.ParsePinsHeader(now, " max-age = xy", ssl_info)); | |
| 170 EXPECT_FALSE(state.ParsePinsHeader( | |
| 171 now, | |
| 172 " max-age = 3488a923", | |
| 173 ssl_info)); | |
| 174 EXPECT_FALSE(state.ParsePinsHeader(now, "max-age=3488a923 ", ssl_info)); | |
| 175 EXPECT_FALSE(state.ParsePinsHeader(now, | |
| 176 "max-ag=3488923pins=" + good_pin + "," + backup_pin, | |
| 177 ssl_info)); | |
| 178 EXPECT_FALSE(state.ParsePinsHeader(now, "max-aged=3488923" + backup_pin, | |
| 179 ssl_info)); | |
| 180 EXPECT_FALSE(state.ParsePinsHeader(now, "max-aged=3488923; " + backup_pin, | |
| 181 ssl_info)); | |
| 182 EXPECT_FALSE(state.ParsePinsHeader(now, | |
| 183 "max-aged=3488923; " + backup_pin + ";" + backup_pin, | |
| 184 ssl_info)); | |
| 185 EXPECT_FALSE(state.ParsePinsHeader(now, | |
| 186 "max-aged=3488923; " + good_pin + ";" + good_pin, | |
| 187 ssl_info)); | |
| 188 EXPECT_FALSE(state.ParsePinsHeader(now, "max-aged=3488923; " + good_pin, | |
| 189 ssl_info)); | |
| 190 EXPECT_FALSE(state.ParsePinsHeader(now, "max-age==3488923", ssl_info)); | |
| 191 EXPECT_FALSE(state.ParsePinsHeader(now, "amax-age=3488923", ssl_info)); | |
| 192 EXPECT_FALSE(state.ParsePinsHeader(now, "max-age=-3488923", ssl_info)); | |
| 193 EXPECT_FALSE(state.ParsePinsHeader(now, "max-age=3488923;", ssl_info)); | |
| 194 EXPECT_FALSE(state.ParsePinsHeader(now, "max-age=3488923 e", ssl_info)); | |
| 195 EXPECT_FALSE(state.ParsePinsHeader( | |
| 196 now, | |
| 197 "max-age=3488923 includesubdomain", | |
| 198 ssl_info)); | |
| 199 EXPECT_FALSE(state.ParsePinsHeader(now, "max-age=34889.23", ssl_info)); | |
| 200 | |
| 201 // Check that |state| was not updated by expecting the default | |
| 202 // values for its predictable fields. | |
| 203 EXPECT_EQ(state.upgrade_mode, | |
| 204 TransportSecurityState::DomainState::MODE_FORCE_HTTPS); | |
| 205 EXPECT_FALSE(state.include_subdomains); | |
| 206 } | |
| 207 | |
| 208 TEST_F(TransportSecurityStateTest, BogusPinsHeadersSHA1) { | |
| 209 TestBogusPinsHeaders(HASH_VALUE_SHA1); | |
| 210 } | |
| 211 | |
| 212 TEST_F(TransportSecurityStateTest, BogusPinsHeadersSHA256) { | |
| 213 TestBogusPinsHeaders(HASH_VALUE_SHA256); | |
| 214 } | |
| 215 | |
| 216 TEST_F(TransportSecurityStateTest, ValidSTSHeaders) { | |
| 217 TransportSecurityState::DomainState state; | |
| 218 base::Time expiry; | |
| 219 base::Time now = base::Time::Now(); | |
| 220 | |
| 221 EXPECT_TRUE(state.ParseSTSHeader(now, "max-age=243")); | |
| 222 expiry = now + base::TimeDelta::FromSeconds(243); | |
| 223 EXPECT_EQ(expiry, state.upgrade_expiry); | |
| 224 EXPECT_FALSE(state.include_subdomains); | |
| 225 | |
| 226 EXPECT_TRUE(state.ParseSTSHeader(now, " Max-agE = 567")); | |
| 227 expiry = now + base::TimeDelta::FromSeconds(567); | |
| 228 EXPECT_EQ(expiry, state.upgrade_expiry); | |
| 229 EXPECT_FALSE(state.include_subdomains); | |
| 230 | |
| 231 EXPECT_TRUE(state.ParseSTSHeader(now, " mAx-aGe = 890 ")); | |
| 232 expiry = now + base::TimeDelta::FromSeconds(890); | |
| 233 EXPECT_EQ(expiry, state.upgrade_expiry); | |
| 234 EXPECT_FALSE(state.include_subdomains); | |
| 235 | |
| 236 EXPECT_TRUE(state.ParseSTSHeader(now, "max-age=123;incLudesUbdOmains")); | |
| 237 expiry = now + base::TimeDelta::FromSeconds(123); | |
| 238 EXPECT_EQ(expiry, state.upgrade_expiry); | |
| 239 EXPECT_TRUE(state.include_subdomains); | |
| 240 | |
| 241 EXPECT_TRUE(state.ParseSTSHeader(now, "incLudesUbdOmains; max-age=123")); | |
| 242 expiry = now + base::TimeDelta::FromSeconds(123); | |
| 243 EXPECT_EQ(expiry, state.upgrade_expiry); | |
| 244 EXPECT_TRUE(state.include_subdomains); | |
| 245 | |
| 246 EXPECT_TRUE(state.ParseSTSHeader(now, " incLudesUbdOmains; max-age=123")); | |
| 247 expiry = now + base::TimeDelta::FromSeconds(123); | |
| 248 EXPECT_EQ(expiry, state.upgrade_expiry); | |
| 249 EXPECT_TRUE(state.include_subdomains); | |
| 250 | |
| 251 EXPECT_TRUE(state.ParseSTSHeader(now, | |
| 252 " incLudesUbdOmains; max-age=123; pumpkin=kitten")); | |
| 253 expiry = now + base::TimeDelta::FromSeconds(123); | |
| 254 EXPECT_EQ(expiry, state.upgrade_expiry); | |
| 255 EXPECT_TRUE(state.include_subdomains); | |
| 256 | |
| 257 EXPECT_TRUE(state.ParseSTSHeader(now, | |
| 258 " pumpkin=894; incLudesUbdOmains; max-age=123 ")); | |
| 259 expiry = now + base::TimeDelta::FromSeconds(123); | |
| 260 EXPECT_EQ(expiry, state.upgrade_expiry); | |
| 261 EXPECT_TRUE(state.include_subdomains); | |
| 262 | |
| 263 EXPECT_TRUE(state.ParseSTSHeader(now, | |
| 264 " pumpkin; incLudesUbdOmains; max-age=123 ")); | |
| 265 expiry = now + base::TimeDelta::FromSeconds(123); | |
| 266 EXPECT_EQ(expiry, state.upgrade_expiry); | |
| 267 EXPECT_TRUE(state.include_subdomains); | |
| 268 | |
| 269 EXPECT_TRUE(state.ParseSTSHeader(now, | |
| 270 " pumpkin; incLudesUbdOmains; max-age=\"123\" ")); | |
| 271 expiry = now + base::TimeDelta::FromSeconds(123); | |
| 272 EXPECT_EQ(expiry, state.upgrade_expiry); | |
| 273 EXPECT_TRUE(state.include_subdomains); | |
| 274 | |
| 275 EXPECT_TRUE(state.ParseSTSHeader(now, | |
| 276 "animal=\"squirrel; distinguished\"; incLudesUbdOmains; max-age=123")); | |
| 277 expiry = now + base::TimeDelta::FromSeconds(123); | |
| 278 EXPECT_EQ(expiry, state.upgrade_expiry); | |
| 279 EXPECT_TRUE(state.include_subdomains); | |
| 280 | |
| 281 EXPECT_TRUE(state.ParseSTSHeader(now, "max-age=394082; incLudesUbdOmains")); | |
| 282 expiry = now + base::TimeDelta::FromSeconds(394082); | |
| 283 EXPECT_EQ(expiry, state.upgrade_expiry); | |
| 284 EXPECT_TRUE(state.include_subdomains); | |
| 285 | |
| 286 EXPECT_TRUE(state.ParseSTSHeader( | |
| 287 now, "max-age=39408299 ;incLudesUbdOmains")); | |
| 288 expiry = now + base::TimeDelta::FromSeconds( | |
| 289 std::min(TransportSecurityState::kMaxHSTSAgeSecs, 39408299l)); | |
| 290 EXPECT_EQ(expiry, state.upgrade_expiry); | |
| 291 EXPECT_TRUE(state.include_subdomains); | |
| 292 | |
| 293 EXPECT_TRUE(state.ParseSTSHeader( | |
| 294 now, "max-age=394082038 ; incLudesUbdOmains")); | |
| 295 expiry = now + base::TimeDelta::FromSeconds( | |
| 296 std::min(TransportSecurityState::kMaxHSTSAgeSecs, 394082038l)); | |
| 297 EXPECT_EQ(expiry, state.upgrade_expiry); | |
| 298 EXPECT_TRUE(state.include_subdomains); | |
| 299 | |
| 300 EXPECT_TRUE(state.ParseSTSHeader( | |
| 301 now, " max-age=0 ; incLudesUbdOmains ")); | |
| 302 expiry = now + base::TimeDelta::FromSeconds(0); | |
| 303 EXPECT_EQ(expiry, state.upgrade_expiry); | |
| 304 EXPECT_TRUE(state.include_subdomains); | |
| 305 // When max-age == 0, we downgrade to MODE_DEFAULT rather than deleting | |
| 306 // the entire DomainState. (That is because we currently overload | |
| 307 // DomainState to also include pins, and we don't want to invalidate any | |
| 308 // opportunistic pins that may be in place.) | |
| 309 EXPECT_EQ(TransportSecurityState::DomainState::MODE_DEFAULT, | |
| 310 state.upgrade_mode); | |
| 311 | |
| 312 EXPECT_TRUE(state.ParseSTSHeader( | |
| 313 now, | |
| 314 " max-age=999999999999999999999999999999999999999999999 ;" | |
| 315 " incLudesUbdOmains ")); | |
| 316 expiry = now + base::TimeDelta::FromSeconds( | |
| 317 TransportSecurityState::kMaxHSTSAgeSecs); | |
| 318 EXPECT_EQ(expiry, state.upgrade_expiry); | |
| 319 EXPECT_TRUE(state.include_subdomains); | |
| 320 } | |
| 321 | |
| 322 static void TestValidPinsHeaders(HashValueTag tag) { | |
| 323 TransportSecurityState::DomainState state; | |
| 324 base::Time expiry; | |
| 325 base::Time now = base::Time::Now(); | |
| 326 | |
| 327 // Set up a realistic SSLInfo with a realistic cert chain. | |
| 328 FilePath certs_dir = GetTestCertsDirectory(); | |
| 329 scoped_refptr<X509Certificate> ee_cert = | |
| 330 ImportCertFromFile(certs_dir, "2048-rsa-ee-by-2048-rsa-intermediate.pem"); | |
| 331 ASSERT_NE(static_cast<X509Certificate*>(NULL), ee_cert); | |
| 332 scoped_refptr<X509Certificate> intermediate = | |
| 333 ImportCertFromFile(certs_dir, "2048-rsa-intermediate.pem"); | |
| 334 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate); | |
| 335 X509Certificate::OSCertHandles intermediates; | |
| 336 intermediates.push_back(intermediate->os_cert_handle()); | |
| 337 SSLInfo ssl_info; | |
| 338 ssl_info.cert = X509Certificate::CreateFromHandle(ee_cert->os_cert_handle(), | |
| 339 intermediates); | |
| 340 | |
| 341 // Add the root that signed the intermediate for this test. | |
| 342 scoped_refptr<X509Certificate> root_cert = | |
| 343 ImportCertFromFile(certs_dir, "2048-rsa-root.pem"); | |
| 344 ASSERT_NE(static_cast<X509Certificate*>(NULL), root_cert); | |
| 345 ScopedTestRoot scoped_root(root_cert); | |
| 346 | |
| 347 // Verify has the side-effect of populating public_key_hashes, which | |
| 348 // ParsePinsHeader needs. (It wants to check pins against the validated | |
| 349 // chain, not just the presented chain.) | |
| 350 int rv = ERR_FAILED; | |
| 351 CertVerifyResult result; | |
| 352 scoped_ptr<CertVerifier> verifier(CertVerifier::CreateDefault()); | |
| 353 TestCompletionCallback callback; | |
| 354 CertVerifier::RequestHandle handle = NULL; | |
| 355 rv = verifier->Verify(ssl_info.cert, "127.0.0.1", 0, NULL, &result, | |
| 356 callback.callback(), &handle, BoundNetLog()); | |
| 357 rv = callback.GetResult(rv); | |
| 358 ASSERT_EQ(OK, rv); | |
| 359 // Normally, ssl_client_socket_nss would do this, but for a unit test we | |
| 360 // fake it. | |
| 361 ssl_info.public_key_hashes = result.public_key_hashes; | |
| 362 std::string good_pin = GetPinFromCert(ssl_info.cert, /*tag*/HASH_VALUE_SHA1); | |
| 363 DLOG(WARNING) << "good pin: " << good_pin; | |
| 364 | |
| 365 // The backup pin is fake --- we just need an SPKI hash that does not match | |
| 366 // the hash of any SPKI in the certificate chain. | |
| 367 std::string backup_pin = "pin-sha1=" + | |
| 368 HttpUtil::Quote("6dcfXufJLW3J6S/9rRe4vUlBj5g="); | |
| 369 | |
| 370 EXPECT_TRUE(state.ParsePinsHeader( | |
| 371 now, | |
| 372 "max-age=243; " + good_pin + ";" + backup_pin, | |
| 373 ssl_info)); | |
| 374 expiry = now + base::TimeDelta::FromSeconds(243); | |
| 375 EXPECT_EQ(expiry, state.dynamic_spki_hashes_expiry); | |
| 376 | |
| 377 EXPECT_TRUE(state.ParsePinsHeader( | |
| 378 now, | |
| 379 " " + good_pin + "; " + backup_pin + " ; Max-agE = 567", | |
| 380 ssl_info)); | |
| 381 expiry = now + base::TimeDelta::FromSeconds(567); | |
| 382 EXPECT_EQ(expiry, state.dynamic_spki_hashes_expiry); | |
| 383 | |
| 384 EXPECT_TRUE(state.ParsePinsHeader( | |
| 385 now, | |
| 386 good_pin + ";" + backup_pin + " ; mAx-aGe = 890 ", | |
| 387 ssl_info)); | |
| 388 expiry = now + base::TimeDelta::FromSeconds(890); | |
| 389 EXPECT_EQ(expiry, state.dynamic_spki_hashes_expiry); | |
| 390 | |
| 391 EXPECT_TRUE(state.ParsePinsHeader( | |
| 392 now, | |
| 393 good_pin + ";" + backup_pin + "; max-age=123;IGNORED;", | |
| 394 ssl_info)); | |
| 395 expiry = now + base::TimeDelta::FromSeconds(123); | |
| 396 EXPECT_EQ(expiry, state.dynamic_spki_hashes_expiry); | |
| 397 | |
| 398 EXPECT_TRUE(state.ParsePinsHeader( | |
| 399 now, | |
| 400 "max-age=394082;" + backup_pin + ";" + good_pin + "; ", | |
| 401 ssl_info)); | |
| 402 expiry = now + base::TimeDelta::FromSeconds(394082); | |
| 403 EXPECT_EQ(expiry, state.dynamic_spki_hashes_expiry); | |
| 404 | |
| 405 EXPECT_TRUE(state.ParsePinsHeader( | |
| 406 now, | |
| 407 "max-age=39408299 ;" + backup_pin + ";" + good_pin + "; ", | |
| 408 ssl_info)); | |
| 409 expiry = now + base::TimeDelta::FromSeconds( | |
| 410 std::min(TransportSecurityState::kMaxHSTSAgeSecs, 39408299l)); | |
| 411 EXPECT_EQ(expiry, state.dynamic_spki_hashes_expiry); | |
| 412 | |
| 413 EXPECT_TRUE(state.ParsePinsHeader( | |
| 414 now, | |
| 415 "max-age=39408038 ; cybers=39408038 ; " + | |
| 416 good_pin + ";" + backup_pin + "; ", | |
| 417 ssl_info)); | |
| 418 expiry = now + base::TimeDelta::FromSeconds( | |
| 419 std::min(TransportSecurityState::kMaxHSTSAgeSecs, 394082038l)); | |
| 420 EXPECT_EQ(expiry, state.dynamic_spki_hashes_expiry); | |
| 421 | |
| 422 EXPECT_TRUE(state.ParsePinsHeader( | |
| 423 now, | |
| 424 " max-age=0 ; " + good_pin + ";" + backup_pin, | |
| 425 ssl_info)); | |
| 426 expiry = now + base::TimeDelta::FromSeconds(0); | |
| 427 EXPECT_EQ(expiry, state.dynamic_spki_hashes_expiry); | |
| 428 | |
| 429 EXPECT_TRUE(state.ParsePinsHeader( | |
| 430 now, | |
| 431 " max-age=999999999999999999999999999999999999999999999 ; " + | |
| 432 backup_pin + ";" + good_pin + "; ", | |
| 433 ssl_info)); | |
| 434 expiry = now + | |
| 435 base::TimeDelta::FromSeconds(TransportSecurityState::kMaxHSTSAgeSecs); | |
| 436 EXPECT_EQ(expiry, state.dynamic_spki_hashes_expiry); | |
| 437 } | |
| 438 | |
| 439 TEST_F(TransportSecurityStateTest, ValidPinsHeadersSHA1) { | |
| 440 TestValidPinsHeaders(HASH_VALUE_SHA1); | |
| 441 } | |
| 442 | |
| 443 TEST_F(TransportSecurityStateTest, ValidPinsHeadersSHA256) { | |
| 444 TestValidPinsHeaders(HASH_VALUE_SHA256); | |
| 445 } | |
| 446 | |
| 447 TEST_F(TransportSecurityStateTest, SimpleMatches) { | 48 TEST_F(TransportSecurityStateTest, SimpleMatches) { |
| 448 TransportSecurityState state; | 49 TransportSecurityState state; |
| 449 TransportSecurityState::DomainState domain_state; | 50 TransportSecurityState::DomainState domain_state; |
| 450 const base::Time current_time(base::Time::Now()); | 51 const base::Time current_time(base::Time::Now()); |
| 451 const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); | 52 const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); |
| 452 | 53 |
| 453 EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state)); | 54 EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state)); |
| 454 domain_state.upgrade_expiry = expiry; | 55 domain_state.upgrade_expiry = expiry; |
| 455 state.EnableHost("yahoo.com", domain_state); | 56 state.EnableHost("yahoo.com", domain_state); |
| 456 EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state)); | 57 EXPECT_TRUE(state.GetDomainState("yahoo.com", true, &domain_state)); |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 912 EXPECT_TRUE(HasPins("dev.twitter.com")); | 513 EXPECT_TRUE(HasPins("dev.twitter.com")); |
| 913 EXPECT_TRUE(HasPins("business.twitter.com")); | 514 EXPECT_TRUE(HasPins("business.twitter.com")); |
| 914 EXPECT_TRUE(HasPins("platform.twitter.com")); | 515 EXPECT_TRUE(HasPins("platform.twitter.com")); |
| 915 EXPECT_TRUE(HasPins("si0.twimg.com")); | 516 EXPECT_TRUE(HasPins("si0.twimg.com")); |
| 916 EXPECT_TRUE(HasPins("twimg0-a.akamaihd.net")); | 517 EXPECT_TRUE(HasPins("twimg0-a.akamaihd.net")); |
| 917 } | 518 } |
| 918 | 519 |
| 919 static bool AddHash(const std::string& type_and_base64, | 520 static bool AddHash(const std::string& type_and_base64, |
| 920 HashValueVector* out) { | 521 HashValueVector* out) { |
| 921 HashValue hash; | 522 HashValue hash; |
| 922 | 523 if (!hash.FromString(type_and_base64)) |
| 923 if (!TransportSecurityState::ParsePin(type_and_base64, &hash)) | |
| 924 return false; | 524 return false; |
| 925 | 525 |
| 926 out->push_back(hash); | 526 out->push_back(hash); |
| 927 return true; | 527 return true; |
| 928 } | 528 } |
| 929 | 529 |
| 930 TEST_F(TransportSecurityStateTest, PinValidationWithRejectedCerts) { | 530 TEST_F(TransportSecurityStateTest, PinValidationWithRejectedCerts) { |
| 931 // kGoodPath is plus.google.com via Google Internet Authority. | 531 // kGoodPath is plus.google.com via Google Internet Authority. |
| 932 static const char* kGoodPath[] = { | 532 static const char* kGoodPath[] = { |
| 933 "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=", | 533 "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=", |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1226 // Expect to fail for SNI hosts when not searching the SNI list: | 826 // Expect to fail for SNI hosts when not searching the SNI list: |
| 1227 EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( | 827 EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( |
| 1228 "gmail.com", false)); | 828 "gmail.com", false)); |
| 1229 EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( | 829 EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( |
| 1230 "googlegroups.com", false)); | 830 "googlegroups.com", false)); |
| 1231 EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( | 831 EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty( |
| 1232 "www.googlegroups.com", false)); | 832 "www.googlegroups.com", false)); |
| 1233 } | 833 } |
| 1234 | 834 |
| 1235 } // namespace net | 835 } // namespace net |
| OLD | NEW |