xref: /aosp_15_r20/external/cronet/net/cert/mock_cert_verifier.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "net/cert/mock_cert_verifier.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <memory>
8*6777b538SAndroid Build Coastguard Worker #include <utility>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include "base/callback_list.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/memory/ref_counted.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/memory/weak_ptr.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/strings/pattern.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/task/single_thread_task_runner.h"
19*6777b538SAndroid Build Coastguard Worker #include "net/base/net_errors.h"
20*6777b538SAndroid Build Coastguard Worker #include "net/cert/cert_status_flags.h"
21*6777b538SAndroid Build Coastguard Worker #include "net/cert/cert_verify_result.h"
22*6777b538SAndroid Build Coastguard Worker #include "net/cert/x509_certificate.h"
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker namespace net {
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker namespace {
27*6777b538SAndroid Build Coastguard Worker // Helper function for setting the appropriate CertStatus given a net::Error.
MapNetErrorToCertStatus(int error)28*6777b538SAndroid Build Coastguard Worker CertStatus MapNetErrorToCertStatus(int error) {
29*6777b538SAndroid Build Coastguard Worker   switch (error) {
30*6777b538SAndroid Build Coastguard Worker     case ERR_CERT_COMMON_NAME_INVALID:
31*6777b538SAndroid Build Coastguard Worker       return CERT_STATUS_COMMON_NAME_INVALID;
32*6777b538SAndroid Build Coastguard Worker     case ERR_CERT_DATE_INVALID:
33*6777b538SAndroid Build Coastguard Worker       return CERT_STATUS_DATE_INVALID;
34*6777b538SAndroid Build Coastguard Worker     case ERR_CERT_AUTHORITY_INVALID:
35*6777b538SAndroid Build Coastguard Worker       return CERT_STATUS_AUTHORITY_INVALID;
36*6777b538SAndroid Build Coastguard Worker     case ERR_CERT_NO_REVOCATION_MECHANISM:
37*6777b538SAndroid Build Coastguard Worker       return CERT_STATUS_NO_REVOCATION_MECHANISM;
38*6777b538SAndroid Build Coastguard Worker     case ERR_CERT_UNABLE_TO_CHECK_REVOCATION:
39*6777b538SAndroid Build Coastguard Worker       return CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
40*6777b538SAndroid Build Coastguard Worker     case ERR_CERTIFICATE_TRANSPARENCY_REQUIRED:
41*6777b538SAndroid Build Coastguard Worker       return CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED;
42*6777b538SAndroid Build Coastguard Worker     case ERR_CERT_REVOKED:
43*6777b538SAndroid Build Coastguard Worker       return CERT_STATUS_REVOKED;
44*6777b538SAndroid Build Coastguard Worker     case ERR_CERT_INVALID:
45*6777b538SAndroid Build Coastguard Worker       return CERT_STATUS_INVALID;
46*6777b538SAndroid Build Coastguard Worker     case ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
47*6777b538SAndroid Build Coastguard Worker       return CERT_STATUS_WEAK_SIGNATURE_ALGORITHM;
48*6777b538SAndroid Build Coastguard Worker     case ERR_CERT_NON_UNIQUE_NAME:
49*6777b538SAndroid Build Coastguard Worker       return CERT_STATUS_NON_UNIQUE_NAME;
50*6777b538SAndroid Build Coastguard Worker     case ERR_CERT_WEAK_KEY:
51*6777b538SAndroid Build Coastguard Worker       return CERT_STATUS_WEAK_KEY;
52*6777b538SAndroid Build Coastguard Worker     case ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN:
53*6777b538SAndroid Build Coastguard Worker       return CERT_STATUS_PINNED_KEY_MISSING;
54*6777b538SAndroid Build Coastguard Worker     case ERR_CERT_NAME_CONSTRAINT_VIOLATION:
55*6777b538SAndroid Build Coastguard Worker       return CERT_STATUS_NAME_CONSTRAINT_VIOLATION;
56*6777b538SAndroid Build Coastguard Worker     case ERR_CERT_VALIDITY_TOO_LONG:
57*6777b538SAndroid Build Coastguard Worker       return CERT_STATUS_VALIDITY_TOO_LONG;
58*6777b538SAndroid Build Coastguard Worker     case ERR_CERT_SYMANTEC_LEGACY:
59*6777b538SAndroid Build Coastguard Worker       return CERT_STATUS_SYMANTEC_LEGACY;
60*6777b538SAndroid Build Coastguard Worker     case ERR_CERT_KNOWN_INTERCEPTION_BLOCKED:
61*6777b538SAndroid Build Coastguard Worker       return (CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED | CERT_STATUS_REVOKED);
62*6777b538SAndroid Build Coastguard Worker     default:
63*6777b538SAndroid Build Coastguard Worker       return 0;
64*6777b538SAndroid Build Coastguard Worker   }
65*6777b538SAndroid Build Coastguard Worker }
66*6777b538SAndroid Build Coastguard Worker }  // namespace
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker struct MockCertVerifier::Rule {
Rulenet::MockCertVerifier::Rule69*6777b538SAndroid Build Coastguard Worker   Rule(scoped_refptr<X509Certificate> cert_arg,
70*6777b538SAndroid Build Coastguard Worker        const std::string& hostname_arg,
71*6777b538SAndroid Build Coastguard Worker        const CertVerifyResult& result_arg,
72*6777b538SAndroid Build Coastguard Worker        int rv_arg)
73*6777b538SAndroid Build Coastguard Worker       : cert(std::move(cert_arg)),
74*6777b538SAndroid Build Coastguard Worker         hostname(hostname_arg),
75*6777b538SAndroid Build Coastguard Worker         result(result_arg),
76*6777b538SAndroid Build Coastguard Worker         rv(rv_arg) {
77*6777b538SAndroid Build Coastguard Worker     DCHECK(cert);
78*6777b538SAndroid Build Coastguard Worker     DCHECK(result.verified_cert);
79*6777b538SAndroid Build Coastguard Worker   }
80*6777b538SAndroid Build Coastguard Worker 
81*6777b538SAndroid Build Coastguard Worker   scoped_refptr<X509Certificate> cert;
82*6777b538SAndroid Build Coastguard Worker   std::string hostname;
83*6777b538SAndroid Build Coastguard Worker   CertVerifyResult result;
84*6777b538SAndroid Build Coastguard Worker   int rv;
85*6777b538SAndroid Build Coastguard Worker };
86*6777b538SAndroid Build Coastguard Worker 
87*6777b538SAndroid Build Coastguard Worker class MockCertVerifier::MockRequest : public CertVerifier::Request {
88*6777b538SAndroid Build Coastguard Worker  public:
MockRequest(MockCertVerifier * parent,CertVerifyResult * result,CompletionOnceCallback callback)89*6777b538SAndroid Build Coastguard Worker   MockRequest(MockCertVerifier* parent,
90*6777b538SAndroid Build Coastguard Worker               CertVerifyResult* result,
91*6777b538SAndroid Build Coastguard Worker               CompletionOnceCallback callback)
92*6777b538SAndroid Build Coastguard Worker       : result_(result), callback_(std::move(callback)) {
93*6777b538SAndroid Build Coastguard Worker     subscription_ = parent->request_list_.Add(
94*6777b538SAndroid Build Coastguard Worker         base::BindOnce(&MockRequest::Cleanup, weak_factory_.GetWeakPtr()));
95*6777b538SAndroid Build Coastguard Worker   }
96*6777b538SAndroid Build Coastguard Worker 
ReturnResultLater(int rv,const CertVerifyResult & result)97*6777b538SAndroid Build Coastguard Worker   void ReturnResultLater(int rv, const CertVerifyResult& result) {
98*6777b538SAndroid Build Coastguard Worker     base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
99*6777b538SAndroid Build Coastguard Worker         FROM_HERE, base::BindOnce(&MockRequest::ReturnResult,
100*6777b538SAndroid Build Coastguard Worker                                   weak_factory_.GetWeakPtr(), rv, result));
101*6777b538SAndroid Build Coastguard Worker   }
102*6777b538SAndroid Build Coastguard Worker 
103*6777b538SAndroid Build Coastguard Worker  private:
ReturnResult(int rv,const CertVerifyResult & result)104*6777b538SAndroid Build Coastguard Worker   void ReturnResult(int rv, const CertVerifyResult& result) {
105*6777b538SAndroid Build Coastguard Worker     // If the MockCertVerifier has been deleted, the callback will have been
106*6777b538SAndroid Build Coastguard Worker     // reset to null.
107*6777b538SAndroid Build Coastguard Worker     if (!callback_)
108*6777b538SAndroid Build Coastguard Worker       return;
109*6777b538SAndroid Build Coastguard Worker 
110*6777b538SAndroid Build Coastguard Worker     *result_ = result;
111*6777b538SAndroid Build Coastguard Worker     std::move(callback_).Run(rv);
112*6777b538SAndroid Build Coastguard Worker   }
113*6777b538SAndroid Build Coastguard Worker 
Cleanup()114*6777b538SAndroid Build Coastguard Worker   void Cleanup() {
115*6777b538SAndroid Build Coastguard Worker     // Note: May delete |this_|.
116*6777b538SAndroid Build Coastguard Worker     std::move(callback_).Reset();
117*6777b538SAndroid Build Coastguard Worker   }
118*6777b538SAndroid Build Coastguard Worker 
119*6777b538SAndroid Build Coastguard Worker   raw_ptr<CertVerifyResult> result_;
120*6777b538SAndroid Build Coastguard Worker   CompletionOnceCallback callback_;
121*6777b538SAndroid Build Coastguard Worker   base::CallbackListSubscription subscription_;
122*6777b538SAndroid Build Coastguard Worker 
123*6777b538SAndroid Build Coastguard Worker   base::WeakPtrFactory<MockRequest> weak_factory_{this};
124*6777b538SAndroid Build Coastguard Worker };
125*6777b538SAndroid Build Coastguard Worker 
126*6777b538SAndroid Build Coastguard Worker MockCertVerifier::MockCertVerifier() = default;
127*6777b538SAndroid Build Coastguard Worker 
~MockCertVerifier()128*6777b538SAndroid Build Coastguard Worker MockCertVerifier::~MockCertVerifier() {
129*6777b538SAndroid Build Coastguard Worker   // Reset the callbacks for any outstanding MockRequests to fulfill the
130*6777b538SAndroid Build Coastguard Worker   // respective net::CertVerifier contract.
131*6777b538SAndroid Build Coastguard Worker   request_list_.Notify();
132*6777b538SAndroid Build Coastguard Worker }
133*6777b538SAndroid Build Coastguard Worker 
Verify(const RequestParams & params,CertVerifyResult * verify_result,CompletionOnceCallback callback,std::unique_ptr<Request> * out_req,const NetLogWithSource & net_log)134*6777b538SAndroid Build Coastguard Worker int MockCertVerifier::Verify(const RequestParams& params,
135*6777b538SAndroid Build Coastguard Worker                              CertVerifyResult* verify_result,
136*6777b538SAndroid Build Coastguard Worker                              CompletionOnceCallback callback,
137*6777b538SAndroid Build Coastguard Worker                              std::unique_ptr<Request>* out_req,
138*6777b538SAndroid Build Coastguard Worker                              const NetLogWithSource& net_log) {
139*6777b538SAndroid Build Coastguard Worker   if (!async_) {
140*6777b538SAndroid Build Coastguard Worker     return VerifyImpl(params, verify_result);
141*6777b538SAndroid Build Coastguard Worker   }
142*6777b538SAndroid Build Coastguard Worker 
143*6777b538SAndroid Build Coastguard Worker   auto request =
144*6777b538SAndroid Build Coastguard Worker       std::make_unique<MockRequest>(this, verify_result, std::move(callback));
145*6777b538SAndroid Build Coastguard Worker   CertVerifyResult result;
146*6777b538SAndroid Build Coastguard Worker   int rv = VerifyImpl(params, &result);
147*6777b538SAndroid Build Coastguard Worker   request->ReturnResultLater(rv, result);
148*6777b538SAndroid Build Coastguard Worker   *out_req = std::move(request);
149*6777b538SAndroid Build Coastguard Worker   return ERR_IO_PENDING;
150*6777b538SAndroid Build Coastguard Worker }
151*6777b538SAndroid Build Coastguard Worker 
AddObserver(Observer * observer)152*6777b538SAndroid Build Coastguard Worker void MockCertVerifier::AddObserver(Observer* observer) {
153*6777b538SAndroid Build Coastguard Worker   observers_.AddObserver(observer);
154*6777b538SAndroid Build Coastguard Worker }
155*6777b538SAndroid Build Coastguard Worker 
RemoveObserver(Observer * observer)156*6777b538SAndroid Build Coastguard Worker void MockCertVerifier::RemoveObserver(Observer* observer) {
157*6777b538SAndroid Build Coastguard Worker   observers_.RemoveObserver(observer);
158*6777b538SAndroid Build Coastguard Worker }
159*6777b538SAndroid Build Coastguard Worker 
AddResultForCert(scoped_refptr<X509Certificate> cert,const CertVerifyResult & verify_result,int rv)160*6777b538SAndroid Build Coastguard Worker void MockCertVerifier::AddResultForCert(scoped_refptr<X509Certificate> cert,
161*6777b538SAndroid Build Coastguard Worker                                         const CertVerifyResult& verify_result,
162*6777b538SAndroid Build Coastguard Worker                                         int rv) {
163*6777b538SAndroid Build Coastguard Worker   AddResultForCertAndHost(std::move(cert), "*", verify_result, rv);
164*6777b538SAndroid Build Coastguard Worker }
165*6777b538SAndroid Build Coastguard Worker 
AddResultForCertAndHost(scoped_refptr<X509Certificate> cert,const std::string & host_pattern,const CertVerifyResult & verify_result,int rv)166*6777b538SAndroid Build Coastguard Worker void MockCertVerifier::AddResultForCertAndHost(
167*6777b538SAndroid Build Coastguard Worker     scoped_refptr<X509Certificate> cert,
168*6777b538SAndroid Build Coastguard Worker     const std::string& host_pattern,
169*6777b538SAndroid Build Coastguard Worker     const CertVerifyResult& verify_result,
170*6777b538SAndroid Build Coastguard Worker     int rv) {
171*6777b538SAndroid Build Coastguard Worker   rules_.push_back(Rule(std::move(cert), host_pattern, verify_result, rv));
172*6777b538SAndroid Build Coastguard Worker }
173*6777b538SAndroid Build Coastguard Worker 
ClearRules()174*6777b538SAndroid Build Coastguard Worker void MockCertVerifier::ClearRules() {
175*6777b538SAndroid Build Coastguard Worker   rules_.clear();
176*6777b538SAndroid Build Coastguard Worker }
177*6777b538SAndroid Build Coastguard Worker 
SimulateOnCertVerifierChanged()178*6777b538SAndroid Build Coastguard Worker void MockCertVerifier::SimulateOnCertVerifierChanged() {
179*6777b538SAndroid Build Coastguard Worker   for (Observer& observer : observers_) {
180*6777b538SAndroid Build Coastguard Worker     observer.OnCertVerifierChanged();
181*6777b538SAndroid Build Coastguard Worker   }
182*6777b538SAndroid Build Coastguard Worker }
183*6777b538SAndroid Build Coastguard Worker 
VerifyImpl(const RequestParams & params,CertVerifyResult * verify_result)184*6777b538SAndroid Build Coastguard Worker int MockCertVerifier::VerifyImpl(const RequestParams& params,
185*6777b538SAndroid Build Coastguard Worker                                  CertVerifyResult* verify_result) {
186*6777b538SAndroid Build Coastguard Worker   for (const Rule& rule : rules_) {
187*6777b538SAndroid Build Coastguard Worker     // Check just the server cert. Intermediates will be ignored.
188*6777b538SAndroid Build Coastguard Worker     if (!rule.cert->EqualsExcludingChain(params.certificate().get()))
189*6777b538SAndroid Build Coastguard Worker       continue;
190*6777b538SAndroid Build Coastguard Worker     if (!base::MatchPattern(params.hostname(), rule.hostname))
191*6777b538SAndroid Build Coastguard Worker       continue;
192*6777b538SAndroid Build Coastguard Worker     *verify_result = rule.result;
193*6777b538SAndroid Build Coastguard Worker     return rule.rv;
194*6777b538SAndroid Build Coastguard Worker   }
195*6777b538SAndroid Build Coastguard Worker 
196*6777b538SAndroid Build Coastguard Worker   // Fall through to the default.
197*6777b538SAndroid Build Coastguard Worker   verify_result->verified_cert = params.certificate();
198*6777b538SAndroid Build Coastguard Worker   verify_result->cert_status = MapNetErrorToCertStatus(default_result_);
199*6777b538SAndroid Build Coastguard Worker   return default_result_;
200*6777b538SAndroid Build Coastguard Worker }
201*6777b538SAndroid Build Coastguard Worker 
202*6777b538SAndroid Build Coastguard Worker ParamRecordingMockCertVerifier::ParamRecordingMockCertVerifier() = default;
203*6777b538SAndroid Build Coastguard Worker ParamRecordingMockCertVerifier::~ParamRecordingMockCertVerifier() = default;
204*6777b538SAndroid Build Coastguard Worker 
Verify(const RequestParams & params,CertVerifyResult * verify_result,CompletionOnceCallback callback,std::unique_ptr<Request> * out_req,const NetLogWithSource & net_log)205*6777b538SAndroid Build Coastguard Worker int ParamRecordingMockCertVerifier::Verify(const RequestParams& params,
206*6777b538SAndroid Build Coastguard Worker                                            CertVerifyResult* verify_result,
207*6777b538SAndroid Build Coastguard Worker                                            CompletionOnceCallback callback,
208*6777b538SAndroid Build Coastguard Worker                                            std::unique_ptr<Request>* out_req,
209*6777b538SAndroid Build Coastguard Worker                                            const NetLogWithSource& net_log) {
210*6777b538SAndroid Build Coastguard Worker   params_.push_back(params);
211*6777b538SAndroid Build Coastguard Worker   return MockCertVerifier::Verify(params, verify_result, std::move(callback),
212*6777b538SAndroid Build Coastguard Worker                                   out_req, net_log);
213*6777b538SAndroid Build Coastguard Worker }
214*6777b538SAndroid Build Coastguard Worker 
CertVerifierObserverCounter(CertVerifier * verifier)215*6777b538SAndroid Build Coastguard Worker CertVerifierObserverCounter::CertVerifierObserverCounter(
216*6777b538SAndroid Build Coastguard Worker     CertVerifier* verifier) {
217*6777b538SAndroid Build Coastguard Worker   obs_.Observe(verifier);
218*6777b538SAndroid Build Coastguard Worker }
219*6777b538SAndroid Build Coastguard Worker 
220*6777b538SAndroid Build Coastguard Worker CertVerifierObserverCounter::~CertVerifierObserverCounter() = default;
221*6777b538SAndroid Build Coastguard Worker 
OnCertVerifierChanged()222*6777b538SAndroid Build Coastguard Worker void CertVerifierObserverCounter::OnCertVerifierChanged() {
223*6777b538SAndroid Build Coastguard Worker   change_count_++;
224*6777b538SAndroid Build Coastguard Worker }
225*6777b538SAndroid Build Coastguard Worker 
226*6777b538SAndroid Build Coastguard Worker }  // namespace net
227