Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / http / http_security_headers_unittest.cc
blob029b16730fd3325716b38df5b61f8433d4f20052
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
3 // found in the LICENSE file.
5 #include <stdint.h>
6 #include <algorithm>
8 #include "base/base64.h"
9 #include "base/sha1.h"
10 #include "base/strings/string_piece.h"
11 #include "crypto/sha2.h"
12 #include "net/base/test_completion_callback.h"
13 #include "net/http/http_security_headers.h"
14 #include "net/http/http_util.h"
15 #include "net/http/transport_security_state.h"
16 #include "net/log/net_log.h"
17 #include "net/ssl/ssl_info.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 namespace net {
22 namespace {
24 HashValue GetTestHashValue(uint8 label, HashValueTag tag) {
25 HashValue hash_value(tag);
26 memset(hash_value.data(), label, hash_value.size());
27 return hash_value;
30 std::string GetTestPinImpl(uint8 label, HashValueTag tag, bool quoted) {
31 HashValue hash_value = GetTestHashValue(label, tag);
32 std::string base64;
33 base::Base64Encode(base::StringPiece(
34 reinterpret_cast<char*>(hash_value.data()), hash_value.size()), &base64);
36 std::string ret;
37 switch (hash_value.tag) {
38 case HASH_VALUE_SHA1:
39 ret = "pin-sha1=";
40 break;
41 case HASH_VALUE_SHA256:
42 ret = "pin-sha256=";
43 break;
44 default:
45 NOTREACHED() << "Unknown HashValueTag " << hash_value.tag;
46 return std::string("ERROR");
48 if (quoted)
49 ret += '\"';
50 ret += base64;
51 if (quoted)
52 ret += '\"';
53 return ret;
56 std::string GetTestPin(uint8 label, HashValueTag tag) {
57 return GetTestPinImpl(label, tag, true);
60 std::string GetTestPinUnquoted(uint8 label, HashValueTag tag) {
61 return GetTestPinImpl(label, tag, false);
67 class HttpSecurityHeadersTest : public testing::Test {
71 TEST_F(HttpSecurityHeadersTest, BogusHeaders) {
72 base::TimeDelta max_age;
73 bool include_subdomains = false;
75 EXPECT_FALSE(
76 ParseHSTSHeader(std::string(), &max_age, &include_subdomains));
77 EXPECT_FALSE(ParseHSTSHeader(" ", &max_age, &include_subdomains));
78 EXPECT_FALSE(ParseHSTSHeader("abc", &max_age, &include_subdomains));
79 EXPECT_FALSE(ParseHSTSHeader(" abc", &max_age, &include_subdomains));
80 EXPECT_FALSE(ParseHSTSHeader(" abc ", &max_age, &include_subdomains));
81 EXPECT_FALSE(ParseHSTSHeader("max-age", &max_age, &include_subdomains));
82 EXPECT_FALSE(ParseHSTSHeader(" max-age", &max_age,
83 &include_subdomains));
84 EXPECT_FALSE(ParseHSTSHeader(" max-age ", &max_age,
85 &include_subdomains));
86 EXPECT_FALSE(ParseHSTSHeader("max-age=", &max_age, &include_subdomains));
87 EXPECT_FALSE(ParseHSTSHeader(" max-age=", &max_age,
88 &include_subdomains));
89 EXPECT_FALSE(ParseHSTSHeader(" max-age =", &max_age,
90 &include_subdomains));
91 EXPECT_FALSE(ParseHSTSHeader(" max-age= ", &max_age,
92 &include_subdomains));
93 EXPECT_FALSE(ParseHSTSHeader(" max-age = ", &max_age,
94 &include_subdomains));
95 EXPECT_FALSE(ParseHSTSHeader(" max-age = xy", &max_age,
96 &include_subdomains));
97 EXPECT_FALSE(ParseHSTSHeader(" max-age = 3488a923", &max_age,
98 &include_subdomains));
99 EXPECT_FALSE(ParseHSTSHeader("max-age=3488a923 ", &max_age,
100 &include_subdomains));
101 EXPECT_FALSE(ParseHSTSHeader("max-ag=3488923", &max_age,
102 &include_subdomains));
103 EXPECT_FALSE(ParseHSTSHeader("max-aged=3488923", &max_age,
104 &include_subdomains));
105 EXPECT_FALSE(ParseHSTSHeader("max-age==3488923", &max_age,
106 &include_subdomains));
107 EXPECT_FALSE(ParseHSTSHeader("amax-age=3488923", &max_age,
108 &include_subdomains));
109 EXPECT_FALSE(ParseHSTSHeader("max-age=-3488923", &max_age,
110 &include_subdomains));
111 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 e", &max_age,
112 &include_subdomains));
113 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomain",
114 &max_age, &include_subdomains));
115 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923includesubdomains",
116 &max_age, &include_subdomains));
117 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923=includesubdomains",
118 &max_age, &include_subdomains));
119 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomainx",
120 &max_age, &include_subdomains));
121 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomain=",
122 &max_age, &include_subdomains));
123 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomain=true",
124 &max_age, &include_subdomains));
125 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomainsx",
126 &max_age, &include_subdomains));
127 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomains x",
128 &max_age, &include_subdomains));
129 EXPECT_FALSE(ParseHSTSHeader("max-age=34889.23 includesubdomains",
130 &max_age, &include_subdomains));
131 EXPECT_FALSE(ParseHSTSHeader("max-age=34889 includesubdomains",
132 &max_age, &include_subdomains));
133 EXPECT_FALSE(ParseHSTSHeader(";;;; ;;;",
134 &max_age, &include_subdomains));
135 EXPECT_FALSE(ParseHSTSHeader(";;;; includeSubDomains;;;",
136 &max_age, &include_subdomains));
137 EXPECT_FALSE(ParseHSTSHeader(" includeSubDomains; ",
138 &max_age, &include_subdomains));
139 EXPECT_FALSE(ParseHSTSHeader(";",
140 &max_age, &include_subdomains));
141 EXPECT_FALSE(ParseHSTSHeader("max-age; ;",
142 &max_age, &include_subdomains));
144 // Check the out args were not updated by checking the default
145 // values for its predictable fields.
146 EXPECT_EQ(0, max_age.InSeconds());
147 EXPECT_FALSE(include_subdomains);
150 static void TestBogusPinsHeaders(HashValueTag tag) {
151 base::TimeDelta max_age;
152 bool include_subdomains;
153 HashValueVector hashes;
154 HashValueVector chain_hashes;
155 GURL report_uri;
157 // Set some fake "chain" hashes
158 chain_hashes.push_back(GetTestHashValue(1, tag));
159 chain_hashes.push_back(GetTestHashValue(2, tag));
160 chain_hashes.push_back(GetTestHashValue(3, tag));
162 // The good pin must be in the chain, the backup pin must not be
163 std::string good_pin = GetTestPin(2, tag);
164 std::string good_pin_unquoted = GetTestPinUnquoted(2, tag);
165 std::string backup_pin = GetTestPin(4, tag);
167 EXPECT_FALSE(ParseHPKPHeader(std::string(), chain_hashes, &max_age,
168 &include_subdomains, &hashes, &report_uri));
169 EXPECT_FALSE(ParseHPKPHeader(" ", chain_hashes, &max_age,
170 &include_subdomains, &hashes, &report_uri));
171 EXPECT_FALSE(ParseHPKPHeader("abc", chain_hashes, &max_age,
172 &include_subdomains, &hashes, &report_uri));
173 EXPECT_FALSE(ParseHPKPHeader(" abc", chain_hashes, &max_age,
174 &include_subdomains, &hashes, &report_uri));
175 EXPECT_FALSE(ParseHPKPHeader(" abc ", chain_hashes, &max_age,
176 &include_subdomains, &hashes, &report_uri));
177 EXPECT_FALSE(ParseHPKPHeader("max-age", chain_hashes, &max_age,
178 &include_subdomains, &hashes, &report_uri));
179 EXPECT_FALSE(ParseHPKPHeader(" max-age", chain_hashes, &max_age,
180 &include_subdomains, &hashes, &report_uri));
181 EXPECT_FALSE(ParseHPKPHeader(" max-age ", chain_hashes, &max_age,
182 &include_subdomains, &hashes, &report_uri));
183 EXPECT_FALSE(ParseHPKPHeader("max-age=", chain_hashes, &max_age,
184 &include_subdomains, &hashes, &report_uri));
185 EXPECT_FALSE(ParseHPKPHeader(" max-age=", chain_hashes, &max_age,
186 &include_subdomains, &hashes, &report_uri));
187 EXPECT_FALSE(ParseHPKPHeader(" max-age =", chain_hashes, &max_age,
188 &include_subdomains, &hashes, &report_uri));
189 EXPECT_FALSE(ParseHPKPHeader(" max-age= ", chain_hashes, &max_age,
190 &include_subdomains, &hashes, &report_uri));
191 EXPECT_FALSE(ParseHPKPHeader(" max-age = ", chain_hashes, &max_age,
192 &include_subdomains, &hashes, &report_uri));
193 EXPECT_FALSE(ParseHPKPHeader(" max-age = xy", chain_hashes, &max_age,
194 &include_subdomains, &hashes, &report_uri));
195 EXPECT_FALSE(ParseHPKPHeader(" max-age = 3488a923", chain_hashes,
196 &max_age, &include_subdomains, &hashes,
197 &report_uri));
198 EXPECT_FALSE(ParseHPKPHeader("max-age=3488a923 ", chain_hashes, &max_age,
199 &include_subdomains, &hashes, &report_uri));
200 EXPECT_FALSE(ParseHPKPHeader(
201 "max-ag=3488923pins=" + good_pin + "," + backup_pin, chain_hashes,
202 &max_age, &include_subdomains, &hashes, &report_uri));
203 EXPECT_FALSE(ParseHPKPHeader("max-age=3488923;pins=" + good_pin + "," +
204 backup_pin + "report-uri=\"http://foo.com\"",
205 chain_hashes, &max_age, &include_subdomains,
206 &hashes, &report_uri));
207 EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923" + backup_pin, chain_hashes,
208 &max_age, &include_subdomains, &hashes,
209 &report_uri));
210 EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + backup_pin, chain_hashes,
211 &max_age, &include_subdomains, &hashes,
212 &report_uri));
213 EXPECT_FALSE(ParseHPKPHeader(
214 "max-aged=3488923; " + backup_pin + ";" + backup_pin, chain_hashes,
215 &max_age, &include_subdomains, &hashes, &report_uri));
216 EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + good_pin + ";" + good_pin,
217 chain_hashes, &max_age, &include_subdomains,
218 &hashes, &report_uri));
219 EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + good_pin, chain_hashes,
220 &max_age, &include_subdomains, &hashes,
221 &report_uri));
222 EXPECT_FALSE(ParseHPKPHeader("max-age==3488923", chain_hashes, &max_age,
223 &include_subdomains, &hashes, &report_uri));
224 EXPECT_FALSE(ParseHPKPHeader("amax-age=3488923", chain_hashes, &max_age,
225 &include_subdomains, &hashes, &report_uri));
226 EXPECT_FALSE(ParseHPKPHeader("max-age=-3488923", chain_hashes, &max_age,
227 &include_subdomains, &hashes, &report_uri));
228 EXPECT_FALSE(ParseHPKPHeader("max-age=3488923;", chain_hashes, &max_age,
229 &include_subdomains, &hashes, &report_uri));
230 EXPECT_FALSE(ParseHPKPHeader("max-age=3488923 e", chain_hashes, &max_age,
231 &include_subdomains, &hashes, &report_uri));
232 EXPECT_FALSE(ParseHPKPHeader("max-age=3488923 includesubdomain",
233 chain_hashes, &max_age, &include_subdomains,
234 &hashes, &report_uri));
235 EXPECT_FALSE(ParseHPKPHeader(
236 "max-age=3488923 report-uri=\"http://foo.com\"", chain_hashes,
237 &max_age, &include_subdomains, &hashes, &report_uri));
238 EXPECT_FALSE(ParseHPKPHeader("max-age=34889.23", chain_hashes, &max_age,
239 &include_subdomains, &hashes, &report_uri));
240 EXPECT_FALSE(ParseHPKPHeader(
241 "max-age=243; " + good_pin_unquoted + ";" + backup_pin, chain_hashes,
242 &max_age, &include_subdomains, &hashes, &report_uri));
243 EXPECT_FALSE(ParseHPKPHeader(
244 "max-age=243; " + good_pin + ";" + backup_pin + ";report-uri=;",
245 chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri));
246 EXPECT_FALSE(ParseHPKPHeader("max-age=243; " + good_pin + ";" + backup_pin +
247 ";report-uri=http://foo.com;",
248 chain_hashes, &max_age, &include_subdomains,
249 &hashes, &report_uri));
250 EXPECT_FALSE(ParseHPKPHeader(
251 "max-age=243; " + good_pin + ";" + backup_pin + ";report-uri=''",
252 chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri));
254 // Test that the parser rejects misquoted strings.
255 EXPECT_FALSE(ParseHPKPHeader("max-age=999; " + backup_pin + "; " + good_pin +
256 "; report-uri=\"http://foo;bar\'",
257 chain_hashes, &max_age, &include_subdomains,
258 &hashes, &report_uri));
260 // Test that the parser rejects invalid report-uris.
261 EXPECT_FALSE(ParseHPKPHeader("max-age=999; " + backup_pin + "; " + good_pin +
262 "; report-uri=\"foo;bar\'",
263 chain_hashes, &max_age, &include_subdomains,
264 &hashes, &report_uri));
266 // Check the out args were not updated by checking the default
267 // values for its predictable fields.
268 EXPECT_EQ(0, max_age.InSeconds());
269 EXPECT_EQ(hashes.size(), (size_t)0);
272 TEST_F(HttpSecurityHeadersTest, ValidSTSHeaders) {
273 base::TimeDelta max_age;
274 base::TimeDelta expect_max_age;
275 bool include_subdomains = false;
277 EXPECT_TRUE(ParseHSTSHeader("max-age=243", &max_age,
278 &include_subdomains));
279 expect_max_age = base::TimeDelta::FromSeconds(243);
280 EXPECT_EQ(expect_max_age, max_age);
281 EXPECT_FALSE(include_subdomains);
283 EXPECT_TRUE(ParseHSTSHeader("max-age=3488923;", &max_age,
284 &include_subdomains));
286 EXPECT_TRUE(ParseHSTSHeader(" Max-agE = 567", &max_age,
287 &include_subdomains));
288 expect_max_age = base::TimeDelta::FromSeconds(567);
289 EXPECT_EQ(expect_max_age, max_age);
290 EXPECT_FALSE(include_subdomains);
292 EXPECT_TRUE(ParseHSTSHeader(" mAx-aGe = 890 ", &max_age,
293 &include_subdomains));
294 expect_max_age = base::TimeDelta::FromSeconds(890);
295 EXPECT_EQ(expect_max_age, max_age);
296 EXPECT_FALSE(include_subdomains);
298 EXPECT_TRUE(ParseHSTSHeader("max-age=123;incLudesUbdOmains", &max_age,
299 &include_subdomains));
300 expect_max_age = base::TimeDelta::FromSeconds(123);
301 EXPECT_EQ(expect_max_age, max_age);
302 EXPECT_TRUE(include_subdomains);
304 EXPECT_TRUE(ParseHSTSHeader("incLudesUbdOmains; max-age=123", &max_age,
305 &include_subdomains));
306 expect_max_age = base::TimeDelta::FromSeconds(123);
307 EXPECT_EQ(expect_max_age, max_age);
308 EXPECT_TRUE(include_subdomains);
310 EXPECT_TRUE(ParseHSTSHeader(" incLudesUbdOmains; max-age=123",
311 &max_age, &include_subdomains));
312 expect_max_age = base::TimeDelta::FromSeconds(123);
313 EXPECT_EQ(expect_max_age, max_age);
314 EXPECT_TRUE(include_subdomains);
316 EXPECT_TRUE(ParseHSTSHeader(
317 " incLudesUbdOmains; max-age=123; pumpkin=kitten", &max_age,
318 &include_subdomains));
319 expect_max_age = base::TimeDelta::FromSeconds(123);
320 EXPECT_EQ(expect_max_age, max_age);
321 EXPECT_TRUE(include_subdomains);
323 EXPECT_TRUE(ParseHSTSHeader(
324 " pumpkin=894; incLudesUbdOmains; max-age=123 ", &max_age,
325 &include_subdomains));
326 expect_max_age = base::TimeDelta::FromSeconds(123);
327 EXPECT_EQ(expect_max_age, max_age);
328 EXPECT_TRUE(include_subdomains);
330 EXPECT_TRUE(ParseHSTSHeader(
331 " pumpkin; incLudesUbdOmains; max-age=123 ", &max_age,
332 &include_subdomains));
333 expect_max_age = base::TimeDelta::FromSeconds(123);
334 EXPECT_EQ(expect_max_age, max_age);
335 EXPECT_TRUE(include_subdomains);
337 EXPECT_TRUE(ParseHSTSHeader(
338 " pumpkin; incLudesUbdOmains; max-age=\"123\" ", &max_age,
339 &include_subdomains));
340 expect_max_age = base::TimeDelta::FromSeconds(123);
341 EXPECT_EQ(expect_max_age, max_age);
342 EXPECT_TRUE(include_subdomains);
344 EXPECT_TRUE(ParseHSTSHeader(
345 "animal=\"squirrel; distinguished\"; incLudesUbdOmains; max-age=123",
346 &max_age, &include_subdomains));
347 expect_max_age = base::TimeDelta::FromSeconds(123);
348 EXPECT_EQ(expect_max_age, max_age);
349 EXPECT_TRUE(include_subdomains);
351 EXPECT_TRUE(ParseHSTSHeader("max-age=394082; incLudesUbdOmains",
352 &max_age, &include_subdomains));
353 expect_max_age = base::TimeDelta::FromSeconds(394082);
354 EXPECT_EQ(expect_max_age, max_age);
355 EXPECT_TRUE(include_subdomains);
357 EXPECT_TRUE(ParseHSTSHeader(
358 "max-age=39408299 ;incLudesUbdOmains", &max_age,
359 &include_subdomains));
360 expect_max_age = base::TimeDelta::FromSeconds(
361 std::min(kMaxHSTSAgeSecs, static_cast<int64>(INT64_C(39408299))));
362 EXPECT_EQ(expect_max_age, max_age);
363 EXPECT_TRUE(include_subdomains);
365 EXPECT_TRUE(ParseHSTSHeader(
366 "max-age=394082038 ; incLudesUbdOmains", &max_age,
367 &include_subdomains));
368 expect_max_age = base::TimeDelta::FromSeconds(
369 std::min(kMaxHSTSAgeSecs, static_cast<int64>(INT64_C(394082038))));
370 EXPECT_EQ(expect_max_age, max_age);
371 EXPECT_TRUE(include_subdomains);
373 EXPECT_TRUE(ParseHSTSHeader(
374 "max-age=394082038 ; incLudesUbdOmains;", &max_age,
375 &include_subdomains));
376 expect_max_age = base::TimeDelta::FromSeconds(
377 std::min(kMaxHSTSAgeSecs, static_cast<int64>(INT64_C(394082038))));
378 EXPECT_EQ(expect_max_age, max_age);
379 EXPECT_TRUE(include_subdomains);
381 EXPECT_TRUE(ParseHSTSHeader(
382 ";; max-age=394082038 ; incLudesUbdOmains; ;", &max_age,
383 &include_subdomains));
384 expect_max_age = base::TimeDelta::FromSeconds(
385 std::min(kMaxHSTSAgeSecs, static_cast<int64>(INT64_C(394082038))));
386 EXPECT_EQ(expect_max_age, max_age);
387 EXPECT_TRUE(include_subdomains);
389 EXPECT_TRUE(ParseHSTSHeader(
390 ";; max-age=394082038 ;", &max_age,
391 &include_subdomains));
392 expect_max_age = base::TimeDelta::FromSeconds(
393 std::min(kMaxHSTSAgeSecs, static_cast<int64>(INT64_C(394082038))));
394 EXPECT_EQ(expect_max_age, max_age);
395 EXPECT_FALSE(include_subdomains);
397 EXPECT_TRUE(ParseHSTSHeader(
398 ";; ; ; max-age=394082038;;; includeSubdomains ;; ;", &max_age,
399 &include_subdomains));
400 expect_max_age = base::TimeDelta::FromSeconds(
401 std::min(kMaxHSTSAgeSecs, static_cast<int64>(INT64_C(394082038))));
402 EXPECT_EQ(expect_max_age, max_age);
403 EXPECT_TRUE(include_subdomains);
405 EXPECT_TRUE(ParseHSTSHeader(
406 "incLudesUbdOmains ; max-age=394082038 ;;", &max_age,
407 &include_subdomains));
408 expect_max_age = base::TimeDelta::FromSeconds(
409 std::min(kMaxHSTSAgeSecs, static_cast<int64>(INT64_C(394082038))));
410 EXPECT_EQ(expect_max_age, max_age);
411 EXPECT_TRUE(include_subdomains);
413 EXPECT_TRUE(ParseHSTSHeader(
414 " max-age=0 ; incLudesUbdOmains ", &max_age,
415 &include_subdomains));
416 expect_max_age = base::TimeDelta::FromSeconds(0);
417 EXPECT_EQ(expect_max_age, max_age);
418 EXPECT_TRUE(include_subdomains);
420 EXPECT_TRUE(ParseHSTSHeader(
421 " max-age=999999999999999999999999999999999999999999999 ;"
422 " incLudesUbdOmains ", &max_age, &include_subdomains));
423 expect_max_age = base::TimeDelta::FromSeconds(
424 kMaxHSTSAgeSecs);
425 EXPECT_EQ(expect_max_age, max_age);
426 EXPECT_TRUE(include_subdomains);
429 static void TestValidPKPHeaders(HashValueTag tag) {
430 base::TimeDelta max_age;
431 base::TimeDelta expect_max_age;
432 bool include_subdomains;
433 HashValueVector hashes;
434 HashValueVector chain_hashes;
435 GURL expect_report_uri;
436 GURL report_uri;
438 // Set some fake "chain" hashes into chain_hashes
439 chain_hashes.push_back(GetTestHashValue(1, tag));
440 chain_hashes.push_back(GetTestHashValue(2, tag));
441 chain_hashes.push_back(GetTestHashValue(3, tag));
443 // The good pin must be in the chain, the backup pin must not be
444 std::string good_pin = GetTestPin(2, tag);
445 std::string good_pin2 = GetTestPin(3, tag);
446 std::string backup_pin = GetTestPin(4, tag);
448 EXPECT_TRUE(ParseHPKPHeader("max-age=243; " + good_pin + ";" + backup_pin,
449 chain_hashes, &max_age, &include_subdomains,
450 &hashes, &report_uri));
451 expect_max_age = base::TimeDelta::FromSeconds(243);
452 EXPECT_EQ(expect_max_age, max_age);
453 EXPECT_FALSE(include_subdomains);
454 EXPECT_TRUE(report_uri.is_empty());
456 EXPECT_TRUE(ParseHPKPHeader("max-age=243; " + good_pin + ";" + backup_pin +
457 "; report-uri= \"http://example.test/foo\"",
458 chain_hashes, &max_age, &include_subdomains,
459 &hashes, &report_uri));
460 expect_max_age = base::TimeDelta::FromSeconds(243);
461 expect_report_uri = GURL("http://example.test/foo");
462 EXPECT_EQ(expect_max_age, max_age);
463 EXPECT_FALSE(include_subdomains);
464 EXPECT_EQ(expect_report_uri, report_uri);
466 EXPECT_TRUE(ParseHPKPHeader(
467 " " + good_pin + "; " + backup_pin +
468 " ; Max-agE = 567; repOrT-URi = \"http://example.test/foo\"",
469 chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri));
470 expect_max_age = base::TimeDelta::FromSeconds(567);
471 expect_report_uri = GURL("http://example.test/foo");
472 EXPECT_EQ(expect_max_age, max_age);
473 EXPECT_FALSE(include_subdomains);
474 EXPECT_EQ(expect_report_uri, report_uri);
476 EXPECT_TRUE(ParseHPKPHeader("includeSubDOMAINS;" + good_pin + ";" +
477 backup_pin + " ; mAx-aGe = 890 ",
478 chain_hashes, &max_age, &include_subdomains,
479 &hashes, &report_uri));
480 expect_max_age = base::TimeDelta::FromSeconds(890);
481 EXPECT_EQ(expect_max_age, max_age);
482 EXPECT_TRUE(include_subdomains);
484 EXPECT_TRUE(ParseHPKPHeader(
485 good_pin + ";" + backup_pin + "; max-age=123;IGNORED;", chain_hashes,
486 &max_age, &include_subdomains, &hashes, &report_uri));
487 expect_max_age = base::TimeDelta::FromSeconds(123);
488 EXPECT_EQ(expect_max_age, max_age);
489 EXPECT_FALSE(include_subdomains);
491 EXPECT_TRUE(ParseHPKPHeader(
492 "max-age=394082;" + backup_pin + ";" + good_pin + "; ", chain_hashes,
493 &max_age, &include_subdomains, &hashes, &report_uri));
494 expect_max_age = base::TimeDelta::FromSeconds(394082);
495 EXPECT_EQ(expect_max_age, max_age);
496 EXPECT_FALSE(include_subdomains);
498 EXPECT_TRUE(ParseHPKPHeader(
499 "max-age=39408299 ;" + backup_pin + ";" + good_pin + "; ", chain_hashes,
500 &max_age, &include_subdomains, &hashes, &report_uri));
501 expect_max_age = base::TimeDelta::FromSeconds(
502 std::min(kMaxHSTSAgeSecs, static_cast<int64>(INT64_C(39408299))));
503 EXPECT_EQ(expect_max_age, max_age);
504 EXPECT_FALSE(include_subdomains);
506 EXPECT_TRUE(ParseHPKPHeader(
507 "max-age=39408038 ; cybers=39408038 ; includeSubdomains; " +
508 good_pin + ";" + backup_pin + "; ",
509 chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri));
510 expect_max_age = base::TimeDelta::FromSeconds(
511 std::min(kMaxHSTSAgeSecs, static_cast<int64>(INT64_C(394082038))));
512 EXPECT_EQ(expect_max_age, max_age);
513 EXPECT_TRUE(include_subdomains);
515 EXPECT_TRUE(ParseHPKPHeader(" max-age=0 ; " + good_pin + ";" + backup_pin,
516 chain_hashes, &max_age, &include_subdomains,
517 &hashes, &report_uri));
518 expect_max_age = base::TimeDelta::FromSeconds(0);
519 EXPECT_EQ(expect_max_age, max_age);
520 EXPECT_FALSE(include_subdomains);
522 EXPECT_TRUE(ParseHPKPHeader(
523 " max-age=0 ; includeSubdomains; " + good_pin + ";" + backup_pin,
524 chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri));
525 expect_max_age = base::TimeDelta::FromSeconds(0);
526 EXPECT_EQ(expect_max_age, max_age);
527 EXPECT_TRUE(include_subdomains);
529 EXPECT_TRUE(ParseHPKPHeader(
530 " max-age=999999999999999999999999999999999999999999999 ; " +
531 backup_pin + ";" + good_pin + "; ",
532 chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri));
533 expect_max_age = base::TimeDelta::FromSeconds(kMaxHSTSAgeSecs);
534 EXPECT_EQ(expect_max_age, max_age);
535 EXPECT_FALSE(include_subdomains);
537 EXPECT_TRUE(ParseHPKPHeader(
538 " max-age=999999999999999999999999999999999999999999999 ; " +
539 backup_pin + ";" + good_pin +
540 "; report-uri=\"http://example.test/foo\"",
541 chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri));
542 expect_max_age = base::TimeDelta::FromSeconds(kMaxHSTSAgeSecs);
543 expect_report_uri = GURL("http://example.test/foo");
544 EXPECT_EQ(expect_max_age, max_age);
545 EXPECT_FALSE(include_subdomains);
546 EXPECT_EQ(expect_report_uri, report_uri);
548 // Test that parsing a different header resets the hashes.
549 hashes.clear();
550 EXPECT_TRUE(ParseHPKPHeader(
551 " max-age=999; " + backup_pin + ";" + good_pin + "; ", chain_hashes,
552 &max_age, &include_subdomains, &hashes, &report_uri));
553 EXPECT_EQ(2u, hashes.size());
554 EXPECT_TRUE(ParseHPKPHeader(
555 " max-age=999; " + backup_pin + ";" + good_pin2 + "; ", chain_hashes,
556 &max_age, &include_subdomains, &hashes, &report_uri));
557 EXPECT_EQ(2u, hashes.size());
559 // Test that the parser correctly parses an unencoded ';' inside a
560 // quoted report-uri.
561 EXPECT_TRUE(ParseHPKPHeader("max-age=999; " + backup_pin + "; " + good_pin +
562 "; report-uri=\"http://foo.com/?;bar\"",
563 chain_hashes, &max_age, &include_subdomains,
564 &hashes, &report_uri));
565 expect_max_age = base::TimeDelta::FromSeconds(999);
566 expect_report_uri = GURL("http://foo.com/?;bar");
567 EXPECT_EQ(expect_max_age, max_age);
568 EXPECT_FALSE(include_subdomains);
569 EXPECT_EQ(expect_report_uri, report_uri);
571 // Test that the parser correctly parses a report-uri with a >0x7f
572 // character.
573 std::string uri = "http://foo.com/";
574 uri += char(0x7f);
575 expect_report_uri = GURL(uri);
576 EXPECT_TRUE(ParseHPKPHeader("max-age=999; " + backup_pin + "; " + good_pin +
577 "; report-uri=\"" + uri + "\"",
578 chain_hashes, &max_age, &include_subdomains,
579 &hashes, &report_uri));
580 expect_max_age = base::TimeDelta::FromSeconds(999);
581 EXPECT_EQ(expect_max_age, max_age);
582 EXPECT_FALSE(include_subdomains);
583 EXPECT_EQ(expect_report_uri, report_uri);
585 // Test that the parser allows quoted max-age values.
586 EXPECT_TRUE(ParseHPKPHeader("max-age='999'; " + backup_pin + "; " + good_pin,
587 chain_hashes, &max_age, &include_subdomains,
588 &hashes, &report_uri));
589 expect_max_age = base::TimeDelta::FromSeconds(999);
590 EXPECT_EQ(expect_max_age, max_age);
591 EXPECT_FALSE(include_subdomains);
593 // Test that the parser handles escaped values.
594 expect_report_uri = GURL("http://foo.com'a");
595 EXPECT_TRUE(ParseHPKPHeader("max-age=999; " + backup_pin + "; " + good_pin +
596 "; report-uri='http://foo.com\\'\\a'",
597 chain_hashes, &max_age, &include_subdomains,
598 &hashes, &report_uri));
599 expect_max_age = base::TimeDelta::FromSeconds(999);
600 EXPECT_EQ(expect_max_age, max_age);
601 EXPECT_FALSE(include_subdomains);
602 EXPECT_EQ(expect_report_uri, report_uri);
605 TEST_F(HttpSecurityHeadersTest, BogusPinsHeadersSHA1) {
606 TestBogusPinsHeaders(HASH_VALUE_SHA1);
609 TEST_F(HttpSecurityHeadersTest, BogusPinsHeadersSHA256) {
610 TestBogusPinsHeaders(HASH_VALUE_SHA256);
613 TEST_F(HttpSecurityHeadersTest, ValidPKPHeadersSHA1) {
614 TestValidPKPHeaders(HASH_VALUE_SHA1);
617 TEST_F(HttpSecurityHeadersTest, ValidPKPHeadersSHA256) {
618 TestValidPKPHeaders(HASH_VALUE_SHA256);
621 TEST_F(HttpSecurityHeadersTest, UpdateDynamicPKPOnly) {
622 TransportSecurityState state;
623 TransportSecurityState::STSState static_sts_state;
624 TransportSecurityState::PKPState static_pkp_state;
626 // docs.google.com has preloaded pins.
627 std::string domain = "docs.google.com";
628 state.enable_static_pins_ = true;
629 EXPECT_TRUE(
630 state.GetStaticDomainState(domain, &static_sts_state, &static_pkp_state));
631 EXPECT_GT(static_pkp_state.spki_hashes.size(), 1UL);
632 HashValueVector saved_hashes = static_pkp_state.spki_hashes;
634 // Add a header, which should only update the dynamic state.
635 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1);
636 HashValue backup_hash = GetTestHashValue(2, HASH_VALUE_SHA1);
637 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1);
638 std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1);
639 GURL report_uri("http://google.com");
640 std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin +
641 ";report-uri=\"" + report_uri.spec() + "\"";
643 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
644 SSLInfo ssl_info;
645 ssl_info.public_key_hashes.push_back(good_hash);
646 ssl_info.public_key_hashes.push_back(saved_hashes[0]);
647 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
649 // Expect the static state to remain unchanged.
650 TransportSecurityState::STSState new_static_sts_state;
651 TransportSecurityState::PKPState new_static_pkp_state;
652 EXPECT_TRUE(state.GetStaticDomainState(domain, &new_static_sts_state,
653 &new_static_pkp_state));
654 for (size_t i = 0; i < saved_hashes.size(); ++i) {
655 EXPECT_TRUE(
656 HashValuesEqual(saved_hashes[i])(new_static_pkp_state.spki_hashes[i]));
659 // Expect the dynamic state to reflect the header.
660 TransportSecurityState::PKPState dynamic_pkp_state;
661 EXPECT_TRUE(state.GetDynamicPKPState(domain, &dynamic_pkp_state));
662 EXPECT_EQ(2UL, dynamic_pkp_state.spki_hashes.size());
663 EXPECT_EQ(report_uri, dynamic_pkp_state.report_uri);
665 HashValueVector::const_iterator hash = std::find_if(
666 dynamic_pkp_state.spki_hashes.begin(),
667 dynamic_pkp_state.spki_hashes.end(), HashValuesEqual(good_hash));
668 EXPECT_NE(dynamic_pkp_state.spki_hashes.end(), hash);
670 hash = std::find_if(dynamic_pkp_state.spki_hashes.begin(),
671 dynamic_pkp_state.spki_hashes.end(),
672 HashValuesEqual(backup_hash));
673 EXPECT_NE(dynamic_pkp_state.spki_hashes.end(), hash);
675 // Expect the overall state to reflect the header, too.
676 EXPECT_TRUE(state.HasPublicKeyPins(domain));
677 HashValueVector hashes;
678 hashes.push_back(good_hash);
679 std::string failure_log;
680 const bool is_issued_by_known_root = true;
681 EXPECT_TRUE(state.CheckPublicKeyPins(
682 domain, is_issued_by_known_root, hashes, &failure_log));
684 TransportSecurityState::PKPState new_dynamic_pkp_state;
685 EXPECT_TRUE(state.GetDynamicPKPState(domain, &new_dynamic_pkp_state));
686 EXPECT_EQ(2UL, new_dynamic_pkp_state.spki_hashes.size());
687 EXPECT_EQ(report_uri, new_dynamic_pkp_state.report_uri);
689 hash = std::find_if(new_dynamic_pkp_state.spki_hashes.begin(),
690 new_dynamic_pkp_state.spki_hashes.end(),
691 HashValuesEqual(good_hash));
692 EXPECT_NE(new_dynamic_pkp_state.spki_hashes.end(), hash);
694 hash = std::find_if(new_dynamic_pkp_state.spki_hashes.begin(),
695 new_dynamic_pkp_state.spki_hashes.end(),
696 HashValuesEqual(backup_hash));
697 EXPECT_NE(new_dynamic_pkp_state.spki_hashes.end(), hash);
700 TEST_F(HttpSecurityHeadersTest, UpdateDynamicPKPMaxAge0) {
701 TransportSecurityState state;
702 TransportSecurityState::STSState static_sts_state;
703 TransportSecurityState::PKPState static_pkp_state;
705 // docs.google.com has preloaded pins.
706 std::string domain = "docs.google.com";
707 state.enable_static_pins_ = true;
708 ASSERT_TRUE(
709 state.GetStaticDomainState(domain, &static_sts_state, &static_pkp_state));
710 EXPECT_GT(static_pkp_state.spki_hashes.size(), 1UL);
711 HashValueVector saved_hashes = static_pkp_state.spki_hashes;
713 // Add a header, which should only update the dynamic state.
714 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1);
715 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1);
716 std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1);
717 std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin;
719 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
720 SSLInfo ssl_info;
721 ssl_info.public_key_hashes.push_back(good_hash);
722 ssl_info.public_key_hashes.push_back(saved_hashes[0]);
723 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
725 // Expect the static state to remain unchanged.
726 TransportSecurityState::STSState new_static_sts_state;
727 TransportSecurityState::PKPState new_static_pkp_state;
728 EXPECT_TRUE(state.GetStaticDomainState(domain, &new_static_sts_state,
729 &new_static_pkp_state));
730 EXPECT_EQ(saved_hashes.size(), new_static_pkp_state.spki_hashes.size());
731 for (size_t i = 0; i < saved_hashes.size(); ++i) {
732 EXPECT_TRUE(
733 HashValuesEqual(saved_hashes[i])(new_static_pkp_state.spki_hashes[i]));
736 // Expect the dynamic state to have pins.
737 TransportSecurityState::PKPState new_dynamic_pkp_state;
738 EXPECT_TRUE(state.GetDynamicPKPState(domain, &new_dynamic_pkp_state));
739 EXPECT_EQ(2UL, new_dynamic_pkp_state.spki_hashes.size());
740 EXPECT_TRUE(new_dynamic_pkp_state.HasPublicKeyPins());
742 // Now set another header with max-age=0, and check that the pins are
743 // cleared in the dynamic state only.
744 header = "max-age = 0; " + good_pin + "; " + backup_pin;
745 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
747 // Expect the static state to remain unchanged.
748 TransportSecurityState::PKPState new_static_pkp_state2;
749 EXPECT_TRUE(state.GetStaticDomainState(domain, &static_sts_state,
750 &new_static_pkp_state2));
751 EXPECT_EQ(saved_hashes.size(), new_static_pkp_state2.spki_hashes.size());
752 for (size_t i = 0; i < saved_hashes.size(); ++i) {
753 EXPECT_TRUE(
754 HashValuesEqual(saved_hashes[i])(new_static_pkp_state2.spki_hashes[i]));
757 // Expect the dynamic pins to be gone.
758 TransportSecurityState::PKPState new_dynamic_pkp_state2;
759 EXPECT_FALSE(state.GetDynamicPKPState(domain, &new_dynamic_pkp_state2));
761 // Expect the exact-matching static policy to continue to apply, even
762 // though dynamic policy has been removed. (This policy may change in the
763 // future, in which case this test must be updated.)
764 EXPECT_TRUE(state.HasPublicKeyPins(domain));
765 EXPECT_TRUE(state.ShouldSSLErrorsBeFatal(domain));
766 std::string failure_log;
768 // Damage the hashes to cause a pin validation failure.
769 new_static_pkp_state2.spki_hashes[0].data()[0] ^= 0x80;
770 new_static_pkp_state2.spki_hashes[1].data()[0] ^= 0x80;
771 new_static_pkp_state2.spki_hashes[2].data()[0] ^= 0x80;
773 const bool is_issued_by_known_root = true;
774 EXPECT_FALSE(state.CheckPublicKeyPins(domain, is_issued_by_known_root,
775 new_static_pkp_state2.spki_hashes,
776 &failure_log));
777 EXPECT_NE(0UL, failure_log.length());
780 // Tests that when a static HSTS and a static HPKP entry are present, adding a
781 // dynamic HSTS header does not clobber the static HPKP entry. Further, adding a
782 // dynamic HPKP entry could not affect the HSTS entry for the site.
783 TEST_F(HttpSecurityHeadersTest, NoClobberPins) {
784 TransportSecurityState state;
785 TransportSecurityState::STSState sts_state;
786 TransportSecurityState::PKPState pkp_state;
788 // accounts.google.com has preloaded pins.
789 std::string domain = "accounts.google.com";
790 state.enable_static_pins_ = true;
792 // Retrieve the static STS and PKP states as it is by default, including its
793 // known good pins.
794 EXPECT_TRUE(state.GetStaticDomainState(domain, &sts_state, &pkp_state));
795 HashValueVector saved_hashes = pkp_state.spki_hashes;
796 EXPECT_TRUE(sts_state.ShouldUpgradeToSSL());
797 EXPECT_TRUE(pkp_state.HasPublicKeyPins());
798 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain));
799 EXPECT_TRUE(state.HasPublicKeyPins(domain));
801 // Add a dynamic HSTS header. CheckPublicKeyPins should still pass when given
802 // the original |saved_hashes|, indicating that the static PKP data is still
803 // configured for the domain.
804 EXPECT_TRUE(state.AddHSTSHeader(domain, "includesubdomains; max-age=10000"));
805 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain));
806 std::string failure_log;
807 const bool is_issued_by_known_root = true;
808 EXPECT_TRUE(state.CheckPublicKeyPins(domain,
809 is_issued_by_known_root,
810 saved_hashes,
811 &failure_log));
813 // Add an HPKP header, which should only update the dynamic state.
814 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1);
815 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1);
816 std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1);
817 std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin;
819 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
820 SSLInfo ssl_info;
821 ssl_info.public_key_hashes.push_back(good_hash);
822 ssl_info.public_key_hashes.push_back(saved_hashes[0]);
823 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
825 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
826 // HSTS should still be configured for this domain.
827 EXPECT_TRUE(sts_state.ShouldUpgradeToSSL());
828 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain));
829 // The dynamic pins, which do not match |saved_hashes|, should take
830 // precedence over the static pins and cause the check to fail.
831 EXPECT_FALSE(state.CheckPublicKeyPins(domain,
832 is_issued_by_known_root,
833 saved_hashes,
834 &failure_log));
837 // Tests that seeing an invalid HPKP header leaves the existing one alone.
838 TEST_F(HttpSecurityHeadersTest, IgnoreInvalidHeaders) {
839 TransportSecurityState state;
841 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA256);
842 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA256);
843 std::string bad_pin = GetTestPin(2, HASH_VALUE_SHA256);
844 std::string backup_pin = GetTestPin(3, HASH_VALUE_SHA256);
846 SSLInfo ssl_info;
847 ssl_info.public_key_hashes.push_back(good_hash);
849 // Add a valid HPKP header.
850 EXPECT_TRUE(state.AddHPKPHeader(
851 "example.com", "max-age = 10000; " + good_pin + "; " + backup_pin,
852 ssl_info));
854 // Check the insertion was valid.
855 EXPECT_TRUE(state.HasPublicKeyPins("example.com"));
856 std::string failure_log;
857 bool is_issued_by_known_root = true;
858 EXPECT_TRUE(state.CheckPublicKeyPins("example.com", is_issued_by_known_root,
859 ssl_info.public_key_hashes,
860 &failure_log));
862 // Now assert an invalid one. This should fail.
863 EXPECT_FALSE(state.AddHPKPHeader(
864 "example.com", "max-age = 10000; " + bad_pin + "; " + backup_pin,
865 ssl_info));
867 // The old pins must still exist.
868 EXPECT_TRUE(state.HasPublicKeyPins("example.com"));
869 EXPECT_TRUE(state.CheckPublicKeyPins("example.com", is_issued_by_known_root,
870 ssl_info.public_key_hashes,
871 &failure_log));
874 }; // namespace net