Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: net/cert/internal/cert_issuer_source_aia.cc

Issue 2036033002: Add CertIssuerSourceAia: authorityInfoAccess fetching for CertPathBuilder. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@cert-parsing-path-building
Patch Set: derp Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 "net/cert/internal/cert_issuer_source_aia.h"
6
7 #include "base/bind.h"
8 #include "net/cert/cert_net_fetcher.h"
9 #include "net/cert/internal/parsed_certificate.h"
10 #include "url/gurl.h"
11
12 namespace net {
13
14 namespace {
15
16 // TODO(mattm): These are arbitrary choices. Re-evaluate.
17 const int kTimeoutMilliseconds = 10000;
18 const int kMaxResponseBytes = 65536;
19 const int kMaxFetchesPerCert = 5;
20
21 class AiaRequest : public CertIssuerSource::Request {
22 public:
23 explicit AiaRequest(const CertIssuerSource::IssuerCallback& issuers_callback);
24 ~AiaRequest() override;
25
26 // CertIssuerSource::Request implementation.
27 CompletionStatus GetNext(scoped_refptr<ParsedCertificate>* out_cert) override;
28
29 void AddCertFetcherRequest(
30 std::unique_ptr<CertNetFetcher::Request> cert_fetcher_request);
31
32 void OnFetchCompleted(Error, const std::vector<uint8_t>&);
eroman 2016/06/14 00:22:21 nit: I believe the chrome style is to include the
mattm 2016/06/14 21:37:30 Done.
33
34 private:
35 bool HasNext() const { return current_result_ < results_.size(); }
36
37 CertIssuerSource::IssuerCallback issuers_callback_;
38 std::vector<std::unique_ptr<CertNetFetcher::Request>> cert_fetcher_requests_;
39 size_t pending_requests_ = 0;
40 std::vector<scoped_refptr<ParsedCertificate>> results_;
41 size_t current_result_ = 0;
42
43 DISALLOW_COPY_AND_ASSIGN(AiaRequest);
44 };
45
46 AiaRequest::AiaRequest(const CertIssuerSource::IssuerCallback& issuers_callback)
47 : issuers_callback_(issuers_callback) {}
48
49 AiaRequest::~AiaRequest() = default;
50
51 CompletionStatus AiaRequest::GetNext(
52 scoped_refptr<ParsedCertificate>* out_cert) {
53 if (HasNext()) {
54 *out_cert = std::move(results_[current_result_++]);
55 return CompletionStatus::SYNC;
56 }
57 *out_cert = nullptr;
58 if (pending_requests_)
59 return CompletionStatus::ASYNC;
60 return CompletionStatus::SYNC;
61 }
62
63 void AiaRequest::AddCertFetcherRequest(
64 std::unique_ptr<CertNetFetcher::Request> cert_fetcher_request) {
65 DCHECK(cert_fetcher_request);
66 cert_fetcher_requests_.push_back(std::move(cert_fetcher_request));
67 pending_requests_++;
68 }
69
70 void AiaRequest::OnFetchCompleted(Error error,
71 const std::vector<uint8_t>& fetched_bytes) {
72 DCHECK_GT(pending_requests_, 0U);
73 pending_requests_--;
74 bool client_waiting_for_callback = !HasNext();
75 if (error != OK) {
76 // TODO(mattm): propagate error info.
77 LOG(ERROR) << "AiaRequest::OnFetchCompleted got error " << error;
78 } else {
79 // RFC 5280 section 4.2.2.1:
80 //
81 // Conforming applications that support HTTP or FTP for accessing
82 // certificates MUST be able to accept individual DER encoded
83 // certificates and SHOULD be able to accept "certs-only" CMS messages.
84 //
85 // TODO(mattm): Is supporting CMS message format important?
86 //
87 // TODO(mattm): Avoid copying bytes. Change the CertNetFetcher and
88 // ParsedCertificate interface to allow passing through ownership of the
89 // bytes.
90 if (!ParsedCertificate::CreateAndAddToVector(
91 fetched_bytes.data(), fetched_bytes.size(),
92 ParsedCertificate::DataSource::INTERNAL_COPY, &results_)) {
93 // TODO(mattm): propagate error info.
94 LOG(ERROR) << "Error parsing AIA data";
95 }
96 }
97 // If the client is waiting for results, need to run callback if:
98 // * Some are available now.
99 // * The last fetch finished, even with no results. (Client needs to know to
100 // stop waiting.)
101 if (client_waiting_for_callback && (HasNext() || pending_requests_ == 0))
102 issuers_callback_.Run(this);
103 }
104
105 } // namespace
106
107 CertIssuerSourceAia::CertIssuerSourceAia(CertNetFetcher* cert_fetcher)
108 : cert_fetcher_(cert_fetcher) {}
109
110 CertIssuerSourceAia::~CertIssuerSourceAia() = default;
111
112 void CertIssuerSourceAia::SyncGetIssuersOf(
113 const ParsedCertificate* cert,
114 std::vector<scoped_refptr<ParsedCertificate>>* issuers) {
115 // CertIssuerSourceAia never returns synchronous results.
116 }
117
118 void CertIssuerSourceAia::AsyncGetIssuersOf(
119 const ParsedCertificate* cert,
120 const IssuerCallback& issuers_callback,
121 std::unique_ptr<Request>* out_req) {
122 if (!cert->has_authority_info_access())
123 return;
eroman 2016/06/14 00:22:21 Should we reset out_req for these various no-resu
mattm 2016/06/14 21:37:30 Done.
124
125 // RFC 5280 section 4.2.2.1:
126 //
127 // An authorityInfoAccess extension may include multiple instances of
128 // the id-ad-caIssuers accessMethod. The different instances may
129 // specify different methods for accessing the same information or may
130 // point to different information.
131
132 std::vector<GURL> urls;
133 for (const auto& uri : cert->ca_issuers_uris()) {
134 GURL url(uri);
135 if (url.is_valid()) {
136 // TODO(mattm): do the kMaxFetchesPerCert check only on the number of
137 // supported URL schemes, not all the URLs.
138 if (urls.size() < kMaxFetchesPerCert) {
139 urls.push_back(url);
140 } else {
141 // TODO(mattm): propagate error info.
142 LOG(ERROR) << "kMaxFetchesPerCert exceeded, skipping";
143 }
144 } else {
145 // TODO(mattm): propagate error info.
146 LOG(ERROR) << "invalid AIA URL: " << uri;
147 }
148 }
149 if (urls.empty())
150 return;
151
152 std::unique_ptr<AiaRequest> aia_request(new AiaRequest(issuers_callback));
153
154 for (const auto& url : urls) {
155 // TODO(mattm): add synchronous failure mode to FetchCaIssuers interface so
156 // that this doesn't need to wait for async callback just to tell that an
157 // URL has an unsupported scheme?
158 aia_request->AddCertFetcherRequest(cert_fetcher_->FetchCaIssuers(
159 url, kTimeoutMilliseconds, kMaxResponseBytes,
160 base::Bind(&AiaRequest::OnFetchCompleted,
161 base::Unretained(aia_request.get()))));
162 }
163
164 *out_req = std::move(aia_request);
165 }
166
167 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698