| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/transport_security_state.h" | 5 #include "net/http/transport_security_state.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <memory> | 8 #include <memory> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 uint32_t domain_id; | 368 uint32_t domain_id; |
| 369 // hostname_offset contains the number of bytes from the start of the given | 369 // hostname_offset contains the number of bytes from the start of the given |
| 370 // hostname where the name of the matching entry starts. | 370 // hostname where the name of the matching entry starts. |
| 371 size_t hostname_offset; | 371 size_t hostname_offset; |
| 372 bool sts_include_subdomains; | 372 bool sts_include_subdomains; |
| 373 bool pkp_include_subdomains; | 373 bool pkp_include_subdomains; |
| 374 bool force_https; | 374 bool force_https; |
| 375 bool has_pins; | 375 bool has_pins; |
| 376 bool expect_ct; | 376 bool expect_ct; |
| 377 uint32_t expect_ct_report_uri_id; | 377 uint32_t expect_ct_report_uri_id; |
| 378 bool expect_staple; |
| 379 bool expect_staple_include_subdomains; |
| 380 uint32_t expect_staple_report_uri_id; |
| 378 }; | 381 }; |
| 379 | 382 |
| 380 // DecodeHSTSPreloadRaw resolves |hostname| in the preloaded data. It returns | 383 // DecodeHSTSPreloadRaw resolves |hostname| in the preloaded data. It returns |
| 381 // false on internal error and true otherwise. After a successful return, | 384 // false on internal error and true otherwise. After a successful return, |
| 382 // |*out_found| is true iff a relevant entry has been found. If so, |*out| | 385 // |*out_found| is true iff a relevant entry has been found. If so, |*out| |
| 383 // contains the details. | 386 // contains the details. |
| 384 // | 387 // |
| 385 // Don't call this function, call DecodeHSTSPreload, below. | 388 // Don't call this function, call DecodeHSTSPreload, below. |
| 386 // | 389 // |
| 387 // Although this code should be robust, it never processes attacker-controlled | 390 // Although this code should be robust, it never processes attacker-controlled |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 } | 506 } |
| 504 | 507 |
| 505 if (!reader.Next(&tmp.expect_ct)) | 508 if (!reader.Next(&tmp.expect_ct)) |
| 506 return false; | 509 return false; |
| 507 | 510 |
| 508 if (tmp.expect_ct) { | 511 if (tmp.expect_ct) { |
| 509 if (!reader.Read(4, &tmp.expect_ct_report_uri_id)) | 512 if (!reader.Read(4, &tmp.expect_ct_report_uri_id)) |
| 510 return false; | 513 return false; |
| 511 } | 514 } |
| 512 | 515 |
| 516 if (!reader.Next(&tmp.expect_staple)) |
| 517 return false; |
| 518 tmp.expect_staple_include_subdomains = false; |
| 519 if (tmp.expect_staple) { |
| 520 if (!reader.Next(&tmp.expect_staple_include_subdomains)) |
| 521 return false; |
| 522 if (!reader.Read(4, &tmp.expect_staple_report_uri_id)) |
| 523 return false; |
| 524 } |
| 525 |
| 513 tmp.hostname_offset = hostname_offset; | 526 tmp.hostname_offset = hostname_offset; |
| 514 | 527 |
| 515 if (hostname_offset == 0 || hostname[hostname_offset - 1] == '.') { | 528 if (hostname_offset == 0 || hostname[hostname_offset - 1] == '.') { |
| 516 *out_found = tmp.sts_include_subdomains || tmp.pkp_include_subdomains; | 529 *out_found = tmp.sts_include_subdomains || |
| 530 tmp.pkp_include_subdomains || |
| 531 tmp.expect_staple_include_subdomains; |
| 517 *out = tmp; | 532 *out = tmp; |
| 518 | 533 |
| 519 if (hostname_offset > 0) { | 534 if (hostname_offset > 0) { |
| 520 out->force_https &= tmp.sts_include_subdomains; | 535 out->force_https &= tmp.sts_include_subdomains; |
| 521 } else { | 536 } else { |
| 522 *out_found = true; | 537 *out_found = true; |
| 523 return true; | 538 return true; |
| 524 } | 539 } |
| 525 } | 540 } |
| 526 | 541 |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 697 if (report_sender_) | 712 if (report_sender_) |
| 698 report_sender_->SetErrorCallback(base::Bind(RecordUMAForHPKPReportFailure)); | 713 report_sender_->SetErrorCallback(base::Bind(RecordUMAForHPKPReportFailure)); |
| 699 } | 714 } |
| 700 | 715 |
| 701 void TransportSecurityState::SetExpectCTReporter( | 716 void TransportSecurityState::SetExpectCTReporter( |
| 702 ExpectCTReporter* expect_ct_reporter) { | 717 ExpectCTReporter* expect_ct_reporter) { |
| 703 DCHECK(CalledOnValidThread()); | 718 DCHECK(CalledOnValidThread()); |
| 704 expect_ct_reporter_ = expect_ct_reporter; | 719 expect_ct_reporter_ = expect_ct_reporter; |
| 705 } | 720 } |
| 706 | 721 |
| 722 void TransportSecurityState::SetExpectStapleReporter( |
| 723 ExpectStapleReporter* expect_staple_reporter) { |
| 724 DCHECK(CalledOnValidThread()); |
| 725 expect_staple_reporter_ = expect_staple_reporter; |
| 726 } |
| 727 |
| 707 void TransportSecurityState::AddHSTSInternal( | 728 void TransportSecurityState::AddHSTSInternal( |
| 708 const std::string& host, | 729 const std::string& host, |
| 709 TransportSecurityState::STSState::UpgradeMode upgrade_mode, | 730 TransportSecurityState::STSState::UpgradeMode upgrade_mode, |
| 710 const base::Time& expiry, | 731 const base::Time& expiry, |
| 711 bool include_subdomains) { | 732 bool include_subdomains) { |
| 712 DCHECK(CalledOnValidThread()); | 733 DCHECK(CalledOnValidThread()); |
| 713 | 734 |
| 714 STSState sts_state; | 735 STSState sts_state; |
| 715 sts_state.last_observed = base::Time::Now(); | 736 sts_state.last_observed = base::Time::Now(); |
| 716 sts_state.include_subdomains = include_subdomains; | 737 sts_state.include_subdomains = include_subdomains; |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 849 | 870 |
| 850 if (!enable_static_expect_ct_ || !result.expect_ct) | 871 if (!enable_static_expect_ct_ || !result.expect_ct) |
| 851 return false; | 872 return false; |
| 852 | 873 |
| 853 expect_ct_state->domain = host.substr(result.hostname_offset); | 874 expect_ct_state->domain = host.substr(result.hostname_offset); |
| 854 expect_ct_state->report_uri = | 875 expect_ct_state->report_uri = |
| 855 GURL(kExpectCTReportURIs[result.expect_ct_report_uri_id]); | 876 GURL(kExpectCTReportURIs[result.expect_ct_report_uri_id]); |
| 856 return true; | 877 return true; |
| 857 } | 878 } |
| 858 | 879 |
| 880 bool TransportSecurityState::GetStaticExpectStapleState( |
| 881 const std::string& host, |
| 882 ExpectStapleState* expect_staple_state) const { |
| 883 DCHECK(CalledOnValidThread()); |
| 884 |
| 885 if (!IsBuildTimely()) |
| 886 return false; |
| 887 |
| 888 PreloadResult result; |
| 889 if (!DecodeHSTSPreload(host, &result)) |
| 890 return false; |
| 891 |
| 892 if (!enable_static_expect_staple_ || !result.expect_staple) |
| 893 return false; |
| 894 |
| 895 expect_staple_state->domain = host.substr(result.hostname_offset); |
| 896 expect_staple_state->include_subdomains = |
| 897 result.expect_staple_include_subdomains; |
| 898 expect_staple_state->report_uri = |
| 899 GURL(kExpectStapleReportURIs[result.expect_staple_report_uri_id]); |
| 900 return true; |
| 901 } |
| 902 |
| 859 bool TransportSecurityState::DeleteDynamicDataForHost(const std::string& host) { | 903 bool TransportSecurityState::DeleteDynamicDataForHost(const std::string& host) { |
| 860 DCHECK(CalledOnValidThread()); | 904 DCHECK(CalledOnValidThread()); |
| 861 | 905 |
| 862 const std::string canonicalized_host = CanonicalizeHost(host); | 906 const std::string canonicalized_host = CanonicalizeHost(host); |
| 863 if (canonicalized_host.empty()) | 907 if (canonicalized_host.empty()) |
| 864 return false; | 908 return false; |
| 865 | 909 |
| 866 const std::string hashed_host = HashHost(canonicalized_host); | 910 const std::string hashed_host = HashHost(canonicalized_host); |
| 867 bool deleted = false; | 911 bool deleted = false; |
| 868 STSStateMap::iterator sts_interator = enabled_sts_hosts_.find(hashed_host); | 912 STSStateMap::iterator sts_interator = enabled_sts_hosts_.find(hashed_host); |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1052 } | 1096 } |
| 1053 | 1097 |
| 1054 ExpectCTState state; | 1098 ExpectCTState state; |
| 1055 if (!GetStaticExpectCTState(host_port_pair.host(), &state)) | 1099 if (!GetStaticExpectCTState(host_port_pair.host(), &state)) |
| 1056 return; | 1100 return; |
| 1057 | 1101 |
| 1058 expect_ct_reporter_->OnExpectCTFailed(host_port_pair, state.report_uri, | 1102 expect_ct_reporter_->OnExpectCTFailed(host_port_pair, state.report_uri, |
| 1059 ssl_info); | 1103 ssl_info); |
| 1060 } | 1104 } |
| 1061 | 1105 |
| 1106 void TransportSecurityState::CheckExpectStaple( |
| 1107 const HostPortPair& host_port_pair, |
| 1108 const SSLInfo& ssl_info) { |
| 1109 DCHECK(CalledOnValidThread()); |
| 1110 if (!expect_staple_reporter_) |
| 1111 return; |
| 1112 if (!IsBuildTimely()) |
| 1113 return; |
| 1114 // TODO: actually check OCSP info |
| 1115 ExpectStapleState state; |
| 1116 if (!GetStaticExpectStapleState(host_port_pair.host(), &state)) |
| 1117 return; |
| 1118 expect_staple_reporter_->OnExpectStapleFailed(host_port_pair, |
| 1119 state.report_uri, ssl_info); |
| 1120 } |
| 1121 |
| 1062 // static | 1122 // static |
| 1063 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) { | 1123 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) { |
| 1064 PreloadResult result; | 1124 PreloadResult result; |
| 1065 if (!DecodeHSTSPreload(host, &result) || | 1125 if (!DecodeHSTSPreload(host, &result) || |
| 1066 !result.has_pins) { | 1126 !result.has_pins) { |
| 1067 return; | 1127 return; |
| 1068 } | 1128 } |
| 1069 | 1129 |
| 1070 DCHECK(result.domain_id != DOMAIN_NOT_PINNED); | 1130 DCHECK(result.domain_id != DOMAIN_NOT_PINNED); |
| 1071 | 1131 |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1303 | 1363 |
| 1304 TransportSecurityState::PKPState::PKPState(const PKPState& other) = default; | 1364 TransportSecurityState::PKPState::PKPState(const PKPState& other) = default; |
| 1305 | 1365 |
| 1306 TransportSecurityState::PKPState::~PKPState() { | 1366 TransportSecurityState::PKPState::~PKPState() { |
| 1307 } | 1367 } |
| 1308 | 1368 |
| 1309 TransportSecurityState::ExpectCTState::ExpectCTState() {} | 1369 TransportSecurityState::ExpectCTState::ExpectCTState() {} |
| 1310 | 1370 |
| 1311 TransportSecurityState::ExpectCTState::~ExpectCTState() {} | 1371 TransportSecurityState::ExpectCTState::~ExpectCTState() {} |
| 1312 | 1372 |
| 1373 TransportSecurityState::ExpectStapleState::ExpectStapleState() |
| 1374 : include_subdomains(false) {} |
| 1375 |
| 1376 TransportSecurityState::ExpectStapleState::~ExpectStapleState() {} |
| 1377 |
| 1313 bool TransportSecurityState::PKPState::CheckPublicKeyPins( | 1378 bool TransportSecurityState::PKPState::CheckPublicKeyPins( |
| 1314 const HashValueVector& hashes, | 1379 const HashValueVector& hashes, |
| 1315 std::string* failure_log) const { | 1380 std::string* failure_log) const { |
| 1316 // Validate that hashes is not empty. By the time this code is called (in | 1381 // Validate that hashes is not empty. By the time this code is called (in |
| 1317 // production), that should never happen, but it's good to be defensive. | 1382 // production), that should never happen, but it's good to be defensive. |
| 1318 // And, hashes *can* be empty in some test scenarios. | 1383 // And, hashes *can* be empty in some test scenarios. |
| 1319 if (hashes.empty()) { | 1384 if (hashes.empty()) { |
| 1320 failure_log->append( | 1385 failure_log->append( |
| 1321 "Rejecting empty public key chain for public-key-pinned domains: " + | 1386 "Rejecting empty public key chain for public-key-pinned domains: " + |
| 1322 domain); | 1387 domain); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1356 TransportSecurityState::PKPStateIterator::PKPStateIterator( | 1421 TransportSecurityState::PKPStateIterator::PKPStateIterator( |
| 1357 const TransportSecurityState& state) | 1422 const TransportSecurityState& state) |
| 1358 : iterator_(state.enabled_pkp_hosts_.begin()), | 1423 : iterator_(state.enabled_pkp_hosts_.begin()), |
| 1359 end_(state.enabled_pkp_hosts_.end()) { | 1424 end_(state.enabled_pkp_hosts_.end()) { |
| 1360 } | 1425 } |
| 1361 | 1426 |
| 1362 TransportSecurityState::PKPStateIterator::~PKPStateIterator() { | 1427 TransportSecurityState::PKPStateIterator::~PKPStateIterator() { |
| 1363 } | 1428 } |
| 1364 | 1429 |
| 1365 } // namespace | 1430 } // namespace |
| OLD | NEW |