OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 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 "chrome/browser/ssl/ignore_errors_cert_verifier.h" |
| 6 |
| 7 #include <iterator> |
| 8 #include <utility> |
| 9 |
| 10 #include "base/base64.h" |
| 11 #include "base/memory/ptr_util.h" |
| 12 #include "base/memory/ref_counted.h" |
| 13 #include "base/strings/string_piece.h" |
| 14 #include "base/strings/string_split.h" |
| 15 #include "chrome/common/chrome_switches.h" |
| 16 #include "crypto/sha2.h" |
| 17 #include "net/base/completion_callback.h" |
| 18 #include "net/base/hash_value.h" |
| 19 #include "net/base/net_errors.h" |
| 20 #include "net/base/net_export.h" |
| 21 #include "net/cert/asn1_util.h" |
| 22 #include "net/cert/cert_verify_result.h" |
| 23 #include "net/cert/x509_certificate.h" |
| 24 |
| 25 using ::net::CertVerifier; |
| 26 using ::net::CompletionCallback; |
| 27 using ::net::HashValue; |
| 28 using ::net::SHA256HashValue; |
| 29 using ::net::SHA256HashValueLessThan; |
| 30 using ::net::X509Certificate; |
| 31 |
| 32 // static |
| 33 std::unique_ptr<CertVerifier> IgnoreErrorsCertVerifier::MaybeWrapCertVerifier( |
| 34 const base::CommandLine& command_line, |
| 35 std::unique_ptr<CertVerifier> verifier) { |
| 36 if (!command_line.HasSwitch(switches::kUserDataDir) || |
| 37 !command_line.HasSwitch(switches::kIgnoreCertificateErrorsSPKIList)) { |
| 38 return verifier; |
| 39 } |
| 40 auto spki_list = |
| 41 base::SplitString(command_line.GetSwitchValueASCII( |
| 42 switches::kIgnoreCertificateErrorsSPKIList), |
| 43 ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| 44 return base::MakeUnique<IgnoreErrorsCertVerifier>( |
| 45 std::move(verifier), IgnoreErrorsCertVerifier::MakeWhitelist(spki_list)); |
| 46 } |
| 47 |
| 48 // static |
| 49 IgnoreErrorsCertVerifier::SPKIHashSet IgnoreErrorsCertVerifier::MakeWhitelist( |
| 50 const std::vector<std::string>& fingerprints) { |
| 51 IgnoreErrorsCertVerifier::SPKIHashSet whitelist; |
| 52 for (const std::string& fingerprint : fingerprints) { |
| 53 HashValue hash; |
| 54 if (!hash.FromString("sha256/" + fingerprint)) { |
| 55 LOG(ERROR) << "Invalid SPKI: " << fingerprint; |
| 56 continue; |
| 57 } |
| 58 SHA256HashValue sha256; |
| 59 DCHECK_EQ(hash.size(), sizeof(sha256)); |
| 60 memcpy(&sha256, hash.data(), sizeof(sha256)); |
| 61 whitelist.insert(sha256); |
| 62 } |
| 63 return whitelist; |
| 64 } |
| 65 |
| 66 IgnoreErrorsCertVerifier::IgnoreErrorsCertVerifier( |
| 67 std::unique_ptr<CertVerifier> verifier, |
| 68 IgnoreErrorsCertVerifier::SPKIHashSet whitelist) |
| 69 : verifier_(std::move(verifier)), whitelist_(std::move(whitelist)) {} |
| 70 |
| 71 IgnoreErrorsCertVerifier::~IgnoreErrorsCertVerifier() {} |
| 72 |
| 73 int IgnoreErrorsCertVerifier::Verify(const RequestParams& params, |
| 74 net::CRLSet* crl_set, |
| 75 net::CertVerifyResult* verify_result, |
| 76 const net::CompletionCallback& callback, |
| 77 std::unique_ptr<Request>* out_req, |
| 78 const net::NetLogWithSource& net_log) { |
| 79 SPKIHashSet spki_fingerprints; |
| 80 std::string cert_der; |
| 81 base::StringPiece cert_spki; |
| 82 SHA256HashValue hash; |
| 83 if (X509Certificate::GetDEREncoded(params.certificate()->os_cert_handle(), |
| 84 &cert_der) && |
| 85 net::asn1::ExtractSPKIFromDERCert(cert_der, &cert_spki)) { |
| 86 crypto::SHA256HashString(cert_spki, &hash, sizeof(SHA256HashValue)); |
| 87 spki_fingerprints.insert(hash); |
| 88 } |
| 89 for (const X509Certificate::OSCertHandle& intermediate : |
| 90 params.certificate()->GetIntermediateCertificates()) { |
| 91 if (X509Certificate::GetDEREncoded(intermediate, &cert_der) && |
| 92 net::asn1::ExtractSPKIFromDERCert(cert_der, &cert_spki)) { |
| 93 crypto::SHA256HashString(cert_spki, &hash, sizeof(SHA256HashValue)); |
| 94 spki_fingerprints.insert(hash); |
| 95 } |
| 96 } |
| 97 |
| 98 // Intersect SPKI hashes from the chain with the whitelist. |
| 99 auto whitelist_begin = whitelist_.begin(); |
| 100 auto whitelist_end = whitelist_.end(); |
| 101 auto fingerprints_begin = spki_fingerprints.begin(); |
| 102 auto fingerprints_end = spki_fingerprints.end(); |
| 103 static const SHA256HashValueLessThan sha256_lt; |
| 104 bool ignore_errors = false; |
| 105 while (whitelist_begin != whitelist_end && |
| 106 fingerprints_begin != fingerprints_end) { |
| 107 if (sha256_lt(*whitelist_begin, *fingerprints_begin)) { |
| 108 ++whitelist_begin; |
| 109 } else if (sha256_lt(*fingerprints_begin, *whitelist_begin)) { |
| 110 ++fingerprints_begin; |
| 111 } else { |
| 112 ignore_errors = true; |
| 113 break; |
| 114 } |
| 115 } |
| 116 |
| 117 if (ignore_errors) { |
| 118 verify_result->Reset(); |
| 119 verify_result->verified_cert = params.certificate(); |
| 120 std::transform(spki_fingerprints.begin(), spki_fingerprints.end(), |
| 121 std::back_inserter(verify_result->public_key_hashes), |
| 122 [](const SHA256HashValue& v) { return HashValue(v); }); |
| 123 return net::OK; |
| 124 } |
| 125 |
| 126 return verifier_->Verify(params, crl_set, verify_result, callback, out_req, |
| 127 net_log); |
| 128 } |
| 129 |
| 130 void IgnoreErrorsCertVerifier::set_whitelist(const SPKIHashSet& whitelist) { |
| 131 whitelist_ = whitelist; |
| 132 } |
OLD | NEW |