Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Side by Side Diff: net/base/transport_security_state.cc

Issue 11274032: Separate http_security_headers from transport_security_state (Closed) Base URL: https://src.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/base/transport_security_state.h ('k') | net/base/transport_security_state_static.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/transport_security_state.h" 5 #include "net/base/transport_security_state.h"
6 6
7 #if defined(USE_OPENSSL) 7 #if defined(USE_OPENSSL)
8 #include <openssl/ecdsa.h> 8 #include <openssl/ecdsa.h>
9 #include <openssl/ssl.h> 9 #include <openssl/ssl.h>
10 #else // !defined(USE_OPENSSL) 10 #else // !defined(USE_OPENSSL)
11 #include <cryptohi.h> 11 #include <cryptohi.h>
12 #include <hasht.h> 12 #include <hasht.h>
13 #include <keyhi.h> 13 #include <keyhi.h>
14 #include <pk11pub.h> 14 #include <pk11pub.h>
15 #include <nspr.h> 15 #include <nspr.h>
16 #endif 16 #endif
17 17
18 #include <algorithm> 18 #include <algorithm>
19 19
20 #include "base/base64.h" 20 #include "base/base64.h"
21 #include "base/build_time.h" 21 #include "base/build_time.h"
22 #include "base/logging.h" 22 #include "base/logging.h"
23 #include "base/memory/scoped_ptr.h" 23 #include "base/memory/scoped_ptr.h"
24 #include "base/metrics/histogram.h" 24 #include "base/metrics/histogram.h"
25 #include "base/sha1.h" 25 #include "base/sha1.h"
26 #include "base/string_number_conversions.h" 26 #include "base/string_number_conversions.h"
27 #include "base/string_tokenizer.h"
28 #include "base/string_util.h" 27 #include "base/string_util.h"
29 #include "base/time.h" 28 #include "base/time.h"
30 #include "base/utf_string_conversions.h" 29 #include "base/utf_string_conversions.h"
31 #include "base/values.h" 30 #include "base/values.h"
32 #include "crypto/sha2.h" 31 #include "crypto/sha2.h"
33 #include "googleurl/src/gurl.h" 32 #include "googleurl/src/gurl.h"
34 #include "net/base/dns_util.h" 33 #include "net/base/dns_util.h"
35 #include "net/base/ssl_info.h" 34 #include "net/base/ssl_info.h"
36 #include "net/base/x509_cert_types.h" 35 #include "net/base/x509_cert_types.h"
37 #include "net/base/x509_certificate.h" 36 #include "net/base/x509_certificate.h"
38 #include "net/http/http_util.h" 37 #include "net/http/http_security_headers.h"
39 38
40 #if defined(USE_OPENSSL) 39 #if defined(USE_OPENSSL)
41 #include "crypto/openssl_util.h" 40 #include "crypto/openssl_util.h"
42 #endif 41 #endif
43 42
44 namespace net { 43 namespace net {
45 44
46 const long int TransportSecurityState::kMaxHSTSAgeSecs = 86400 * 365; // 1 year 45 namespace {
47 46
48 static std::string HashHost(const std::string& canonicalized_host) { 47 std::string HashesToBase64String(const HashValueVector& hashes) {
48 std::string str;
49 for (size_t i = 0; i != hashes.size(); ++i) {
50 if (i != 0)
51 str += ",";
52 str += hashes[i].ToString();
53 }
54 return str;
55 }
56
57 std::string HashHost(const std::string& canonicalized_host) {
49 char hashed[crypto::kSHA256Length]; 58 char hashed[crypto::kSHA256Length];
50 crypto::SHA256HashString(canonicalized_host, hashed, sizeof(hashed)); 59 crypto::SHA256HashString(canonicalized_host, hashed, sizeof(hashed));
51 return std::string(hashed, sizeof(hashed)); 60 return std::string(hashed, sizeof(hashed));
52 } 61 }
53 62
63 // Returns true if the intersection of |a| and |b| is not empty. If either
64 // |a| or |b| is empty, returns false.
65 bool HashesIntersect(const HashValueVector& a,
66 const HashValueVector& b) {
67 for (HashValueVector::const_iterator i = a.begin(); i != a.end(); ++i) {
68 HashValueVector::const_iterator j =
69 std::find_if(b.begin(), b.end(), HashValuesEqual(*i));
70 if (j != b.end())
71 return true;
72 }
73 return false;
74 }
75
76 bool AddHash(const char* sha1_hash,
77 HashValueVector* out) {
78 HashValue hash(HASH_VALUE_SHA1);
79 memcpy(hash.data(), sha1_hash, hash.size());
80 out->push_back(hash);
81 return true;
82 }
83
84 } // namespace
85
54 TransportSecurityState::TransportSecurityState() 86 TransportSecurityState::TransportSecurityState()
55 : delegate_(NULL) { 87 : delegate_(NULL) {
56 } 88 }
57 89
58 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state) 90 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state)
59 : iterator_(state.enabled_hosts_.begin()), 91 : iterator_(state.enabled_hosts_.begin()),
60 end_(state.enabled_hosts_.end()) { 92 end_(state.enabled_hosts_.end()) {
61 } 93 }
62 94
63 TransportSecurityState::Iterator::~Iterator() {} 95 TransportSecurityState::Iterator::~Iterator() {}
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 enabled_hosts_.erase(i++); 208 enabled_hosts_.erase(i++);
177 } else { 209 } else {
178 i++; 210 i++;
179 } 211 }
180 } 212 }
181 213
182 if (dirtied) 214 if (dirtied)
183 DirtyNotify(); 215 DirtyNotify();
184 } 216 }
185 217
186 // MaxAgeToInt converts a string representation of a number of seconds into a
187 // int. We use strtol in order to handle overflow correctly. The string may
188 // contain an arbitary number which we should truncate correctly rather than
189 // throwing a parse failure.
190 static bool MaxAgeToInt(std::string::const_iterator begin,
191 std::string::const_iterator end,
192 int* result) {
193 const std::string s(begin, end);
194 char* endptr;
195 long int i = strtol(s.data(), &endptr, 10 /* base */);
196 if (*endptr || i < 0)
197 return false;
198 if (i > TransportSecurityState::kMaxHSTSAgeSecs)
199 i = TransportSecurityState::kMaxHSTSAgeSecs;
200 *result = i;
201 return true;
202 }
203
204 // Strip, Split, StringPair, and ParsePins are private implementation details
205 // of ParsePinsHeader(std::string&, DomainState&).
206 static std::string Strip(const std::string& source) {
207 if (source.empty())
208 return source;
209
210 std::string::const_iterator start = source.begin();
211 std::string::const_iterator end = source.end();
212 HttpUtil::TrimLWS(&start, &end);
213 return std::string(start, end);
214 }
215
216 typedef std::pair<std::string, std::string> StringPair;
217
218 static StringPair Split(const std::string& source, char delimiter) {
219 StringPair pair;
220 size_t point = source.find(delimiter);
221
222 pair.first = source.substr(0, point);
223 if (std::string::npos != point)
224 pair.second = source.substr(point + 1);
225
226 return pair;
227 }
228
229 // static
230 bool TransportSecurityState::ParsePin(const std::string& value,
231 HashValue* out) {
232 StringPair slash = Split(Strip(value), '/');
233
234 if (slash.first == "sha1")
235 out->tag = HASH_VALUE_SHA1;
236 else if (slash.first == "sha256")
237 out->tag = HASH_VALUE_SHA256;
238 else
239 return false;
240
241 std::string decoded;
242 if (!base::Base64Decode(slash.second, &decoded) ||
243 decoded.size() != out->size()) {
244 return false;
245 }
246
247 memcpy(out->data(), decoded.data(), out->size());
248 return true;
249 }
250
251 static bool ParseAndAppendPin(const std::string& value,
252 HashValueTag tag,
253 HashValueVector* hashes) {
254 std::string unquoted = HttpUtil::Unquote(value);
255 std::string decoded;
256
257 // This code has to assume that 32 bytes is SHA-256 and 20 bytes is SHA-1.
258 // Currently, those are the only two possibilities, so the assumption is
259 // valid.
260 if (!base::Base64Decode(unquoted, &decoded))
261 return false;
262
263 HashValue hash(tag);
264 if (decoded.size() != hash.size())
265 return false;
266
267 memcpy(hash.data(), decoded.data(), hash.size());
268 hashes->push_back(hash);
269 return true;
270 }
271
272 struct HashValuesEqualPredicate {
273 explicit HashValuesEqualPredicate(const HashValue& fingerprint) :
274 fingerprint_(fingerprint) {}
275
276 bool operator()(const HashValue& other) const {
277 return fingerprint_.Equals(other);
278 }
279
280 const HashValue& fingerprint_;
281 };
282
283 // Returns true iff there is an item in |pins| which is not present in
284 // |from_cert_chain|. Such an SPKI hash is called a "backup pin".
285 static bool IsBackupPinPresent(const HashValueVector& pins,
286 const HashValueVector& from_cert_chain) {
287 for (HashValueVector::const_iterator
288 i = pins.begin(); i != pins.end(); ++i) {
289 HashValueVector::const_iterator j =
290 std::find_if(from_cert_chain.begin(), from_cert_chain.end(),
291 HashValuesEqualPredicate(*i));
292 if (j == from_cert_chain.end())
293 return true;
294 }
295
296 return false;
297 }
298
299 // Returns true if the intersection of |a| and |b| is not empty. If either
300 // |a| or |b| is empty, returns false.
301 static bool HashesIntersect(const HashValueVector& a,
302 const HashValueVector& b) {
303 for (HashValueVector::const_iterator i = a.begin(); i != a.end(); ++i) {
304 HashValueVector::const_iterator j =
305 std::find_if(b.begin(), b.end(), HashValuesEqualPredicate(*i));
306 if (j != b.end())
307 return true;
308 }
309
310 return false;
311 }
312
313 // Returns true iff |pins| contains both a live and a backup pin. A live pin
314 // is a pin whose SPKI is present in the certificate chain in |ssl_info|. A
315 // backup pin is a pin intended for disaster recovery, not day-to-day use, and
316 // thus must be absent from the certificate chain. The Public-Key-Pins header
317 // specification requires both.
318 static bool IsPinListValid(const HashValueVector& pins,
319 const SSLInfo& ssl_info) {
320 // Fast fail: 1 live + 1 backup = at least 2 pins. (Check for actual
321 // liveness and backupness below.)
322 if (pins.size() < 2)
323 return false;
324
325 const HashValueVector& from_cert_chain = ssl_info.public_key_hashes;
326 if (from_cert_chain.empty())
327 return false;
328
329 return IsBackupPinPresent(pins, from_cert_chain) &&
330 HashesIntersect(pins, from_cert_chain);
331 }
332
333 // "Public-Key-Pins" ":"
334 // "max-age" "=" delta-seconds ";"
335 // "pin-" algo "=" base64 [ ";" ... ]
336 bool TransportSecurityState::DomainState::ParsePinsHeader(
337 const base::Time& now,
338 const std::string& value,
339 const SSLInfo& ssl_info) {
340 bool parsed_max_age = false;
341 int max_age_candidate = 0;
342 HashValueVector pins;
343
344 std::string source = value;
345
346 while (!source.empty()) {
347 StringPair semicolon = Split(source, ';');
348 semicolon.first = Strip(semicolon.first);
349 semicolon.second = Strip(semicolon.second);
350 StringPair equals = Split(semicolon.first, '=');
351 equals.first = Strip(equals.first);
352 equals.second = Strip(equals.second);
353
354 if (LowerCaseEqualsASCII(equals.first, "max-age")) {
355 if (equals.second.empty() ||
356 !MaxAgeToInt(equals.second.begin(), equals.second.end(),
357 &max_age_candidate)) {
358 return false;
359 }
360 if (max_age_candidate > kMaxHSTSAgeSecs)
361 max_age_candidate = kMaxHSTSAgeSecs;
362 parsed_max_age = true;
363 } else if (StartsWithASCII(equals.first, "pin-", false)) {
364 HashValueTag tag;
365 if (LowerCaseEqualsASCII(equals.first, "pin-sha1")) {
366 tag = HASH_VALUE_SHA1;
367 } else if (LowerCaseEqualsASCII(equals.first, "pin-sha256")) {
368 tag = HASH_VALUE_SHA256;
369 } else {
370 LOG(WARNING) << "Ignoring pin of unknown type: " << equals.first;
371 return false;
372 }
373 if (!ParseAndAppendPin(equals.second, tag, &pins))
374 return false;
375 } else {
376 // Silently ignore unknown directives for forward compatibility.
377 }
378
379 source = semicolon.second;
380 }
381
382 if (!parsed_max_age || !IsPinListValid(pins, ssl_info))
383 return false;
384
385 dynamic_spki_hashes_expiry =
386 now + base::TimeDelta::FromSeconds(max_age_candidate);
387
388 dynamic_spki_hashes.clear();
389 if (max_age_candidate > 0) {
390 for (HashValueVector::const_iterator i = pins.begin();
391 i != pins.end(); ++i) {
392 dynamic_spki_hashes.push_back(*i);
393 }
394 }
395
396 return true;
397 }
398
399 // Parse the Strict-Transport-Security header, as currently defined in
400 // http://tools.ietf.org/html/draft-ietf-websec-strict-transport-sec-14:
401 //
402 // Strict-Transport-Security = "Strict-Transport-Security" ":"
403 // [ directive ] *( ";" [ directive ] )
404 //
405 // directive = directive-name [ "=" directive-value ]
406 // directive-name = token
407 // directive-value = token | quoted-string
408 //
409 // 1. The order of appearance of directives is not significant.
410 //
411 // 2. All directives MUST appear only once in an STS header field.
412 // Directives are either optional or required, as stipulated in
413 // their definitions.
414 //
415 // 3. Directive names are case-insensitive.
416 //
417 // 4. UAs MUST ignore any STS header fields containing directives, or
418 // other header field value data, that does not conform to the
419 // syntax defined in this specification.
420 //
421 // 5. If an STS header field contains directive(s) not recognized by
422 // the UA, the UA MUST ignore the unrecognized directives and if the
423 // STS header field otherwise satisfies the above requirements (1
424 // through 4), the UA MUST process the recognized directives.
425 bool TransportSecurityState::DomainState::ParseSTSHeader(
426 const base::Time& now,
427 const std::string& value) {
428 int max_age_candidate = 0;
429 bool include_subdomains_candidate = false;
430
431 // We must see max-age exactly once.
432 int max_age_observed = 0;
433 // We must see includeSubdomains exactly 0 or 1 times.
434 int include_subdomains_observed = 0;
435
436 enum ParserState {
437 START,
438 AFTER_MAX_AGE_LABEL,
439 AFTER_MAX_AGE_EQUALS,
440 AFTER_MAX_AGE,
441 AFTER_INCLUDE_SUBDOMAINS,
442 AFTER_UNKNOWN_LABEL,
443 DIRECTIVE_END
444 } state = START;
445
446 StringTokenizer tokenizer(value, " \t=;");
447 tokenizer.set_options(StringTokenizer::RETURN_DELIMS);
448 tokenizer.set_quote_chars("\"");
449 std::string unquoted;
450 while (tokenizer.GetNext()) {
451 DCHECK(!tokenizer.token_is_delim() || tokenizer.token().length() == 1);
452 switch (state) {
453 case START:
454 case DIRECTIVE_END:
455 if (IsAsciiWhitespace(*tokenizer.token_begin()))
456 continue;
457 if (LowerCaseEqualsASCII(tokenizer.token(), "max-age")) {
458 state = AFTER_MAX_AGE_LABEL;
459 max_age_observed++;
460 } else if (LowerCaseEqualsASCII(tokenizer.token(),
461 "includesubdomains")) {
462 state = AFTER_INCLUDE_SUBDOMAINS;
463 include_subdomains_observed++;
464 include_subdomains_candidate = true;
465 } else {
466 state = AFTER_UNKNOWN_LABEL;
467 }
468 break;
469
470 case AFTER_MAX_AGE_LABEL:
471 if (IsAsciiWhitespace(*tokenizer.token_begin()))
472 continue;
473 if (*tokenizer.token_begin() != '=')
474 return false;
475 DCHECK_EQ(tokenizer.token().length(), 1U);
476 state = AFTER_MAX_AGE_EQUALS;
477 break;
478
479 case AFTER_MAX_AGE_EQUALS:
480 if (IsAsciiWhitespace(*tokenizer.token_begin()))
481 continue;
482 unquoted = HttpUtil::Unquote(tokenizer.token());
483 if (!MaxAgeToInt(unquoted.begin(),
484 unquoted.end(),
485 &max_age_candidate))
486 return false;
487 state = AFTER_MAX_AGE;
488 break;
489
490 case AFTER_MAX_AGE:
491 case AFTER_INCLUDE_SUBDOMAINS:
492 if (IsAsciiWhitespace(*tokenizer.token_begin()))
493 continue;
494 else if (*tokenizer.token_begin() == ';')
495 state = DIRECTIVE_END;
496 else
497 return false;
498 break;
499
500 case AFTER_UNKNOWN_LABEL:
501 // Consume and ignore the post-label contents (if any).
502 if (*tokenizer.token_begin() != ';')
503 continue;
504 state = DIRECTIVE_END;
505 break;
506 }
507 }
508
509 // We've consumed all the input. Let's see what state we ended up in.
510 if (max_age_observed != 1 ||
511 (include_subdomains_observed != 0 && include_subdomains_observed != 1)) {
512 return false;
513 }
514
515 switch (state) {
516 case AFTER_MAX_AGE:
517 case AFTER_INCLUDE_SUBDOMAINS:
518 case AFTER_UNKNOWN_LABEL:
519 if (max_age_candidate > 0) {
520 upgrade_expiry = now + base::TimeDelta::FromSeconds(max_age_candidate);
521 upgrade_mode = MODE_FORCE_HTTPS;
522 } else {
523 upgrade_expiry = now;
524 upgrade_mode = MODE_DEFAULT;
525 }
526 include_subdomains = include_subdomains_candidate;
527 return true;
528 case START:
529 case DIRECTIVE_END:
530 case AFTER_MAX_AGE_LABEL:
531 case AFTER_MAX_AGE_EQUALS:
532 return false;
533 default:
534 NOTREACHED();
535 return false;
536 }
537 }
538
539 static bool AddHash(const std::string& type_and_base64,
540 HashValueVector* out) {
541 HashValue hash;
542
543 if (!TransportSecurityState::ParsePin(type_and_base64, &hash))
544 return false;
545
546 out->push_back(hash);
547 return true;
548 }
549
550 TransportSecurityState::~TransportSecurityState() {} 218 TransportSecurityState::~TransportSecurityState() {}
551 219
552 void TransportSecurityState::DirtyNotify() { 220 void TransportSecurityState::DirtyNotify() {
553 DCHECK(CalledOnValidThread()); 221 DCHECK(CalledOnValidThread());
554 222
555 if (delegate_) 223 if (delegate_)
556 delegate_->StateIsDirty(this); 224 delegate_->StateIsDirty(this);
557 } 225 }
558 226
559 // static 227 // static
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 memcmp(entries[j].dns_name, &canonicalized_host[i], 551 memcmp(entries[j].dns_name, &canonicalized_host[i],
884 entries[j].length) == 0) { 552 entries[j].length) == 0) {
885 if (!entries[j].include_subdomains && i != 0) { 553 if (!entries[j].include_subdomains && i != 0) {
886 *ret = false; 554 *ret = false;
887 } else { 555 } else {
888 out->include_subdomains = entries[j].include_subdomains; 556 out->include_subdomains = entries[j].include_subdomains;
889 *ret = true; 557 *ret = true;
890 if (!entries[j].https_required) 558 if (!entries[j].https_required)
891 out->upgrade_mode = TransportSecurityState::DomainState::MODE_DEFAULT; 559 out->upgrade_mode = TransportSecurityState::DomainState::MODE_DEFAULT;
892 if (entries[j].pins.required_hashes) { 560 if (entries[j].pins.required_hashes) {
893 const char* const* hash = entries[j].pins.required_hashes; 561 const char* const* sha1_hash = entries[j].pins.required_hashes;
894 while (*hash) { 562 while (*sha1_hash) {
895 bool ok = AddHash(*hash, &out->static_spki_hashes); 563 AddHash(*sha1_hash, &out->static_spki_hashes);
896 DCHECK(ok) << " failed to parse " << *hash; 564 sha1_hash++;
897 hash++;
898 } 565 }
899 } 566 }
900 if (entries[j].pins.excluded_hashes) { 567 if (entries[j].pins.excluded_hashes) {
901 const char* const* hash = entries[j].pins.excluded_hashes; 568 const char* const* sha1_hash = entries[j].pins.excluded_hashes;
902 while (*hash) { 569 while (*sha1_hash) {
903 bool ok = AddHash(*hash, &out->bad_static_spki_hashes); 570 AddHash(*sha1_hash, &out->bad_static_spki_hashes);
904 DCHECK(ok) << " failed to parse " << *hash; 571 sha1_hash++;
905 hash++;
906 } 572 }
907 } 573 }
908 } 574 }
909 return true; 575 return true;
910 } 576 }
911 } 577 }
912 return false; 578 return false;
913 } 579 }
914 580
915 #include "net/base/transport_security_state_static.h" 581 #include "net/base/transport_security_state_static.h"
(...skipping 18 matching lines...) Expand all
934 if (entry->length == canonicalized_host.size() - i && 600 if (entry->length == canonicalized_host.size() - i &&
935 memcmp(entry->dns_name, &canonicalized_host[i], entry->length) == 0) { 601 memcmp(entry->dns_name, &canonicalized_host[i], entry->length) == 0) {
936 return entry; 602 return entry;
937 } 603 }
938 } 604 }
939 } 605 }
940 606
941 return NULL; 607 return NULL;
942 } 608 }
943 609
610 bool TransportSecurityState::AddHSTSHeader(const std::string& host,
611 const std::string& value) {
612 base::Time now = base::Time::Now();
613 TransportSecurityState::DomainState domain_state;
614 if (ParseHSTSHeader(now, value, &domain_state.upgrade_expiry,
615 &domain_state.include_subdomains)) {
616 // Handle max-age == 0
617 if (now == domain_state.upgrade_expiry)
618 domain_state.upgrade_mode = DomainState::MODE_DEFAULT;
619 else
620 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
621 domain_state.created = now;
622 EnableHost(host, domain_state);
623 return true;
624 }
625 return false;
626 }
627
628 bool TransportSecurityState::AddHPKPHeader(const std::string& host,
629 const std::string& value,
630 const SSLInfo& ssl_info) {
631 base::Time now = base::Time::Now();
632 TransportSecurityState::DomainState domain_state;
633 if (ParseHPKPHeader(now, value, ssl_info.public_key_hashes,
634 &domain_state.dynamic_spki_hashes_expiry,
635 &domain_state.dynamic_spki_hashes)) {
636 domain_state.upgrade_mode = DomainState::MODE_DEFAULT;
637 domain_state.created = now;
638 EnableHost(host, domain_state);
639 return true;
640 }
641 return false;
642 }
643
944 // static 644 // static
945 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host, 645 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host,
946 bool sni_enabled) { 646 bool sni_enabled) {
947 std::string canonicalized_host = CanonicalizeHost(host); 647 std::string canonicalized_host = CanonicalizeHost(host);
948 const struct HSTSPreload* entry = 648 const struct HSTSPreload* entry =
949 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); 649 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS);
950 650
951 if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts) 651 if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts)
952 return true; 652 return true;
953 653
(...skipping 26 matching lines...) Expand all
980 680
981 DCHECK(entry); 681 DCHECK(entry);
982 DCHECK(entry->pins.required_hashes); 682 DCHECK(entry->pins.required_hashes);
983 DCHECK(entry->second_level_domain_name != DOMAIN_NOT_PINNED); 683 DCHECK(entry->second_level_domain_name != DOMAIN_NOT_PINNED);
984 684
985 UMA_HISTOGRAM_ENUMERATION("Net.PublicKeyPinFailureDomain", 685 UMA_HISTOGRAM_ENUMERATION("Net.PublicKeyPinFailureDomain",
986 entry->second_level_domain_name, DOMAIN_NUM_EVENTS); 686 entry->second_level_domain_name, DOMAIN_NUM_EVENTS);
987 } 687 }
988 688
989 // static 689 // static
990 const char* TransportSecurityState::HashValueLabel(
991 const HashValue& hash_value) {
992 switch (hash_value.tag) {
993 case HASH_VALUE_SHA1:
994 return "sha1/";
995 case HASH_VALUE_SHA256:
996 return "sha256/";
997 default:
998 NOTREACHED();
999 LOG(WARNING) << "Invalid fingerprint of unknown type " << hash_value.tag;
1000 return "unknown/";
1001 }
1002 }
1003
1004 // static
1005 bool TransportSecurityState::IsBuildTimely() { 690 bool TransportSecurityState::IsBuildTimely() {
1006 const base::Time build_time = base::GetBuildTime(); 691 const base::Time build_time = base::GetBuildTime();
1007 // We consider built-in information to be timely for 10 weeks. 692 // We consider built-in information to be timely for 10 weeks.
1008 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; 693 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
1009 } 694 }
1010 695
1011 bool TransportSecurityState::GetStaticDomainState( 696 bool TransportSecurityState::GetStaticDomainState(
1012 const std::string& canonicalized_host, 697 const std::string& canonicalized_host,
1013 bool sni_enabled, 698 bool sni_enabled,
1014 DomainState* out) { 699 DomainState* out) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1049 void TransportSecurityState::AddOrUpdateEnabledHosts( 734 void TransportSecurityState::AddOrUpdateEnabledHosts(
1050 const std::string& hashed_host, const DomainState& state) { 735 const std::string& hashed_host, const DomainState& state) {
1051 enabled_hosts_[hashed_host] = state; 736 enabled_hosts_[hashed_host] = state;
1052 } 737 }
1053 738
1054 void TransportSecurityState::AddOrUpdateForcedHosts( 739 void TransportSecurityState::AddOrUpdateForcedHosts(
1055 const std::string& hashed_host, const DomainState& state) { 740 const std::string& hashed_host, const DomainState& state) {
1056 forced_hosts_[hashed_host] = state; 741 forced_hosts_[hashed_host] = state;
1057 } 742 }
1058 743
1059 static std::string HashesToBase64String(
1060 const HashValueVector& hashes) {
1061 std::vector<std::string> hashes_strs;
1062 for (HashValueVector::const_iterator
1063 i = hashes.begin(); i != hashes.end(); i++) {
1064 std::string s;
1065 const std::string hash_str(reinterpret_cast<const char*>(i->data()),
1066 i->size());
1067 base::Base64Encode(hash_str, &s);
1068 hashes_strs.push_back(s);
1069 }
1070
1071 return JoinString(hashes_strs, ',');
1072 }
1073
1074 TransportSecurityState::DomainState::DomainState() 744 TransportSecurityState::DomainState::DomainState()
1075 : upgrade_mode(MODE_FORCE_HTTPS), 745 : upgrade_mode(MODE_FORCE_HTTPS),
1076 created(base::Time::Now()), 746 created(base::Time::Now()),
1077 include_subdomains(false) { 747 include_subdomains(false) {
1078 } 748 }
1079 749
1080 TransportSecurityState::DomainState::~DomainState() { 750 TransportSecurityState::DomainState::~DomainState() {
1081 } 751 }
1082 752
1083 bool TransportSecurityState::DomainState::IsChainOfPublicKeysPermitted( 753 bool TransportSecurityState::DomainState::IsChainOfPublicKeysPermitted(
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1126 return true; 796 return true;
1127 } 797 }
1128 798
1129 bool TransportSecurityState::DomainState::HasPins() const { 799 bool TransportSecurityState::DomainState::HasPins() const {
1130 return static_spki_hashes.size() > 0 || 800 return static_spki_hashes.size() > 0 ||
1131 bad_static_spki_hashes.size() > 0 || 801 bad_static_spki_hashes.size() > 0 ||
1132 dynamic_spki_hashes.size() > 0; 802 dynamic_spki_hashes.size() > 0;
1133 } 803 }
1134 804
1135 } // namespace 805 } // namespace
OLDNEW
« no previous file with comments | « net/base/transport_security_state.h ('k') | net/base/transport_security_state_static.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698