Index: net/cert/cert_verify_proc_whitelist.cc |
diff --git a/net/cert/cert_verify_proc_whitelist.cc b/net/cert/cert_verify_proc_whitelist.cc |
index 53489ffa60ab3c99b4ae2ff4dbfe004e769a937f..2ba4166d4d831d536fd4e682da876dc575fa0451 100644 |
--- a/net/cert/cert_verify_proc_whitelist.cc |
+++ b/net/cert/cert_verify_proc_whitelist.cc |
@@ -6,6 +6,7 @@ |
#include <cstdlib> |
+#include "net/base/lookup_string_in_fixed_set.h" |
#include "net/cert/x509_certificate.h" |
namespace net { |
@@ -55,27 +56,74 @@ int CompareHashValueToRawHash(const void* key, const void* element) { |
return memcmp(search_key->data(), element, search_key->size()); |
} |
+namespace wosign { |
+#include "net/data/ssl/wosign/wosign_domains-inc.cc" |
} // namespace |
-bool IsNonWhitelistedCertificate(const X509Certificate& cert, |
- const HashValueVector& public_key_hashes) { |
- // 2016-10-21 00:00:00 UTC |
- const base::Time last_wosign_cert = |
- base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(1477008000); |
+} // namespace |
+bool IsNonWhitelistedCertificate(const X509Certificate& cert, |
+ const HashValueVector& public_key_hashes, |
+ base::StringPiece hostname) { |
for (const auto& hash : public_key_hashes) { |
if (hash.tag != HASH_VALUE_SHA256) |
continue; |
// Check for WoSign/StartCom certificates. |
if (bsearch(&hash, kWosignKeys, arraysize(kWosignKeys), |
- crypto::kSHA256Length, CompareHashValueToRawHash) != nullptr && |
- (cert.valid_start().is_null() || cert.valid_start().is_max() || |
- cert.valid_start() > last_wosign_cert)) { |
- return true; |
+ crypto::kSHA256Length, CompareHashValueToRawHash) != nullptr) { |
+ // 2016-10-21 00:00:00 UTC |
+ const base::Time last_wosign_cert = |
+ base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(1477008000); |
+ |
+ // Don't allow new certificates. |
+ if (cert.valid_start().is_null() || cert.valid_start().is_max() || |
+ cert.valid_start() > last_wosign_cert) { |
+ return true; |
+ } |
+ |
+ // Don't allow certificates from non-whitelisted hosts. |
+ return !IsWhitelistedHost(wosign::kDafsa, arraysize(wosign::kDafsa), |
+ hostname); |
} |
} |
return false; |
} |
+bool IsWhitelistedHost(const unsigned char* graph, |
+ size_t graph_length, |
+ base::StringPiece host) { |
+ if (host.empty()) |
+ return false; |
+ |
+ size_t end = host.length(); |
+ |
+ // Skip trailing '.', if any. |
+ if (host[end - 1] == '.') { |
+ --end; |
+ } |
+ |
+ // Reverse through each of the domain components, trying to see if the |
+ // domain is on the whitelist. For example, the string |
+ // "www.domain.example.com" would be processed by first searching |
+ // for "com", then "example.com", then "domain.example.com". The |
+ // loop will terminate when there are no more distinct label separators, |
+ // and thus the final check for "www.domain.example.com". |
+ size_t start = end; |
+ while (start != 0 && |
+ (start = host.rfind('.', start - 1)) != base::StringPiece::npos) { |
+ const char* domain_str = host.data() + start + 1; |
+ size_t domain_length = end - start - 1; |
+ if (domain_length == 0) |
+ return false; |
+ if (LookupStringInFixedSet(graph, graph_length, domain_str, |
+ domain_length) != kDafsaNotFound) { |
+ return true; |
+ } |
+ } |
+ |
+ return LookupStringInFixedSet(graph, graph_length, host.data(), end) != |
+ kDafsaNotFound; |
+} |
+ |
} // namespace net |