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.
8 #include "base/base64.h"
10 #include "base/strings/string_piece.h"
11 #include "crypto/sha2.h"
12 #include "net/base/host_port_pair.h"
13 #include "net/base/test_completion_callback.h"
14 #include "net/http/http_security_headers.h"
15 #include "net/http/http_util.h"
16 #include "net/http/transport_security_state.h"
17 #include "net/log/net_log.h"
18 #include "net/ssl/ssl_info.h"
19 #include "testing/gtest/include/gtest/gtest.h"
25 HashValue
GetTestHashValue(uint8 label
, HashValueTag tag
) {
26 HashValue
hash_value(tag
);
27 memset(hash_value
.data(), label
, hash_value
.size());
31 std::string
GetTestPinImpl(uint8 label
, HashValueTag tag
, bool quoted
) {
32 HashValue hash_value
= GetTestHashValue(label
, tag
);
34 base::Base64Encode(base::StringPiece(
35 reinterpret_cast<char*>(hash_value
.data()), hash_value
.size()), &base64
);
38 switch (hash_value
.tag
) {
42 case HASH_VALUE_SHA256
:
46 NOTREACHED() << "Unknown HashValueTag " << hash_value
.tag
;
47 return std::string("ERROR");
57 std::string
GetTestPin(uint8 label
, HashValueTag tag
) {
58 return GetTestPinImpl(label
, tag
, true);
61 std::string
GetTestPinUnquoted(uint8 label
, HashValueTag tag
) {
62 return GetTestPinImpl(label
, tag
, false);
67 // Parses the given header |value| as both a Public-Key-Pins-Report-Only
68 // and Public-Key-Pins header. Returns true if the value parses
69 // successfully for both header types, and if the parsed hashes and
70 // report_uri match for both header types.
71 bool ParseAsHPKPHeader(const std::string
& value
,
72 const HashValueVector
& chain_hashes
,
73 base::TimeDelta
* max_age
,
74 bool* include_subdomains
,
75 HashValueVector
* hashes
,
78 bool report_only_include_subdomains
;
79 HashValueVector report_only_hashes
;
80 if (!ParseHPKPReportOnlyHeader(value
, &report_only_include_subdomains
,
81 &report_only_hashes
, &report_only_uri
)) {
85 bool result
= ParseHPKPHeader(value
, chain_hashes
, max_age
,
86 include_subdomains
, hashes
, report_uri
);
87 if (!result
|| report_only_include_subdomains
!= *include_subdomains
||
88 report_only_uri
!= *report_uri
||
89 report_only_hashes
.size() != hashes
->size()) {
93 for (size_t i
= 0; i
< report_only_hashes
.size(); i
++) {
94 if (!(*hashes
)[i
].Equals(report_only_hashes
[i
]))
101 class HttpSecurityHeadersTest
: public testing::Test
{
105 TEST_F(HttpSecurityHeadersTest
, BogusHeaders
) {
106 base::TimeDelta max_age
;
107 bool include_subdomains
= false;
110 ParseHSTSHeader(std::string(), &max_age
, &include_subdomains
));
111 EXPECT_FALSE(ParseHSTSHeader(" ", &max_age
, &include_subdomains
));
112 EXPECT_FALSE(ParseHSTSHeader("abc", &max_age
, &include_subdomains
));
113 EXPECT_FALSE(ParseHSTSHeader(" abc", &max_age
, &include_subdomains
));
114 EXPECT_FALSE(ParseHSTSHeader(" abc ", &max_age
, &include_subdomains
));
115 EXPECT_FALSE(ParseHSTSHeader("max-age", &max_age
, &include_subdomains
));
116 EXPECT_FALSE(ParseHSTSHeader(" max-age", &max_age
,
117 &include_subdomains
));
118 EXPECT_FALSE(ParseHSTSHeader(" max-age ", &max_age
,
119 &include_subdomains
));
120 EXPECT_FALSE(ParseHSTSHeader("max-age=", &max_age
, &include_subdomains
));
121 EXPECT_FALSE(ParseHSTSHeader(" max-age=", &max_age
,
122 &include_subdomains
));
123 EXPECT_FALSE(ParseHSTSHeader(" max-age =", &max_age
,
124 &include_subdomains
));
125 EXPECT_FALSE(ParseHSTSHeader(" max-age= ", &max_age
,
126 &include_subdomains
));
127 EXPECT_FALSE(ParseHSTSHeader(" max-age = ", &max_age
,
128 &include_subdomains
));
129 EXPECT_FALSE(ParseHSTSHeader(" max-age = xy", &max_age
,
130 &include_subdomains
));
131 EXPECT_FALSE(ParseHSTSHeader(" max-age = 3488a923", &max_age
,
132 &include_subdomains
));
133 EXPECT_FALSE(ParseHSTSHeader("max-age=3488a923 ", &max_age
,
134 &include_subdomains
));
135 EXPECT_FALSE(ParseHSTSHeader("max-ag=3488923", &max_age
,
136 &include_subdomains
));
137 EXPECT_FALSE(ParseHSTSHeader("max-aged=3488923", &max_age
,
138 &include_subdomains
));
139 EXPECT_FALSE(ParseHSTSHeader("max-age==3488923", &max_age
,
140 &include_subdomains
));
141 EXPECT_FALSE(ParseHSTSHeader("amax-age=3488923", &max_age
,
142 &include_subdomains
));
143 EXPECT_FALSE(ParseHSTSHeader("max-age=-3488923", &max_age
,
144 &include_subdomains
));
145 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 e", &max_age
,
146 &include_subdomains
));
147 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomain",
148 &max_age
, &include_subdomains
));
149 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923includesubdomains",
150 &max_age
, &include_subdomains
));
151 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923=includesubdomains",
152 &max_age
, &include_subdomains
));
153 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomainx",
154 &max_age
, &include_subdomains
));
155 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomain=",
156 &max_age
, &include_subdomains
));
157 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomain=true",
158 &max_age
, &include_subdomains
));
159 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomainsx",
160 &max_age
, &include_subdomains
));
161 EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomains x",
162 &max_age
, &include_subdomains
));
163 EXPECT_FALSE(ParseHSTSHeader("max-age=34889.23 includesubdomains",
164 &max_age
, &include_subdomains
));
165 EXPECT_FALSE(ParseHSTSHeader("max-age=34889 includesubdomains",
166 &max_age
, &include_subdomains
));
167 EXPECT_FALSE(ParseHSTSHeader(";;;; ;;;",
168 &max_age
, &include_subdomains
));
169 EXPECT_FALSE(ParseHSTSHeader(";;;; includeSubDomains;;;",
170 &max_age
, &include_subdomains
));
171 EXPECT_FALSE(ParseHSTSHeader(" includeSubDomains; ",
172 &max_age
, &include_subdomains
));
173 EXPECT_FALSE(ParseHSTSHeader(";",
174 &max_age
, &include_subdomains
));
175 EXPECT_FALSE(ParseHSTSHeader("max-age; ;",
176 &max_age
, &include_subdomains
));
178 // Check the out args were not updated by checking the default
179 // values for its predictable fields.
180 EXPECT_EQ(0, max_age
.InSeconds());
181 EXPECT_FALSE(include_subdomains
);
184 static void TestBogusPinsHeaders(HashValueTag tag
) {
185 base::TimeDelta max_age
;
186 bool include_subdomains
;
187 HashValueVector hashes
;
188 HashValueVector chain_hashes
;
191 // Set some fake "chain" hashes
192 chain_hashes
.push_back(GetTestHashValue(1, tag
));
193 chain_hashes
.push_back(GetTestHashValue(2, tag
));
194 chain_hashes
.push_back(GetTestHashValue(3, tag
));
196 // The good pin must be in the chain, the backup pin must not be
197 std::string good_pin
= GetTestPin(2, tag
);
198 std::string good_pin_unquoted
= GetTestPinUnquoted(2, tag
);
199 std::string backup_pin
= GetTestPin(4, tag
);
201 EXPECT_FALSE(ParseAsHPKPHeader(std::string(), chain_hashes
, &max_age
,
202 &include_subdomains
, &hashes
, &report_uri
));
203 EXPECT_FALSE(ParseAsHPKPHeader(" ", chain_hashes
, &max_age
,
204 &include_subdomains
, &hashes
, &report_uri
));
205 EXPECT_FALSE(ParseAsHPKPHeader("abc", chain_hashes
, &max_age
,
206 &include_subdomains
, &hashes
, &report_uri
));
207 EXPECT_FALSE(ParseAsHPKPHeader(" abc", chain_hashes
, &max_age
,
208 &include_subdomains
, &hashes
, &report_uri
));
209 EXPECT_FALSE(ParseAsHPKPHeader(" abc ", chain_hashes
, &max_age
,
210 &include_subdomains
, &hashes
, &report_uri
));
211 EXPECT_FALSE(ParseAsHPKPHeader("max-age", chain_hashes
, &max_age
,
212 &include_subdomains
, &hashes
, &report_uri
));
213 EXPECT_FALSE(ParseAsHPKPHeader(" max-age", chain_hashes
, &max_age
,
214 &include_subdomains
, &hashes
, &report_uri
));
215 EXPECT_FALSE(ParseAsHPKPHeader(" max-age ", chain_hashes
, &max_age
,
216 &include_subdomains
, &hashes
, &report_uri
));
217 EXPECT_FALSE(ParseAsHPKPHeader("max-age=", chain_hashes
, &max_age
,
218 &include_subdomains
, &hashes
, &report_uri
));
219 EXPECT_FALSE(ParseAsHPKPHeader(" max-age=", chain_hashes
, &max_age
,
220 &include_subdomains
, &hashes
, &report_uri
));
221 EXPECT_FALSE(ParseAsHPKPHeader(" max-age =", chain_hashes
, &max_age
,
222 &include_subdomains
, &hashes
, &report_uri
));
223 EXPECT_FALSE(ParseAsHPKPHeader(" max-age= ", chain_hashes
, &max_age
,
224 &include_subdomains
, &hashes
, &report_uri
));
225 EXPECT_FALSE(ParseAsHPKPHeader(" max-age = ", chain_hashes
, &max_age
,
226 &include_subdomains
, &hashes
, &report_uri
));
227 EXPECT_FALSE(ParseAsHPKPHeader(" max-age = xy", chain_hashes
, &max_age
,
228 &include_subdomains
, &hashes
, &report_uri
));
229 EXPECT_FALSE(ParseAsHPKPHeader(" max-age = 3488a923", chain_hashes
,
230 &max_age
, &include_subdomains
, &hashes
,
232 EXPECT_FALSE(ParseAsHPKPHeader("max-age=3488a923 ", chain_hashes
, &max_age
,
233 &include_subdomains
, &hashes
, &report_uri
));
234 EXPECT_FALSE(ParseAsHPKPHeader(
235 "max-ag=3488923pins=" + good_pin
+ "," + backup_pin
, chain_hashes
,
236 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
237 EXPECT_FALSE(ParseAsHPKPHeader(
238 "max-age=3488923;pins=" + good_pin
+ "," + backup_pin
+
239 "report-uri=\"http://foo.com\"",
240 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
241 EXPECT_FALSE(ParseAsHPKPHeader("max-aged=3488923" + backup_pin
, chain_hashes
,
242 &max_age
, &include_subdomains
, &hashes
,
244 EXPECT_FALSE(ParseAsHPKPHeader("max-aged=3488923; " + backup_pin
,
245 chain_hashes
, &max_age
, &include_subdomains
,
246 &hashes
, &report_uri
));
247 EXPECT_FALSE(ParseAsHPKPHeader(
248 "max-aged=3488923; " + backup_pin
+ ";" + backup_pin
, chain_hashes
,
249 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
250 EXPECT_FALSE(ParseAsHPKPHeader(
251 "max-aged=3488923; " + good_pin
+ ";" + good_pin
, chain_hashes
, &max_age
,
252 &include_subdomains
, &hashes
, &report_uri
));
253 EXPECT_FALSE(ParseAsHPKPHeader("max-aged=3488923; " + good_pin
, chain_hashes
,
254 &max_age
, &include_subdomains
, &hashes
,
256 EXPECT_FALSE(ParseAsHPKPHeader("max-age==3488923", chain_hashes
, &max_age
,
257 &include_subdomains
, &hashes
, &report_uri
));
258 EXPECT_FALSE(ParseAsHPKPHeader("amax-age=3488923", chain_hashes
, &max_age
,
259 &include_subdomains
, &hashes
, &report_uri
));
260 EXPECT_FALSE(ParseAsHPKPHeader("max-age=-3488923", chain_hashes
, &max_age
,
261 &include_subdomains
, &hashes
, &report_uri
));
262 EXPECT_FALSE(ParseAsHPKPHeader("max-age=3488923;", chain_hashes
, &max_age
,
263 &include_subdomains
, &hashes
, &report_uri
));
264 EXPECT_FALSE(ParseAsHPKPHeader("max-age=3488923 e", chain_hashes
,
265 &max_age
, &include_subdomains
, &hashes
,
267 EXPECT_FALSE(ParseAsHPKPHeader("max-age=3488923 includesubdomain",
268 chain_hashes
, &max_age
, &include_subdomains
,
269 &hashes
, &report_uri
));
270 EXPECT_FALSE(ParseAsHPKPHeader(
271 "max-age=3488923 report-uri=\"http://foo.com\"", chain_hashes
,
272 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
273 EXPECT_FALSE(ParseAsHPKPHeader("max-age=34889.23", chain_hashes
, &max_age
,
274 &include_subdomains
, &hashes
, &report_uri
));
275 EXPECT_FALSE(ParseAsHPKPHeader(
276 "max-age=243; " + good_pin_unquoted
+ ";" + backup_pin
, chain_hashes
,
277 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
278 EXPECT_FALSE(ParseAsHPKPHeader(
279 "max-age=243; " + good_pin
+ ";" + backup_pin
+ ";report-uri=;",
280 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
281 EXPECT_FALSE(ParseAsHPKPHeader("max-age=243; " + good_pin
+ ";" + backup_pin
+
282 ";report-uri=http://foo.com;",
283 chain_hashes
, &max_age
, &include_subdomains
,
284 &hashes
, &report_uri
));
285 EXPECT_FALSE(ParseAsHPKPHeader(
286 "max-age=243; " + good_pin
+ ";" + backup_pin
+ ";report-uri=''",
287 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
289 // Test that the parser rejects misquoted strings.
290 EXPECT_FALSE(ParseAsHPKPHeader(
291 "max-age=999; " + backup_pin
+ "; " + good_pin
+
292 "; report-uri=\"http://foo;bar\'",
293 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
295 // Test that the parser rejects invalid report-uris.
296 EXPECT_FALSE(ParseAsHPKPHeader("max-age=999; " + backup_pin
+ "; " +
297 good_pin
+ "; report-uri=\"foo;bar\'",
298 chain_hashes
, &max_age
, &include_subdomains
,
299 &hashes
, &report_uri
));
301 // Check the out args were not updated by checking the default
302 // values for its predictable fields.
303 EXPECT_EQ(0, max_age
.InSeconds());
304 EXPECT_EQ(hashes
.size(), (size_t)0);
307 TEST_F(HttpSecurityHeadersTest
, ValidSTSHeaders
) {
308 base::TimeDelta max_age
;
309 base::TimeDelta expect_max_age
;
310 bool include_subdomains
= false;
312 EXPECT_TRUE(ParseHSTSHeader("max-age=243", &max_age
,
313 &include_subdomains
));
314 expect_max_age
= base::TimeDelta::FromSeconds(243);
315 EXPECT_EQ(expect_max_age
, max_age
);
316 EXPECT_FALSE(include_subdomains
);
318 EXPECT_TRUE(ParseHSTSHeader("max-age=3488923;", &max_age
,
319 &include_subdomains
));
321 EXPECT_TRUE(ParseHSTSHeader(" Max-agE = 567", &max_age
,
322 &include_subdomains
));
323 expect_max_age
= base::TimeDelta::FromSeconds(567);
324 EXPECT_EQ(expect_max_age
, max_age
);
325 EXPECT_FALSE(include_subdomains
);
327 EXPECT_TRUE(ParseHSTSHeader(" mAx-aGe = 890 ", &max_age
,
328 &include_subdomains
));
329 expect_max_age
= base::TimeDelta::FromSeconds(890);
330 EXPECT_EQ(expect_max_age
, max_age
);
331 EXPECT_FALSE(include_subdomains
);
333 EXPECT_TRUE(ParseHSTSHeader("max-age=123;incLudesUbdOmains", &max_age
,
334 &include_subdomains
));
335 expect_max_age
= base::TimeDelta::FromSeconds(123);
336 EXPECT_EQ(expect_max_age
, max_age
);
337 EXPECT_TRUE(include_subdomains
);
339 EXPECT_TRUE(ParseHSTSHeader("incLudesUbdOmains; max-age=123", &max_age
,
340 &include_subdomains
));
341 expect_max_age
= base::TimeDelta::FromSeconds(123);
342 EXPECT_EQ(expect_max_age
, max_age
);
343 EXPECT_TRUE(include_subdomains
);
345 EXPECT_TRUE(ParseHSTSHeader(" 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(
352 " incLudesUbdOmains; max-age=123; pumpkin=kitten", &max_age
,
353 &include_subdomains
));
354 expect_max_age
= base::TimeDelta::FromSeconds(123);
355 EXPECT_EQ(expect_max_age
, max_age
);
356 EXPECT_TRUE(include_subdomains
);
358 EXPECT_TRUE(ParseHSTSHeader(
359 " pumpkin=894; incLudesUbdOmains; max-age=123 ", &max_age
,
360 &include_subdomains
));
361 expect_max_age
= base::TimeDelta::FromSeconds(123);
362 EXPECT_EQ(expect_max_age
, max_age
);
363 EXPECT_TRUE(include_subdomains
);
365 EXPECT_TRUE(ParseHSTSHeader(
366 " pumpkin; incLudesUbdOmains; max-age=123 ", &max_age
,
367 &include_subdomains
));
368 expect_max_age
= base::TimeDelta::FromSeconds(123);
369 EXPECT_EQ(expect_max_age
, max_age
);
370 EXPECT_TRUE(include_subdomains
);
372 EXPECT_TRUE(ParseHSTSHeader(
373 " pumpkin; incLudesUbdOmains; max-age=\"123\" ", &max_age
,
374 &include_subdomains
));
375 expect_max_age
= base::TimeDelta::FromSeconds(123);
376 EXPECT_EQ(expect_max_age
, max_age
);
377 EXPECT_TRUE(include_subdomains
);
379 EXPECT_TRUE(ParseHSTSHeader(
380 "animal=\"squirrel; distinguished\"; incLudesUbdOmains; max-age=123",
381 &max_age
, &include_subdomains
));
382 expect_max_age
= base::TimeDelta::FromSeconds(123);
383 EXPECT_EQ(expect_max_age
, max_age
);
384 EXPECT_TRUE(include_subdomains
);
386 EXPECT_TRUE(ParseHSTSHeader("max-age=394082; incLudesUbdOmains",
387 &max_age
, &include_subdomains
));
388 expect_max_age
= base::TimeDelta::FromSeconds(394082);
389 EXPECT_EQ(expect_max_age
, max_age
);
390 EXPECT_TRUE(include_subdomains
);
392 EXPECT_TRUE(ParseHSTSHeader(
393 "max-age=39408299 ;incLudesUbdOmains", &max_age
,
394 &include_subdomains
));
395 expect_max_age
= base::TimeDelta::FromSeconds(
396 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(39408299))));
397 EXPECT_EQ(expect_max_age
, max_age
);
398 EXPECT_TRUE(include_subdomains
);
400 EXPECT_TRUE(ParseHSTSHeader(
401 "max-age=394082038 ; incLudesUbdOmains", &max_age
,
402 &include_subdomains
));
403 expect_max_age
= base::TimeDelta::FromSeconds(
404 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
405 EXPECT_EQ(expect_max_age
, max_age
);
406 EXPECT_TRUE(include_subdomains
);
408 EXPECT_TRUE(ParseHSTSHeader(
409 "max-age=394082038 ; incLudesUbdOmains;", &max_age
,
410 &include_subdomains
));
411 expect_max_age
= base::TimeDelta::FromSeconds(
412 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
413 EXPECT_EQ(expect_max_age
, max_age
);
414 EXPECT_TRUE(include_subdomains
);
416 EXPECT_TRUE(ParseHSTSHeader(
417 ";; max-age=394082038 ; incLudesUbdOmains; ;", &max_age
,
418 &include_subdomains
));
419 expect_max_age
= base::TimeDelta::FromSeconds(
420 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
421 EXPECT_EQ(expect_max_age
, max_age
);
422 EXPECT_TRUE(include_subdomains
);
424 EXPECT_TRUE(ParseHSTSHeader(
425 ";; max-age=394082038 ;", &max_age
,
426 &include_subdomains
));
427 expect_max_age
= base::TimeDelta::FromSeconds(
428 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
429 EXPECT_EQ(expect_max_age
, max_age
);
430 EXPECT_FALSE(include_subdomains
);
432 EXPECT_TRUE(ParseHSTSHeader(
433 ";; ; ; max-age=394082038;;; includeSubdomains ;; ;", &max_age
,
434 &include_subdomains
));
435 expect_max_age
= base::TimeDelta::FromSeconds(
436 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
437 EXPECT_EQ(expect_max_age
, max_age
);
438 EXPECT_TRUE(include_subdomains
);
440 EXPECT_TRUE(ParseHSTSHeader(
441 "incLudesUbdOmains ; max-age=394082038 ;;", &max_age
,
442 &include_subdomains
));
443 expect_max_age
= base::TimeDelta::FromSeconds(
444 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
445 EXPECT_EQ(expect_max_age
, max_age
);
446 EXPECT_TRUE(include_subdomains
);
448 EXPECT_TRUE(ParseHSTSHeader(
449 " max-age=0 ; incLudesUbdOmains ", &max_age
,
450 &include_subdomains
));
451 expect_max_age
= base::TimeDelta::FromSeconds(0);
452 EXPECT_EQ(expect_max_age
, max_age
);
453 EXPECT_TRUE(include_subdomains
);
455 EXPECT_TRUE(ParseHSTSHeader(
456 " max-age=999999999999999999999999999999999999999999999 ;"
457 " incLudesUbdOmains ", &max_age
, &include_subdomains
));
458 expect_max_age
= base::TimeDelta::FromSeconds(
460 EXPECT_EQ(expect_max_age
, max_age
);
461 EXPECT_TRUE(include_subdomains
);
464 static void TestValidPKPHeaders(HashValueTag tag
) {
465 base::TimeDelta max_age
;
466 base::TimeDelta expect_max_age
;
467 bool include_subdomains
;
468 HashValueVector hashes
;
469 HashValueVector chain_hashes
;
470 GURL expect_report_uri
;
473 // Set some fake "chain" hashes into chain_hashes
474 chain_hashes
.push_back(GetTestHashValue(1, tag
));
475 chain_hashes
.push_back(GetTestHashValue(2, tag
));
476 chain_hashes
.push_back(GetTestHashValue(3, tag
));
478 // The good pin must be in the chain, the backup pin must not be
479 std::string good_pin
= GetTestPin(2, tag
);
480 std::string good_pin2
= GetTestPin(3, tag
);
481 std::string backup_pin
= GetTestPin(4, tag
);
483 EXPECT_TRUE(ParseAsHPKPHeader("max-age=243; " + good_pin
+ ";" + backup_pin
,
484 chain_hashes
, &max_age
, &include_subdomains
,
485 &hashes
, &report_uri
));
486 expect_max_age
= base::TimeDelta::FromSeconds(243);
487 EXPECT_EQ(expect_max_age
, max_age
);
488 EXPECT_FALSE(include_subdomains
);
489 EXPECT_TRUE(report_uri
.is_empty());
491 EXPECT_TRUE(ParseAsHPKPHeader("max-age=243; " + good_pin
+ ";" + backup_pin
+
492 "; report-uri= \"http://example.test/foo\"",
493 chain_hashes
, &max_age
, &include_subdomains
,
494 &hashes
, &report_uri
));
495 expect_max_age
= base::TimeDelta::FromSeconds(243);
496 expect_report_uri
= GURL("http://example.test/foo");
497 EXPECT_EQ(expect_max_age
, max_age
);
498 EXPECT_FALSE(include_subdomains
);
499 EXPECT_EQ(expect_report_uri
, report_uri
);
501 EXPECT_TRUE(ParseAsHPKPHeader(
502 " " + good_pin
+ "; " + backup_pin
+
503 " ; Max-agE = 567; repOrT-URi = \"http://example.test/foo\"",
504 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
505 expect_max_age
= base::TimeDelta::FromSeconds(567);
506 expect_report_uri
= GURL("http://example.test/foo");
507 EXPECT_EQ(expect_max_age
, max_age
);
508 EXPECT_FALSE(include_subdomains
);
509 EXPECT_EQ(expect_report_uri
, report_uri
);
511 EXPECT_TRUE(ParseAsHPKPHeader("includeSubDOMAINS;" + good_pin
+ ";" +
512 backup_pin
+ " ; mAx-aGe = 890 ",
513 chain_hashes
, &max_age
, &include_subdomains
,
514 &hashes
, &report_uri
));
515 expect_max_age
= base::TimeDelta::FromSeconds(890);
516 EXPECT_EQ(expect_max_age
, max_age
);
517 EXPECT_TRUE(include_subdomains
);
519 EXPECT_TRUE(ParseAsHPKPHeader(
520 good_pin
+ ";" + backup_pin
+ "; max-age=123;IGNORED;", chain_hashes
,
521 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
522 expect_max_age
= base::TimeDelta::FromSeconds(123);
523 EXPECT_EQ(expect_max_age
, max_age
);
524 EXPECT_FALSE(include_subdomains
);
526 EXPECT_TRUE(ParseAsHPKPHeader(
527 "max-age=394082;" + backup_pin
+ ";" + good_pin
+ "; ", chain_hashes
,
528 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
529 expect_max_age
= base::TimeDelta::FromSeconds(394082);
530 EXPECT_EQ(expect_max_age
, max_age
);
531 EXPECT_FALSE(include_subdomains
);
533 EXPECT_TRUE(ParseAsHPKPHeader(
534 "max-age=39408299 ;" + backup_pin
+ ";" + good_pin
+ "; ", chain_hashes
,
535 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
536 expect_max_age
= base::TimeDelta::FromSeconds(
537 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(39408299))));
538 EXPECT_EQ(expect_max_age
, max_age
);
539 EXPECT_FALSE(include_subdomains
);
541 EXPECT_TRUE(ParseAsHPKPHeader(
542 "max-age=39408038 ; cybers=39408038 ; includeSubdomains; " +
543 good_pin
+ ";" + backup_pin
+ "; ",
544 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
545 expect_max_age
= base::TimeDelta::FromSeconds(
546 std::min(kMaxHSTSAgeSecs
, static_cast<int64
>(INT64_C(394082038))));
547 EXPECT_EQ(expect_max_age
, max_age
);
548 EXPECT_TRUE(include_subdomains
);
550 EXPECT_TRUE(ParseAsHPKPHeader(
551 " max-age=0 ; " + good_pin
+ ";" + backup_pin
, chain_hashes
, &max_age
,
552 &include_subdomains
, &hashes
, &report_uri
));
553 expect_max_age
= base::TimeDelta::FromSeconds(0);
554 EXPECT_EQ(expect_max_age
, max_age
);
555 EXPECT_FALSE(include_subdomains
);
557 EXPECT_TRUE(ParseAsHPKPHeader(
558 " max-age=0 ; includeSubdomains; " + good_pin
+ ";" + backup_pin
,
559 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
560 expect_max_age
= base::TimeDelta::FromSeconds(0);
561 EXPECT_EQ(expect_max_age
, max_age
);
562 EXPECT_TRUE(include_subdomains
);
564 EXPECT_TRUE(ParseAsHPKPHeader(
565 " max-age=999999999999999999999999999999999999999999999 ; " +
566 backup_pin
+ ";" + good_pin
+ "; ",
567 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
568 expect_max_age
= base::TimeDelta::FromSeconds(kMaxHSTSAgeSecs
);
569 EXPECT_EQ(expect_max_age
, max_age
);
570 EXPECT_FALSE(include_subdomains
);
572 EXPECT_TRUE(ParseAsHPKPHeader(
573 " max-age=999999999999999999999999999999999999999999999 ; " +
574 backup_pin
+ ";" + good_pin
+
575 "; report-uri=\"http://example.test/foo\"",
576 chain_hashes
, &max_age
, &include_subdomains
, &hashes
, &report_uri
));
577 expect_max_age
= base::TimeDelta::FromSeconds(kMaxHSTSAgeSecs
);
578 expect_report_uri
= GURL("http://example.test/foo");
579 EXPECT_EQ(expect_max_age
, max_age
);
580 EXPECT_FALSE(include_subdomains
);
581 EXPECT_EQ(expect_report_uri
, report_uri
);
583 // Test that parsing a different header resets the hashes.
585 EXPECT_TRUE(ParseAsHPKPHeader(
586 " max-age=999; " + backup_pin
+ ";" + good_pin
+ "; ", chain_hashes
,
587 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
588 EXPECT_EQ(2u, hashes
.size());
589 EXPECT_TRUE(ParseAsHPKPHeader(
590 " max-age=999; " + backup_pin
+ ";" + good_pin2
+ "; ", chain_hashes
,
591 &max_age
, &include_subdomains
, &hashes
, &report_uri
));
592 EXPECT_EQ(2u, hashes
.size());
594 // Test that the parser correctly parses an unencoded ';' inside a
595 // quoted report-uri.
596 EXPECT_TRUE(ParseAsHPKPHeader("max-age=999; " + backup_pin
+ "; " + good_pin
+
597 "; report-uri=\"http://foo.com/?;bar\"",
598 chain_hashes
, &max_age
, &include_subdomains
,
599 &hashes
, &report_uri
));
600 expect_max_age
= base::TimeDelta::FromSeconds(999);
601 expect_report_uri
= GURL("http://foo.com/?;bar");
602 EXPECT_EQ(expect_max_age
, max_age
);
603 EXPECT_FALSE(include_subdomains
);
604 EXPECT_EQ(expect_report_uri
, report_uri
);
606 // Test that the parser correctly parses a report-uri with a >0x7f
608 std::string uri
= "http://foo.com/";
610 expect_report_uri
= GURL(uri
);
611 EXPECT_TRUE(ParseAsHPKPHeader("max-age=999; " + backup_pin
+ "; " + good_pin
+
612 "; report-uri=\"" + uri
+ "\"",
613 chain_hashes
, &max_age
, &include_subdomains
,
614 &hashes
, &report_uri
));
615 expect_max_age
= base::TimeDelta::FromSeconds(999);
616 EXPECT_EQ(expect_max_age
, max_age
);
617 EXPECT_FALSE(include_subdomains
);
618 EXPECT_EQ(expect_report_uri
, report_uri
);
620 // Test that the parser allows quoted max-age values.
621 EXPECT_TRUE(ParseAsHPKPHeader(
622 "max-age='999'; " + backup_pin
+ "; " + good_pin
, chain_hashes
, &max_age
,
623 &include_subdomains
, &hashes
, &report_uri
));
624 expect_max_age
= base::TimeDelta::FromSeconds(999);
625 EXPECT_EQ(expect_max_age
, max_age
);
626 EXPECT_FALSE(include_subdomains
);
628 // Test that the parser handles escaped values.
629 expect_report_uri
= GURL("http://foo.com'a");
630 EXPECT_TRUE(ParseAsHPKPHeader("max-age=999; " + backup_pin
+ "; " + good_pin
+
631 "; report-uri='http://foo.com\\'\\a'",
632 chain_hashes
, &max_age
, &include_subdomains
,
633 &hashes
, &report_uri
));
634 expect_max_age
= base::TimeDelta::FromSeconds(999);
635 EXPECT_EQ(expect_max_age
, max_age
);
636 EXPECT_FALSE(include_subdomains
);
637 EXPECT_EQ(expect_report_uri
, report_uri
);
639 // Test that the parser does not require max-age for Report-Only
641 expect_report_uri
= GURL("http://foo.com");
642 EXPECT_TRUE(ParseHPKPReportOnlyHeader(
643 backup_pin
+ "; " + good_pin
+ "; report-uri='http://foo.com'",
644 &include_subdomains
, &hashes
, &report_uri
));
645 EXPECT_EQ(expect_report_uri
, report_uri
);
648 TEST_F(HttpSecurityHeadersTest
, BogusPinsHeadersSHA1
) {
649 TestBogusPinsHeaders(HASH_VALUE_SHA1
);
652 TEST_F(HttpSecurityHeadersTest
, BogusPinsHeadersSHA256
) {
653 TestBogusPinsHeaders(HASH_VALUE_SHA256
);
656 TEST_F(HttpSecurityHeadersTest
, ValidPKPHeadersSHA1
) {
657 TestValidPKPHeaders(HASH_VALUE_SHA1
);
660 TEST_F(HttpSecurityHeadersTest
, ValidPKPHeadersSHA256
) {
661 TestValidPKPHeaders(HASH_VALUE_SHA256
);
664 TEST_F(HttpSecurityHeadersTest
, UpdateDynamicPKPOnly
) {
665 TransportSecurityState state
;
666 TransportSecurityState::STSState static_sts_state
;
667 TransportSecurityState::PKPState static_pkp_state
;
669 // docs.google.com has preloaded pins.
670 std::string domain
= "docs.google.com";
671 state
.enable_static_pins_
= true;
673 state
.GetStaticDomainState(domain
, &static_sts_state
, &static_pkp_state
));
674 EXPECT_GT(static_pkp_state
.spki_hashes
.size(), 1UL);
675 HashValueVector saved_hashes
= static_pkp_state
.spki_hashes
;
677 // Add a header, which should only update the dynamic state.
678 HashValue good_hash
= GetTestHashValue(1, HASH_VALUE_SHA1
);
679 HashValue backup_hash
= GetTestHashValue(2, HASH_VALUE_SHA1
);
680 std::string good_pin
= GetTestPin(1, HASH_VALUE_SHA1
);
681 std::string backup_pin
= GetTestPin(2, HASH_VALUE_SHA1
);
682 GURL
report_uri("http://google.com");
683 std::string header
= "max-age = 10000; " + good_pin
+ "; " + backup_pin
+
684 ";report-uri=\"" + report_uri
.spec() + "\"";
686 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
688 ssl_info
.public_key_hashes
.push_back(good_hash
);
689 ssl_info
.public_key_hashes
.push_back(saved_hashes
[0]);
690 EXPECT_TRUE(state
.AddHPKPHeader(domain
, header
, ssl_info
));
692 // Expect the static state to remain unchanged.
693 TransportSecurityState::STSState new_static_sts_state
;
694 TransportSecurityState::PKPState new_static_pkp_state
;
695 EXPECT_TRUE(state
.GetStaticDomainState(domain
, &new_static_sts_state
,
696 &new_static_pkp_state
));
697 for (size_t i
= 0; i
< saved_hashes
.size(); ++i
) {
699 HashValuesEqual(saved_hashes
[i
])(new_static_pkp_state
.spki_hashes
[i
]));
702 // Expect the dynamic state to reflect the header.
703 TransportSecurityState::PKPState dynamic_pkp_state
;
704 EXPECT_TRUE(state
.GetDynamicPKPState(domain
, &dynamic_pkp_state
));
705 EXPECT_EQ(2UL, dynamic_pkp_state
.spki_hashes
.size());
706 EXPECT_EQ(report_uri
, dynamic_pkp_state
.report_uri
);
708 HashValueVector::const_iterator hash
= std::find_if(
709 dynamic_pkp_state
.spki_hashes
.begin(),
710 dynamic_pkp_state
.spki_hashes
.end(), HashValuesEqual(good_hash
));
711 EXPECT_NE(dynamic_pkp_state
.spki_hashes
.end(), hash
);
713 hash
= std::find_if(dynamic_pkp_state
.spki_hashes
.begin(),
714 dynamic_pkp_state
.spki_hashes
.end(),
715 HashValuesEqual(backup_hash
));
716 EXPECT_NE(dynamic_pkp_state
.spki_hashes
.end(), hash
);
718 // Expect the overall state to reflect the header, too.
719 EXPECT_TRUE(state
.HasPublicKeyPins(domain
));
720 HashValueVector hashes
;
721 hashes
.push_back(good_hash
);
722 std::string failure_log
;
723 const bool is_issued_by_known_root
= true;
724 HostPortPair
domain_port(domain
, 443);
725 EXPECT_TRUE(state
.CheckPublicKeyPins(
726 domain_port
, is_issued_by_known_root
, hashes
, nullptr, nullptr,
727 TransportSecurityState::DISABLE_PIN_REPORTS
, &failure_log
));
729 TransportSecurityState::PKPState new_dynamic_pkp_state
;
730 EXPECT_TRUE(state
.GetDynamicPKPState(domain
, &new_dynamic_pkp_state
));
731 EXPECT_EQ(2UL, new_dynamic_pkp_state
.spki_hashes
.size());
732 EXPECT_EQ(report_uri
, new_dynamic_pkp_state
.report_uri
);
734 hash
= std::find_if(new_dynamic_pkp_state
.spki_hashes
.begin(),
735 new_dynamic_pkp_state
.spki_hashes
.end(),
736 HashValuesEqual(good_hash
));
737 EXPECT_NE(new_dynamic_pkp_state
.spki_hashes
.end(), hash
);
739 hash
= std::find_if(new_dynamic_pkp_state
.spki_hashes
.begin(),
740 new_dynamic_pkp_state
.spki_hashes
.end(),
741 HashValuesEqual(backup_hash
));
742 EXPECT_NE(new_dynamic_pkp_state
.spki_hashes
.end(), hash
);
745 TEST_F(HttpSecurityHeadersTest
, UpdateDynamicPKPMaxAge0
) {
746 TransportSecurityState state
;
747 TransportSecurityState::STSState static_sts_state
;
748 TransportSecurityState::PKPState static_pkp_state
;
750 // docs.google.com has preloaded pins.
751 std::string domain
= "docs.google.com";
752 state
.enable_static_pins_
= true;
754 state
.GetStaticDomainState(domain
, &static_sts_state
, &static_pkp_state
));
755 EXPECT_GT(static_pkp_state
.spki_hashes
.size(), 1UL);
756 HashValueVector saved_hashes
= static_pkp_state
.spki_hashes
;
758 // Add a header, which should only update the dynamic state.
759 HashValue good_hash
= GetTestHashValue(1, HASH_VALUE_SHA1
);
760 std::string good_pin
= GetTestPin(1, HASH_VALUE_SHA1
);
761 std::string backup_pin
= GetTestPin(2, HASH_VALUE_SHA1
);
762 std::string header
= "max-age = 10000; " + good_pin
+ "; " + backup_pin
;
764 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
766 ssl_info
.public_key_hashes
.push_back(good_hash
);
767 ssl_info
.public_key_hashes
.push_back(saved_hashes
[0]);
768 EXPECT_TRUE(state
.AddHPKPHeader(domain
, header
, ssl_info
));
770 // Expect the static state to remain unchanged.
771 TransportSecurityState::STSState new_static_sts_state
;
772 TransportSecurityState::PKPState new_static_pkp_state
;
773 EXPECT_TRUE(state
.GetStaticDomainState(domain
, &new_static_sts_state
,
774 &new_static_pkp_state
));
775 EXPECT_EQ(saved_hashes
.size(), new_static_pkp_state
.spki_hashes
.size());
776 for (size_t i
= 0; i
< saved_hashes
.size(); ++i
) {
778 HashValuesEqual(saved_hashes
[i
])(new_static_pkp_state
.spki_hashes
[i
]));
781 // Expect the dynamic state to have pins.
782 TransportSecurityState::PKPState new_dynamic_pkp_state
;
783 EXPECT_TRUE(state
.GetDynamicPKPState(domain
, &new_dynamic_pkp_state
));
784 EXPECT_EQ(2UL, new_dynamic_pkp_state
.spki_hashes
.size());
785 EXPECT_TRUE(new_dynamic_pkp_state
.HasPublicKeyPins());
787 // Now set another header with max-age=0, and check that the pins are
788 // cleared in the dynamic state only.
789 header
= "max-age = 0; " + good_pin
+ "; " + backup_pin
;
790 EXPECT_TRUE(state
.AddHPKPHeader(domain
, header
, ssl_info
));
792 // Expect the static state to remain unchanged.
793 TransportSecurityState::PKPState new_static_pkp_state2
;
794 EXPECT_TRUE(state
.GetStaticDomainState(domain
, &static_sts_state
,
795 &new_static_pkp_state2
));
796 EXPECT_EQ(saved_hashes
.size(), new_static_pkp_state2
.spki_hashes
.size());
797 for (size_t i
= 0; i
< saved_hashes
.size(); ++i
) {
799 HashValuesEqual(saved_hashes
[i
])(new_static_pkp_state2
.spki_hashes
[i
]));
802 // Expect the dynamic pins to be gone.
803 TransportSecurityState::PKPState new_dynamic_pkp_state2
;
804 EXPECT_FALSE(state
.GetDynamicPKPState(domain
, &new_dynamic_pkp_state2
));
806 // Expect the exact-matching static policy to continue to apply, even
807 // though dynamic policy has been removed. (This policy may change in the
808 // future, in which case this test must be updated.)
809 EXPECT_TRUE(state
.HasPublicKeyPins(domain
));
810 EXPECT_TRUE(state
.ShouldSSLErrorsBeFatal(domain
));
811 std::string failure_log
;
813 // Damage the hashes to cause a pin validation failure.
814 new_static_pkp_state2
.spki_hashes
[0].data()[0] ^= 0x80;
815 new_static_pkp_state2
.spki_hashes
[1].data()[0] ^= 0x80;
816 new_static_pkp_state2
.spki_hashes
[2].data()[0] ^= 0x80;
818 const bool is_issued_by_known_root
= true;
819 HostPortPair
domain_port(domain
, 443);
820 EXPECT_FALSE(state
.CheckPublicKeyPins(
821 domain_port
, is_issued_by_known_root
, new_static_pkp_state2
.spki_hashes
,
822 nullptr, nullptr, TransportSecurityState::DISABLE_PIN_REPORTS
,
824 EXPECT_NE(0UL, failure_log
.length());
827 // Tests that when a static HSTS and a static HPKP entry are present, adding a
828 // dynamic HSTS header does not clobber the static HPKP entry. Further, adding a
829 // dynamic HPKP entry could not affect the HSTS entry for the site.
830 TEST_F(HttpSecurityHeadersTest
, NoClobberPins
) {
831 TransportSecurityState state
;
832 TransportSecurityState::STSState sts_state
;
833 TransportSecurityState::PKPState pkp_state
;
835 // accounts.google.com has preloaded pins.
836 std::string domain
= "accounts.google.com";
837 state
.enable_static_pins_
= true;
839 // Retrieve the static STS and PKP states as it is by default, including its
841 EXPECT_TRUE(state
.GetStaticDomainState(domain
, &sts_state
, &pkp_state
));
842 HashValueVector saved_hashes
= pkp_state
.spki_hashes
;
843 EXPECT_TRUE(sts_state
.ShouldUpgradeToSSL());
844 EXPECT_TRUE(pkp_state
.HasPublicKeyPins());
845 EXPECT_TRUE(state
.ShouldUpgradeToSSL(domain
));
846 EXPECT_TRUE(state
.HasPublicKeyPins(domain
));
848 // Add a dynamic HSTS header. CheckPublicKeyPins should still pass when given
849 // the original |saved_hashes|, indicating that the static PKP data is still
850 // configured for the domain.
851 EXPECT_TRUE(state
.AddHSTSHeader(domain
, "includesubdomains; max-age=10000"));
852 EXPECT_TRUE(state
.ShouldUpgradeToSSL(domain
));
853 std::string failure_log
;
854 const bool is_issued_by_known_root
= true;
855 HostPortPair
domain_port(domain
, 443);
856 EXPECT_TRUE(state
.CheckPublicKeyPins(
857 domain_port
, is_issued_by_known_root
, saved_hashes
, nullptr, nullptr,
858 TransportSecurityState::DISABLE_PIN_REPORTS
, &failure_log
));
860 // Add an HPKP header, which should only update the dynamic state.
861 HashValue good_hash
= GetTestHashValue(1, HASH_VALUE_SHA1
);
862 std::string good_pin
= GetTestPin(1, HASH_VALUE_SHA1
);
863 std::string backup_pin
= GetTestPin(2, HASH_VALUE_SHA1
);
864 std::string header
= "max-age = 10000; " + good_pin
+ "; " + backup_pin
;
866 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
868 ssl_info
.public_key_hashes
.push_back(good_hash
);
869 ssl_info
.public_key_hashes
.push_back(saved_hashes
[0]);
870 EXPECT_TRUE(state
.AddHPKPHeader(domain
, header
, ssl_info
));
872 EXPECT_TRUE(state
.AddHPKPHeader(domain
, header
, ssl_info
));
873 // HSTS should still be configured for this domain.
874 EXPECT_TRUE(sts_state
.ShouldUpgradeToSSL());
875 EXPECT_TRUE(state
.ShouldUpgradeToSSL(domain
));
876 // The dynamic pins, which do not match |saved_hashes|, should take
877 // precedence over the static pins and cause the check to fail.
878 EXPECT_FALSE(state
.CheckPublicKeyPins(
879 domain_port
, is_issued_by_known_root
, saved_hashes
, nullptr, nullptr,
880 TransportSecurityState::DISABLE_PIN_REPORTS
, &failure_log
));
883 // Tests that seeing an invalid HPKP header leaves the existing one alone.
884 TEST_F(HttpSecurityHeadersTest
, IgnoreInvalidHeaders
) {
885 TransportSecurityState state
;
887 HashValue good_hash
= GetTestHashValue(1, HASH_VALUE_SHA256
);
888 std::string good_pin
= GetTestPin(1, HASH_VALUE_SHA256
);
889 std::string bad_pin
= GetTestPin(2, HASH_VALUE_SHA256
);
890 std::string backup_pin
= GetTestPin(3, HASH_VALUE_SHA256
);
893 ssl_info
.public_key_hashes
.push_back(good_hash
);
895 // Add a valid HPKP header.
896 EXPECT_TRUE(state
.AddHPKPHeader(
897 "example.com", "max-age = 10000; " + good_pin
+ "; " + backup_pin
,
900 // Check the insertion was valid.
901 EXPECT_TRUE(state
.HasPublicKeyPins("example.com"));
902 std::string failure_log
;
903 bool is_issued_by_known_root
= true;
904 HostPortPair
domain_port("example.com", 443);
905 EXPECT_TRUE(state
.CheckPublicKeyPins(
906 domain_port
, is_issued_by_known_root
, ssl_info
.public_key_hashes
, nullptr,
907 nullptr, TransportSecurityState::DISABLE_PIN_REPORTS
, &failure_log
));
909 // Now assert an invalid one. This should fail.
910 EXPECT_FALSE(state
.AddHPKPHeader(
911 "example.com", "max-age = 10000; " + bad_pin
+ "; " + backup_pin
,
914 // The old pins must still exist.
915 EXPECT_TRUE(state
.HasPublicKeyPins("example.com"));
916 EXPECT_TRUE(state
.CheckPublicKeyPins(
917 domain_port
, is_issued_by_known_root
, ssl_info
.public_key_hashes
, nullptr,
918 nullptr, TransportSecurityState::DISABLE_PIN_REPORTS
, &failure_log
));