Index: net/http/http_stream_factory_impl_job.cc |
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc |
index d50d24fe13707a6db60bb9cf4537ce6273b2a6aa..7e06f0185f2c6ab3b63a1a46cb4499a079df084e 100644 |
--- a/net/http/http_stream_factory_impl_job.cc |
+++ b/net/http/http_stream_factory_impl_job.cc |
@@ -23,9 +23,11 @@ |
#include "base/trace_event/trace_event.h" |
#include "base/values.h" |
#include "build/build_config.h" |
+#include "crypto/sha2.h" |
#include "net/base/port_util.h" |
#include "net/base/proxy_delegate.h" |
#include "net/base/trace_constants.h" |
+#include "net/cert/asn1_util.h" |
#include "net/cert/cert_verifier.h" |
#include "net/http/bidirectional_stream_impl.h" |
#include "net/http/http_basic_stream.h" |
@@ -1528,6 +1530,44 @@ int HttpStreamFactoryImpl::Job::HandleCertificateError(int error) { |
load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS; |
if (ssl_socket->IgnoreCertError(error, load_flags)) |
return OK; |
+ |
+ // Ignore errors for certificates that chain up to switch-whitelisted certs. |
+ if (!session_->params().ignore_certificate_error_spki_set.empty()) { |
+ base::flat_set<SHA256HashValue, SHA256HashValueLessThan> hashes; |
+ std::string certDer; |
+ base::StringPiece spki; |
+ SHA256HashValue hash; |
+ if (X509Certificate::GetDEREncoded( |
+ ssl_info_.unverified_cert->os_cert_handle(), &certDer) && |
+ asn1::ExtractSPKIFromDERCert(certDer, &spki)) { |
+ crypto::SHA256HashString(spki, &hash, sizeof(SHA256HashValue)); |
+ hashes.insert(hash); |
+ } |
+ for (const net::X509Certificate::OSCertHandle& intermediate : |
+ ssl_info_.unverified_cert->GetIntermediateCertificates()) { |
+ if (X509Certificate::GetDEREncoded(intermediate, &certDer) && |
+ asn1::ExtractSPKIFromDERCert(certDer, &spki)) { |
+ crypto::SHA256HashString(spki, &hash, sizeof(SHA256HashValue)); |
+ hashes.insert(hash); |
+ } |
+ } |
+ |
+ // Try to intersect SPKIs from the chain with the switch whitelist. |
+ auto a = session_->params().ignore_certificate_error_spki_set.begin(); |
+ auto aEnd = session_->params().ignore_certificate_error_spki_set.end(); |
+ auto b = hashes.begin(); |
+ auto bEnd = hashes.end(); |
+ static const net::SHA256HashValueLessThan sha256_lt; |
+ while (a != aEnd && b != bEnd) { |
+ if (sha256_lt(*a, *b)) |
+ ++a; |
+ else if (sha256_lt(*b, *a)) |
+ ++b; |
+ else |
+ return OK; |
+ } |
+ } |
+ |
return error; |
} |