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.
4
5#include <algorithm>
6
7#include "base/base64.h"
8#include "base/sha1.h"
9#include "base/strings/string_piece.h"
10#include "crypto/sha2.h"
11#include "net/base/net_log.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/ssl/ssl_info.h"
17#include "testing/gtest/include/gtest/gtest.h"
18
19namespace net {
20
21namespace {
22
23HashValue GetTestHashValue(uint8 label, HashValueTag tag) {
24  HashValue hash_value(tag);
25  memset(hash_value.data(), label, hash_value.size());
26  return hash_value;
27}
28
29std::string GetTestPin(uint8 label, HashValueTag tag) {
30  HashValue hash_value = GetTestHashValue(label, tag);
31  std::string base64;
32  base::Base64Encode(base::StringPiece(
33      reinterpret_cast<char*>(hash_value.data()), hash_value.size()), &base64);
34
35  switch (hash_value.tag) {
36    case HASH_VALUE_SHA1:
37      return std::string("pin-sha1=\"") + base64 + "\"";
38    case HASH_VALUE_SHA256:
39      return std::string("pin-sha256=\"") + base64 + "\"";
40    default:
41      NOTREACHED() << "Unknown HashValueTag " << hash_value.tag;
42      return std::string("ERROR");
43  }
44}
45
46};
47
48
49class HttpSecurityHeadersTest : public testing::Test {
50};
51
52
53TEST_F(HttpSecurityHeadersTest, BogusHeaders) {
54  base::TimeDelta max_age;
55  bool include_subdomains = false;
56
57  EXPECT_FALSE(
58      ParseHSTSHeader(std::string(), &max_age, &include_subdomains));
59  EXPECT_FALSE(ParseHSTSHeader("    ", &max_age, &include_subdomains));
60  EXPECT_FALSE(ParseHSTSHeader("abc", &max_age, &include_subdomains));
61  EXPECT_FALSE(ParseHSTSHeader("  abc", &max_age, &include_subdomains));
62  EXPECT_FALSE(ParseHSTSHeader("  abc   ", &max_age, &include_subdomains));
63  EXPECT_FALSE(ParseHSTSHeader("max-age", &max_age, &include_subdomains));
64  EXPECT_FALSE(ParseHSTSHeader("  max-age", &max_age,
65                               &include_subdomains));
66  EXPECT_FALSE(ParseHSTSHeader("  max-age  ", &max_age,
67                               &include_subdomains));
68  EXPECT_FALSE(ParseHSTSHeader("max-age=", &max_age, &include_subdomains));
69  EXPECT_FALSE(ParseHSTSHeader("   max-age=", &max_age,
70                               &include_subdomains));
71  EXPECT_FALSE(ParseHSTSHeader("   max-age  =", &max_age,
72                               &include_subdomains));
73  EXPECT_FALSE(ParseHSTSHeader("   max-age=   ", &max_age,
74                               &include_subdomains));
75  EXPECT_FALSE(ParseHSTSHeader("   max-age  =     ", &max_age,
76                               &include_subdomains));
77  EXPECT_FALSE(ParseHSTSHeader("   max-age  =     xy", &max_age,
78                               &include_subdomains));
79  EXPECT_FALSE(ParseHSTSHeader("   max-age  =     3488a923", &max_age,
80                               &include_subdomains));
81  EXPECT_FALSE(ParseHSTSHeader("max-age=3488a923  ", &max_age,
82                               &include_subdomains));
83  EXPECT_FALSE(ParseHSTSHeader("max-ag=3488923", &max_age,
84                               &include_subdomains));
85  EXPECT_FALSE(ParseHSTSHeader("max-aged=3488923", &max_age,
86                               &include_subdomains));
87  EXPECT_FALSE(ParseHSTSHeader("max-age==3488923", &max_age,
88                               &include_subdomains));
89  EXPECT_FALSE(ParseHSTSHeader("amax-age=3488923", &max_age,
90                               &include_subdomains));
91  EXPECT_FALSE(ParseHSTSHeader("max-age=-3488923", &max_age,
92                               &include_subdomains));
93  EXPECT_FALSE(ParseHSTSHeader("max-age=3488923     e", &max_age,
94                               &include_subdomains));
95  EXPECT_FALSE(ParseHSTSHeader("max-age=3488923     includesubdomain",
96                               &max_age, &include_subdomains));
97  EXPECT_FALSE(ParseHSTSHeader("max-age=3488923includesubdomains",
98                               &max_age, &include_subdomains));
99  EXPECT_FALSE(ParseHSTSHeader("max-age=3488923=includesubdomains",
100                               &max_age, &include_subdomains));
101  EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomainx",
102                               &max_age, &include_subdomains));
103  EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomain=",
104                               &max_age, &include_subdomains));
105  EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomain=true",
106                               &max_age, &include_subdomains));
107  EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomainsx",
108                               &max_age, &include_subdomains));
109  EXPECT_FALSE(ParseHSTSHeader("max-age=3488923 includesubdomains x",
110                               &max_age, &include_subdomains));
111  EXPECT_FALSE(ParseHSTSHeader("max-age=34889.23 includesubdomains",
112                               &max_age, &include_subdomains));
113  EXPECT_FALSE(ParseHSTSHeader("max-age=34889 includesubdomains",
114                               &max_age, &include_subdomains));
115  EXPECT_FALSE(ParseHSTSHeader(";;;; ;;;",
116                               &max_age, &include_subdomains));
117  EXPECT_FALSE(ParseHSTSHeader(";;;; includeSubDomains;;;",
118                               &max_age, &include_subdomains));
119  EXPECT_FALSE(ParseHSTSHeader("   includeSubDomains;  ",
120                               &max_age, &include_subdomains));
121  EXPECT_FALSE(ParseHSTSHeader(";",
122                               &max_age, &include_subdomains));
123  EXPECT_FALSE(ParseHSTSHeader("max-age; ;",
124                               &max_age, &include_subdomains));
125
126  // Check the out args were not updated by checking the default
127  // values for its predictable fields.
128  EXPECT_EQ(0, max_age.InSeconds());
129  EXPECT_FALSE(include_subdomains);
130}
131
132static void TestBogusPinsHeaders(HashValueTag tag) {
133  base::TimeDelta max_age;
134  bool include_subdomains;
135  HashValueVector hashes;
136  HashValueVector chain_hashes;
137
138  // Set some fake "chain" hashes
139  chain_hashes.push_back(GetTestHashValue(1, tag));
140  chain_hashes.push_back(GetTestHashValue(2, tag));
141  chain_hashes.push_back(GetTestHashValue(3, tag));
142
143  // The good pin must be in the chain, the backup pin must not be
144  std::string good_pin = GetTestPin(2, tag);
145  std::string backup_pin = GetTestPin(4, tag);
146
147  EXPECT_FALSE(ParseHPKPHeader(std::string(), chain_hashes, &max_age,
148                               &include_subdomains, &hashes));
149  EXPECT_FALSE(ParseHPKPHeader("    ", chain_hashes, &max_age,
150                               &include_subdomains, &hashes));
151  EXPECT_FALSE(ParseHPKPHeader("abc", chain_hashes, &max_age,
152                               &include_subdomains, &hashes));
153  EXPECT_FALSE(ParseHPKPHeader("  abc", chain_hashes, &max_age,
154                               &include_subdomains, &hashes));
155  EXPECT_FALSE(ParseHPKPHeader("  abc   ", chain_hashes, &max_age,
156                               &include_subdomains, &hashes));
157  EXPECT_FALSE(ParseHPKPHeader("max-age", chain_hashes, &max_age,
158                               &include_subdomains, &hashes));
159  EXPECT_FALSE(ParseHPKPHeader("  max-age", chain_hashes, &max_age,
160                               &include_subdomains, &hashes));
161  EXPECT_FALSE(ParseHPKPHeader("  max-age  ", chain_hashes, &max_age,
162                               &include_subdomains, &hashes));
163  EXPECT_FALSE(ParseHPKPHeader("max-age=", chain_hashes, &max_age,
164                               &include_subdomains, &hashes));
165  EXPECT_FALSE(ParseHPKPHeader("   max-age=", chain_hashes, &max_age,
166                               &include_subdomains, &hashes));
167  EXPECT_FALSE(ParseHPKPHeader("   max-age  =", chain_hashes, &max_age,
168                               &include_subdomains, &hashes));
169  EXPECT_FALSE(ParseHPKPHeader("   max-age=   ", chain_hashes, &max_age,
170                               &include_subdomains, &hashes));
171  EXPECT_FALSE(ParseHPKPHeader("   max-age  =     ", chain_hashes,
172                               &max_age, &include_subdomains, &hashes));
173  EXPECT_FALSE(ParseHPKPHeader("   max-age  =     xy", chain_hashes,
174                               &max_age, &include_subdomains, &hashes));
175  EXPECT_FALSE(ParseHPKPHeader("   max-age  =     3488a923",
176                               chain_hashes, &max_age, &include_subdomains,
177                               &hashes));
178  EXPECT_FALSE(ParseHPKPHeader("max-age=3488a923  ", chain_hashes,
179                               &max_age, &include_subdomains, &hashes));
180  EXPECT_FALSE(ParseHPKPHeader("max-ag=3488923pins=" + good_pin + "," +
181                               backup_pin,
182                               chain_hashes, &max_age, &include_subdomains,
183                               &hashes));
184  EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923" + backup_pin,
185                               chain_hashes, &max_age, &include_subdomains,
186                               &hashes));
187  EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + backup_pin,
188                               chain_hashes, &max_age, &include_subdomains,
189                               &hashes));
190  EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + backup_pin + ";" +
191                               backup_pin,
192                               chain_hashes, &max_age, &include_subdomains,
193                               &hashes));
194  EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + good_pin + ";" +
195                               good_pin,
196                               chain_hashes, &max_age, &include_subdomains,
197                               &hashes));
198  EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + good_pin,
199                               chain_hashes, &max_age, &include_subdomains,
200                               &hashes));
201  EXPECT_FALSE(ParseHPKPHeader("max-age==3488923", chain_hashes, &max_age,
202                               &include_subdomains, &hashes));
203  EXPECT_FALSE(ParseHPKPHeader("amax-age=3488923", chain_hashes, &max_age,
204                               &include_subdomains, &hashes));
205  EXPECT_FALSE(ParseHPKPHeader("max-age=-3488923", chain_hashes, &max_age,
206                               &include_subdomains, &hashes));
207  EXPECT_FALSE(ParseHPKPHeader("max-age=3488923;", chain_hashes, &max_age,
208                               &include_subdomains, &hashes));
209  EXPECT_FALSE(ParseHPKPHeader("max-age=3488923     e", chain_hashes,
210                               &max_age, &include_subdomains, &hashes));
211  EXPECT_FALSE(ParseHPKPHeader("max-age=3488923     includesubdomain",
212                               chain_hashes, &max_age, &include_subdomains,
213                               &hashes));
214  EXPECT_FALSE(ParseHPKPHeader("max-age=34889.23", chain_hashes, &max_age,
215                               &include_subdomains, &hashes));
216
217  // Check the out args were not updated by checking the default
218  // values for its predictable fields.
219  EXPECT_EQ(0, max_age.InSeconds());
220  EXPECT_EQ(hashes.size(), (size_t)0);
221}
222
223TEST_F(HttpSecurityHeadersTest, ValidSTSHeaders) {
224  base::TimeDelta max_age;
225  base::TimeDelta expect_max_age;
226  bool include_subdomains = false;
227
228  EXPECT_TRUE(ParseHSTSHeader("max-age=243", &max_age,
229                              &include_subdomains));
230  expect_max_age = base::TimeDelta::FromSeconds(243);
231  EXPECT_EQ(expect_max_age, max_age);
232  EXPECT_FALSE(include_subdomains);
233
234  EXPECT_TRUE(ParseHSTSHeader("max-age=3488923;", &max_age,
235                              &include_subdomains));
236
237  EXPECT_TRUE(ParseHSTSHeader("  Max-agE    = 567", &max_age,
238                              &include_subdomains));
239  expect_max_age = base::TimeDelta::FromSeconds(567);
240  EXPECT_EQ(expect_max_age, max_age);
241  EXPECT_FALSE(include_subdomains);
242
243  EXPECT_TRUE(ParseHSTSHeader("  mAx-aGe    = 890      ", &max_age,
244                              &include_subdomains));
245  expect_max_age = base::TimeDelta::FromSeconds(890);
246  EXPECT_EQ(expect_max_age, max_age);
247  EXPECT_FALSE(include_subdomains);
248
249  EXPECT_TRUE(ParseHSTSHeader("max-age=123;incLudesUbdOmains", &max_age,
250                              &include_subdomains));
251  expect_max_age = base::TimeDelta::FromSeconds(123);
252  EXPECT_EQ(expect_max_age, max_age);
253  EXPECT_TRUE(include_subdomains);
254
255  EXPECT_TRUE(ParseHSTSHeader("incLudesUbdOmains; max-age=123", &max_age,
256                              &include_subdomains));
257  expect_max_age = base::TimeDelta::FromSeconds(123);
258  EXPECT_EQ(expect_max_age, max_age);
259  EXPECT_TRUE(include_subdomains);
260
261  EXPECT_TRUE(ParseHSTSHeader("   incLudesUbdOmains; max-age=123",
262                              &max_age, &include_subdomains));
263  expect_max_age = base::TimeDelta::FromSeconds(123);
264  EXPECT_EQ(expect_max_age, max_age);
265  EXPECT_TRUE(include_subdomains);
266
267  EXPECT_TRUE(ParseHSTSHeader(
268      "   incLudesUbdOmains; max-age=123; pumpkin=kitten", &max_age,
269                                   &include_subdomains));
270  expect_max_age = base::TimeDelta::FromSeconds(123);
271  EXPECT_EQ(expect_max_age, max_age);
272  EXPECT_TRUE(include_subdomains);
273
274  EXPECT_TRUE(ParseHSTSHeader(
275      "   pumpkin=894; incLudesUbdOmains; max-age=123  ", &max_age,
276                                   &include_subdomains));
277  expect_max_age = base::TimeDelta::FromSeconds(123);
278  EXPECT_EQ(expect_max_age, max_age);
279  EXPECT_TRUE(include_subdomains);
280
281  EXPECT_TRUE(ParseHSTSHeader(
282      "   pumpkin; incLudesUbdOmains; max-age=123  ", &max_age,
283                                   &include_subdomains));
284  expect_max_age = base::TimeDelta::FromSeconds(123);
285  EXPECT_EQ(expect_max_age, max_age);
286  EXPECT_TRUE(include_subdomains);
287
288  EXPECT_TRUE(ParseHSTSHeader(
289      "   pumpkin; incLudesUbdOmains; max-age=\"123\"  ", &max_age,
290                                   &include_subdomains));
291  expect_max_age = base::TimeDelta::FromSeconds(123);
292  EXPECT_EQ(expect_max_age, max_age);
293  EXPECT_TRUE(include_subdomains);
294
295  EXPECT_TRUE(ParseHSTSHeader(
296      "animal=\"squirrel; distinguished\"; incLudesUbdOmains; max-age=123",
297                                   &max_age, &include_subdomains));
298  expect_max_age = base::TimeDelta::FromSeconds(123);
299  EXPECT_EQ(expect_max_age, max_age);
300  EXPECT_TRUE(include_subdomains);
301
302  EXPECT_TRUE(ParseHSTSHeader("max-age=394082;  incLudesUbdOmains",
303                              &max_age, &include_subdomains));
304  expect_max_age = base::TimeDelta::FromSeconds(394082);
305  EXPECT_EQ(expect_max_age, max_age);
306  EXPECT_TRUE(include_subdomains);
307
308  EXPECT_TRUE(ParseHSTSHeader(
309      "max-age=39408299  ;incLudesUbdOmains", &max_age,
310      &include_subdomains));
311  expect_max_age = base::TimeDelta::FromSeconds(
312      std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(39408299))));
313  EXPECT_EQ(expect_max_age, max_age);
314  EXPECT_TRUE(include_subdomains);
315
316  EXPECT_TRUE(ParseHSTSHeader(
317      "max-age=394082038  ; incLudesUbdOmains", &max_age,
318      &include_subdomains));
319  expect_max_age = base::TimeDelta::FromSeconds(
320      std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(394082038))));
321  EXPECT_EQ(expect_max_age, max_age);
322  EXPECT_TRUE(include_subdomains);
323
324  EXPECT_TRUE(ParseHSTSHeader(
325      "max-age=394082038  ; incLudesUbdOmains;", &max_age,
326      &include_subdomains));
327  expect_max_age = base::TimeDelta::FromSeconds(
328      std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(394082038))));
329  EXPECT_EQ(expect_max_age, max_age);
330  EXPECT_TRUE(include_subdomains);
331
332  EXPECT_TRUE(ParseHSTSHeader(
333      ";; max-age=394082038  ; incLudesUbdOmains; ;", &max_age,
334      &include_subdomains));
335  expect_max_age = base::TimeDelta::FromSeconds(
336      std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(394082038))));
337  EXPECT_EQ(expect_max_age, max_age);
338  EXPECT_TRUE(include_subdomains);
339
340  EXPECT_TRUE(ParseHSTSHeader(
341      ";; max-age=394082038  ;", &max_age,
342      &include_subdomains));
343  expect_max_age = base::TimeDelta::FromSeconds(
344      std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(394082038))));
345  EXPECT_EQ(expect_max_age, max_age);
346  EXPECT_FALSE(include_subdomains);
347
348  EXPECT_TRUE(ParseHSTSHeader(
349      ";;    ; ; max-age=394082038;;; includeSubdomains     ;;  ;", &max_age,
350      &include_subdomains));
351  expect_max_age = base::TimeDelta::FromSeconds(
352      std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(394082038))));
353  EXPECT_EQ(expect_max_age, max_age);
354  EXPECT_TRUE(include_subdomains);
355
356  EXPECT_TRUE(ParseHSTSHeader(
357      "incLudesUbdOmains   ; max-age=394082038 ;;", &max_age,
358      &include_subdomains));
359  expect_max_age = base::TimeDelta::FromSeconds(
360      std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(394082038))));
361  EXPECT_EQ(expect_max_age, max_age);
362  EXPECT_TRUE(include_subdomains);
363
364  EXPECT_TRUE(ParseHSTSHeader(
365      "  max-age=0  ;  incLudesUbdOmains   ", &max_age,
366      &include_subdomains));
367  expect_max_age = base::TimeDelta::FromSeconds(0);
368  EXPECT_EQ(expect_max_age, max_age);
369  EXPECT_TRUE(include_subdomains);
370
371  EXPECT_TRUE(ParseHSTSHeader(
372      "  max-age=999999999999999999999999999999999999999999999  ;"
373      "  incLudesUbdOmains   ", &max_age, &include_subdomains));
374  expect_max_age = base::TimeDelta::FromSeconds(
375      kMaxHSTSAgeSecs);
376  EXPECT_EQ(expect_max_age, max_age);
377  EXPECT_TRUE(include_subdomains);
378}
379
380static void TestValidPKPHeaders(HashValueTag tag) {
381  base::TimeDelta max_age;
382  base::TimeDelta expect_max_age;
383  bool include_subdomains;
384  HashValueVector hashes;
385  HashValueVector chain_hashes;
386
387  // Set some fake "chain" hashes into chain_hashes
388  chain_hashes.push_back(GetTestHashValue(1, tag));
389  chain_hashes.push_back(GetTestHashValue(2, tag));
390  chain_hashes.push_back(GetTestHashValue(3, tag));
391
392  // The good pin must be in the chain, the backup pin must not be
393  std::string good_pin = GetTestPin(2, tag);
394  std::string backup_pin = GetTestPin(4, tag);
395
396  EXPECT_TRUE(ParseHPKPHeader(
397      "max-age=243; " + good_pin + ";" + backup_pin,
398      chain_hashes, &max_age, &include_subdomains, &hashes));
399  expect_max_age = base::TimeDelta::FromSeconds(243);
400  EXPECT_EQ(expect_max_age, max_age);
401  EXPECT_FALSE(include_subdomains);
402
403  EXPECT_TRUE(ParseHPKPHeader(
404      "   " + good_pin + "; " + backup_pin + "  ; Max-agE    = 567",
405      chain_hashes, &max_age, &include_subdomains, &hashes));
406  expect_max_age = base::TimeDelta::FromSeconds(567);
407  EXPECT_EQ(expect_max_age, max_age);
408  EXPECT_FALSE(include_subdomains);
409
410  EXPECT_TRUE(ParseHPKPHeader(
411      "includeSubDOMAINS;" + good_pin + ";" + backup_pin +
412      "  ; mAx-aGe    = 890      ",
413      chain_hashes, &max_age, &include_subdomains, &hashes));
414  expect_max_age = base::TimeDelta::FromSeconds(890);
415  EXPECT_EQ(expect_max_age, max_age);
416  EXPECT_TRUE(include_subdomains);
417
418  EXPECT_TRUE(ParseHPKPHeader(
419      good_pin + ";" + backup_pin + "; max-age=123;IGNORED;",
420      chain_hashes, &max_age, &include_subdomains, &hashes));
421  expect_max_age = base::TimeDelta::FromSeconds(123);
422  EXPECT_EQ(expect_max_age, max_age);
423  EXPECT_FALSE(include_subdomains);
424
425  EXPECT_TRUE(ParseHPKPHeader(
426      "max-age=394082;" + backup_pin + ";" + good_pin + ";  ",
427      chain_hashes, &max_age, &include_subdomains, &hashes));
428  expect_max_age = base::TimeDelta::FromSeconds(394082);
429  EXPECT_EQ(expect_max_age, max_age);
430  EXPECT_FALSE(include_subdomains);
431
432  EXPECT_TRUE(ParseHPKPHeader(
433      "max-age=39408299  ;" + backup_pin + ";" + good_pin + ";  ",
434      chain_hashes, &max_age, &include_subdomains, &hashes));
435  expect_max_age = base::TimeDelta::FromSeconds(
436      std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(39408299))));
437  EXPECT_EQ(expect_max_age, max_age);
438  EXPECT_FALSE(include_subdomains);
439
440  EXPECT_TRUE(ParseHPKPHeader(
441      "max-age=39408038  ;    cybers=39408038  ;  includeSubdomains; " +
442          good_pin + ";" + backup_pin + ";   ",
443      chain_hashes, &max_age, &include_subdomains, &hashes));
444  expect_max_age = base::TimeDelta::FromSeconds(
445      std::min(kMaxHSTSAgeSecs, static_cast<int64>(GG_INT64_C(394082038))));
446  EXPECT_EQ(expect_max_age, max_age);
447  EXPECT_TRUE(include_subdomains);
448
449  EXPECT_TRUE(ParseHPKPHeader(
450      "  max-age=0  ;  " + good_pin + ";" + backup_pin,
451      chain_hashes, &max_age, &include_subdomains, &hashes));
452  expect_max_age = base::TimeDelta::FromSeconds(0);
453  EXPECT_EQ(expect_max_age, max_age);
454  EXPECT_FALSE(include_subdomains);
455
456  EXPECT_TRUE(ParseHPKPHeader(
457      "  max-age=0 ; includeSubdomains;  " + good_pin + ";" + backup_pin,
458      chain_hashes, &max_age, &include_subdomains, &hashes));
459  expect_max_age = base::TimeDelta::FromSeconds(0);
460  EXPECT_EQ(expect_max_age, max_age);
461  EXPECT_TRUE(include_subdomains);
462
463  EXPECT_TRUE(ParseHPKPHeader(
464      "  max-age=999999999999999999999999999999999999999999999  ;  " +
465          backup_pin + ";" + good_pin + ";   ",
466      chain_hashes, &max_age, &include_subdomains, &hashes));
467  expect_max_age = base::TimeDelta::FromSeconds(kMaxHSTSAgeSecs);
468  EXPECT_EQ(expect_max_age, max_age);
469  EXPECT_FALSE(include_subdomains);
470
471  // Test that parsing the same header twice doesn't duplicate the recorded
472  // hashes.
473  hashes.clear();
474  EXPECT_TRUE(ParseHPKPHeader(
475      "  max-age=999;  " +
476          backup_pin + ";" + good_pin + ";   ",
477      chain_hashes, &max_age, &include_subdomains, &hashes));
478  EXPECT_EQ(2u, hashes.size());
479  EXPECT_TRUE(ParseHPKPHeader(
480      "  max-age=999;  " +
481          backup_pin + ";" + good_pin + ";   ",
482      chain_hashes, &max_age, &include_subdomains, &hashes));
483  EXPECT_EQ(2u, hashes.size());
484}
485
486TEST_F(HttpSecurityHeadersTest, BogusPinsHeadersSHA1) {
487  TestBogusPinsHeaders(HASH_VALUE_SHA1);
488}
489
490TEST_F(HttpSecurityHeadersTest, BogusPinsHeadersSHA256) {
491  TestBogusPinsHeaders(HASH_VALUE_SHA256);
492}
493
494TEST_F(HttpSecurityHeadersTest, ValidPKPHeadersSHA1) {
495  TestValidPKPHeaders(HASH_VALUE_SHA1);
496}
497
498TEST_F(HttpSecurityHeadersTest, ValidPKPHeadersSHA256) {
499  TestValidPKPHeaders(HASH_VALUE_SHA256);
500}
501
502TEST_F(HttpSecurityHeadersTest, UpdateDynamicPKPOnly) {
503  TransportSecurityState state;
504  TransportSecurityState::DomainState static_domain_state;
505
506  // docs.google.com has preloaded pins.
507  std::string domain = "docs.google.com";
508  state.enable_static_pins_ = true;
509  EXPECT_TRUE(
510      state.GetStaticDomainState(domain, &static_domain_state));
511  EXPECT_GT(static_domain_state.pkp.spki_hashes.size(), 1UL);
512  HashValueVector saved_hashes = static_domain_state.pkp.spki_hashes;
513
514  // Add a header, which should only update the dynamic state.
515  HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1);
516  HashValue backup_hash = GetTestHashValue(2, HASH_VALUE_SHA1);
517  std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1);
518  std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1);
519  std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin;
520
521  // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
522  SSLInfo ssl_info;
523  ssl_info.public_key_hashes.push_back(good_hash);
524  ssl_info.public_key_hashes.push_back(saved_hashes[0]);
525  EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
526
527  // Expect the static state to remain unchanged.
528  TransportSecurityState::DomainState new_static_domain_state;
529  EXPECT_TRUE(state.GetStaticDomainState(
530      domain, &new_static_domain_state));
531  for (size_t i = 0; i < saved_hashes.size(); ++i) {
532    EXPECT_TRUE(HashValuesEqual(saved_hashes[i])(
533        new_static_domain_state.pkp.spki_hashes[i]));
534  }
535
536  // Expect the dynamic state to reflect the header.
537  TransportSecurityState::DomainState dynamic_domain_state;
538  EXPECT_TRUE(state.GetDynamicDomainState(domain, &dynamic_domain_state));
539  EXPECT_EQ(2UL, dynamic_domain_state.pkp.spki_hashes.size());
540
541  HashValueVector::const_iterator hash =
542      std::find_if(dynamic_domain_state.pkp.spki_hashes.begin(),
543                   dynamic_domain_state.pkp.spki_hashes.end(),
544                   HashValuesEqual(good_hash));
545  EXPECT_NE(dynamic_domain_state.pkp.spki_hashes.end(), hash);
546
547  hash = std::find_if(dynamic_domain_state.pkp.spki_hashes.begin(),
548                      dynamic_domain_state.pkp.spki_hashes.end(),
549                      HashValuesEqual(backup_hash));
550  EXPECT_NE(dynamic_domain_state.pkp.spki_hashes.end(), hash);
551
552  // Expect the overall state to reflect the header, too.
553  EXPECT_TRUE(state.HasPublicKeyPins(domain));
554  HashValueVector hashes;
555  hashes.push_back(good_hash);
556  std::string failure_log;
557  const bool is_issued_by_known_root = true;
558  EXPECT_TRUE(state.CheckPublicKeyPins(
559      domain, is_issued_by_known_root, hashes, &failure_log));
560
561  TransportSecurityState::DomainState new_dynamic_domain_state;
562  EXPECT_TRUE(state.GetDynamicDomainState(domain, &new_dynamic_domain_state));
563  EXPECT_EQ(2UL, new_dynamic_domain_state.pkp.spki_hashes.size());
564
565  hash = std::find_if(new_dynamic_domain_state.pkp.spki_hashes.begin(),
566                      new_dynamic_domain_state.pkp.spki_hashes.end(),
567                      HashValuesEqual(good_hash));
568  EXPECT_NE(new_dynamic_domain_state.pkp.spki_hashes.end(), hash);
569
570  hash = std::find_if(new_dynamic_domain_state.pkp.spki_hashes.begin(),
571                      new_dynamic_domain_state.pkp.spki_hashes.end(),
572                      HashValuesEqual(backup_hash));
573  EXPECT_NE(new_dynamic_domain_state.pkp.spki_hashes.end(), hash);
574}
575
576// Failing on win_chromium_rel. crbug.com/375538
577#if defined(OS_WIN)
578#define MAYBE_UpdateDynamicPKPMaxAge0 DISABLED_UpdateDynamicPKPMaxAge0
579#else
580#define MAYBE_UpdateDynamicPKPMaxAge0 UpdateDynamicPKPMaxAge0
581#endif
582TEST_F(HttpSecurityHeadersTest, MAYBE_UpdateDynamicPKPMaxAge0) {
583  TransportSecurityState state;
584  TransportSecurityState::DomainState static_domain_state;
585
586  // docs.google.com has preloaded pins.
587  std::string domain = "docs.google.com";
588  state.enable_static_pins_ = true;
589  ASSERT_TRUE(
590      state.GetStaticDomainState(domain, &static_domain_state));
591  EXPECT_GT(static_domain_state.pkp.spki_hashes.size(), 1UL);
592  HashValueVector saved_hashes = static_domain_state.pkp.spki_hashes;
593
594  // Add a header, which should only update the dynamic state.
595  HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1);
596  std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1);
597  std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1);
598  std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin;
599
600  // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
601  SSLInfo ssl_info;
602  ssl_info.public_key_hashes.push_back(good_hash);
603  ssl_info.public_key_hashes.push_back(saved_hashes[0]);
604  EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
605
606  // Expect the static state to remain unchanged.
607  TransportSecurityState::DomainState new_static_domain_state;
608  EXPECT_TRUE(state.GetStaticDomainState(
609      domain, &new_static_domain_state));
610  EXPECT_EQ(saved_hashes.size(),
611            new_static_domain_state.pkp.spki_hashes.size());
612  for (size_t i = 0; i < saved_hashes.size(); ++i) {
613    EXPECT_TRUE(HashValuesEqual(saved_hashes[i])(
614        new_static_domain_state.pkp.spki_hashes[i]));
615  }
616
617  // Expect the dynamic state to have pins.
618  TransportSecurityState::DomainState new_dynamic_domain_state;
619  EXPECT_TRUE(state.GetDynamicDomainState(domain, &new_dynamic_domain_state));
620  EXPECT_EQ(2UL, new_dynamic_domain_state.pkp.spki_hashes.size());
621  EXPECT_TRUE(new_dynamic_domain_state.HasPublicKeyPins());
622
623  // Now set another header with max-age=0, and check that the pins are
624  // cleared in the dynamic state only.
625  header = "max-age = 0; " + good_pin + "; " + backup_pin;
626  EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
627
628  // Expect the static state to remain unchanged.
629  TransportSecurityState::DomainState new_static_domain_state2;
630  EXPECT_TRUE(state.GetStaticDomainState(
631      domain, &new_static_domain_state2));
632  EXPECT_EQ(saved_hashes.size(),
633            new_static_domain_state2.pkp.spki_hashes.size());
634  for (size_t i = 0; i < saved_hashes.size(); ++i) {
635    EXPECT_TRUE(HashValuesEqual(saved_hashes[i])(
636        new_static_domain_state2.pkp.spki_hashes[i]));
637  }
638
639  // Expect the dynamic pins to be gone.
640  TransportSecurityState::DomainState new_dynamic_domain_state2;
641  EXPECT_FALSE(state.GetDynamicDomainState(domain, &new_dynamic_domain_state2));
642
643  // Expect the exact-matching static policy to continue to apply, even
644  // though dynamic policy has been removed. (This policy may change in the
645  // future, in which case this test must be updated.)
646  EXPECT_TRUE(state.HasPublicKeyPins(domain));
647  EXPECT_TRUE(state.ShouldSSLErrorsBeFatal(domain));
648  std::string failure_log;
649  // Damage the hashes to cause a pin validation failure.
650  new_static_domain_state2.pkp.spki_hashes[0].data()[0] ^= 0x80;
651  new_static_domain_state2.pkp.spki_hashes[1].data()[0] ^= 0x80;
652  const bool is_issued_by_known_root = true;
653  EXPECT_FALSE(
654      state.CheckPublicKeyPins(domain,
655                               is_issued_by_known_root,
656                               new_static_domain_state2.pkp.spki_hashes,
657                               &failure_log));
658  EXPECT_NE(0UL, failure_log.length());
659}
660#undef MAYBE_UpdateDynamicPKPMaxAge0
661
662// Tests that when a static HSTS and a static HPKP entry are present, adding a
663// dynamic HSTS header does not clobber the static HPKP entry. Further, adding a
664// dynamic HPKP entry could not affect the HSTS entry for the site.
665TEST_F(HttpSecurityHeadersTest, NoClobberPins) {
666  TransportSecurityState state;
667  TransportSecurityState::DomainState domain_state;
668
669  // accounts.google.com has preloaded pins.
670  std::string domain = "accounts.google.com";
671  state.enable_static_pins_ = true;
672
673  // Retrieve the DomainState as it is by default, including its known good
674  // pins.
675  EXPECT_TRUE(state.GetStaticDomainState(domain, &domain_state));
676  HashValueVector saved_hashes = domain_state.pkp.spki_hashes;
677  EXPECT_TRUE(domain_state.ShouldUpgradeToSSL());
678  EXPECT_TRUE(domain_state.HasPublicKeyPins());
679  EXPECT_TRUE(state.ShouldUpgradeToSSL(domain));
680  EXPECT_TRUE(state.HasPublicKeyPins(domain));
681
682  // Add a dynamic HSTS header. CheckPublicKeyPins should still pass when given
683  // the original |saved_hashes|, indicating that the static PKP data is still
684  // configured for the domain.
685  EXPECT_TRUE(state.AddHSTSHeader(domain, "includesubdomains; max-age=10000"));
686  EXPECT_TRUE(state.ShouldUpgradeToSSL(domain));
687  std::string failure_log;
688  const bool is_issued_by_known_root = true;
689  EXPECT_TRUE(state.CheckPublicKeyPins(domain,
690                                       is_issued_by_known_root,
691                                       saved_hashes,
692                                       &failure_log));
693
694  // Add an HPKP header, which should only update the dynamic state.
695  HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1);
696  std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1);
697  std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1);
698  std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin;
699
700  // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
701  SSLInfo ssl_info;
702  ssl_info.public_key_hashes.push_back(good_hash);
703  ssl_info.public_key_hashes.push_back(saved_hashes[0]);
704  EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
705
706  EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
707  // HSTS should still be configured for this domain.
708  EXPECT_TRUE(domain_state.ShouldUpgradeToSSL());
709  EXPECT_TRUE(state.ShouldUpgradeToSSL(domain));
710  // The dynamic pins, which do not match |saved_hashes|, should take
711  // precedence over the static pins and cause the check to fail.
712  EXPECT_FALSE(state.CheckPublicKeyPins(domain,
713                                        is_issued_by_known_root,
714                                        saved_hashes,
715                                        &failure_log));
716}
717
718};    // namespace net
719