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

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

Issue 2453093004: Remove dependence on a message loop for net::PathBuilder. (Closed)
Patch Set: remove unnecessary forward decl Created 4 years 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
« no previous file with comments | « net/cert/internal/path_builder.h ('k') | net/cert/internal/path_builder_pkits_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/cert/internal/path_builder.h" 5 #include "net/cert/internal/path_builder.h"
6 6
7 #include <set> 7 #include <set>
8 #include <unordered_set> 8 #include <unordered_set>
9 9
10 #include "base/callback_helpers.h"
11 #include "base/logging.h" 10 #include "base/logging.h"
12 #include "base/memory/ptr_util.h" 11 #include "base/memory/ptr_util.h"
13 #include "net/base/net_errors.h" 12 #include "net/base/net_errors.h"
14 #include "net/cert/internal/cert_issuer_source.h" 13 #include "net/cert/internal/cert_issuer_source.h"
15 #include "net/cert/internal/parse_certificate.h" 14 #include "net/cert/internal/parse_certificate.h"
16 #include "net/cert/internal/parse_name.h" // For CertDebugString. 15 #include "net/cert/internal/parse_name.h" // For CertDebugString.
17 #include "net/cert/internal/signature_policy.h" 16 #include "net/cert/internal/signature_policy.h"
18 #include "net/cert/internal/trust_store.h" 17 #include "net/cert/internal/trust_store.h"
19 #include "net/cert/internal/verify_certificate_chain.h" 18 #include "net/cert/internal/verify_certificate_chain.h"
20 #include "net/cert/internal/verify_name_match.h" 19 #include "net/cert/internal/verify_name_match.h"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 // CertIssuersIter iterates through the intermediates from |cert_issuer_sources| 63 // CertIssuersIter iterates through the intermediates from |cert_issuer_sources|
65 // which may be issuers of |cert|. 64 // which may be issuers of |cert|.
66 class CertIssuersIter { 65 class CertIssuersIter {
67 public: 66 public:
68 // Constructs the CertIssuersIter. |*cert_issuer_sources| and |*trust_store| 67 // Constructs the CertIssuersIter. |*cert_issuer_sources| and |*trust_store|
69 // must be valid for the lifetime of the CertIssuersIter. 68 // must be valid for the lifetime of the CertIssuersIter.
70 CertIssuersIter(scoped_refptr<ParsedCertificate> cert, 69 CertIssuersIter(scoped_refptr<ParsedCertificate> cert,
71 CertIssuerSources* cert_issuer_sources, 70 CertIssuerSources* cert_issuer_sources,
72 const TrustStore* trust_store); 71 const TrustStore* trust_store);
73 72
74 // Gets the next candidate issuer. If an issuer is ready synchronously, SYNC 73 // Gets the next candidate issuer, or clears |*out| when all issuers have been
75 // is returned and the cert is stored in |*cert|. If an issuer is not 74 // exhausted.
76 // ready, ASYNC is returned and |callback| will be called once |*out_cert| has 75 void GetNextIssuer(CertificateOrTrustAnchor* out);
77 // been set. If |callback| is null, always completes synchronously.
78 //
79 // In either case, if all issuers have been exhausted, |*out| is cleared.
80 CompletionStatus GetNextIssuer(CertificateOrTrustAnchor* out,
81 const base::Closure& callback);
82 76
83 // Returns the |cert| for which issuers are being retrieved. 77 // Returns the |cert| for which issuers are being retrieved.
84 const ParsedCertificate* cert() const { return cert_.get(); } 78 const ParsedCertificate* cert() const { return cert_.get(); }
85 scoped_refptr<ParsedCertificate> reference_cert() const { return cert_; } 79 scoped_refptr<ParsedCertificate> reference_cert() const { return cert_; }
86 80
87 private: 81 private:
82 void AddIssuers(ParsedCertificateList issuers);
88 void DoAsyncIssuerQuery(); 83 void DoAsyncIssuerQuery();
89 void GotAsyncAnchors(TrustAnchors anchors);
90 void GotAsyncCerts(CertIssuerSource::Request* request);
91 void NotifyIfNecessary();
92 84
93 scoped_refptr<ParsedCertificate> cert_; 85 scoped_refptr<ParsedCertificate> cert_;
94 CertIssuerSources* cert_issuer_sources_; 86 CertIssuerSources* cert_issuer_sources_;
95 const TrustStore* trust_store_; 87 const TrustStore* trust_store_;
96 88
97 // The list of trust anchors that match the issuer name for |cert_|. 89 // The list of trust anchors that match the issuer name for |cert_|.
98 TrustAnchors anchors_; 90 TrustAnchors anchors_;
99 // The index of the next trust anchor in |anchors_| to return. 91 // The index of the next trust anchor in |anchors_| to return.
100 size_t cur_anchor_ = 0; 92 size_t cur_anchor_ = 0;
101 93
(...skipping 10 matching lines...) Expand all
112 104
113 // Set of DER-encoded values for the certs in |issuers_|. Used to prevent 105 // Set of DER-encoded values for the certs in |issuers_|. Used to prevent
114 // duplicates. This is based on the full DER of the cert to allow different 106 // duplicates. This is based on the full DER of the cert to allow different
115 // versions of the same certificate to be tried in different candidate paths. 107 // versions of the same certificate to be tried in different candidate paths.
116 // This points to data owned by |issuers_|. 108 // This points to data owned by |issuers_|.
117 std::unordered_set<base::StringPiece, base::StringPieceHash> present_issuers_; 109 std::unordered_set<base::StringPiece, base::StringPieceHash> present_issuers_;
118 110
119 // Tracks which requests have been made yet. 111 // Tracks which requests have been made yet.
120 bool did_initial_query_ = false; 112 bool did_initial_query_ = false;
121 bool did_async_issuer_query_ = false; 113 bool did_async_issuer_query_ = false;
122 // If asynchronous requests were made, how many of them are still outstanding? 114 // Index into pending_async_requests_ that is the next one to process.
123 size_t pending_async_results_; 115 size_t cur_async_request_ = 0;
124 // Owns the Request objects for any asynchronous requests so that they will be 116 // Owns the Request objects for any asynchronous requests so that they will be
125 // cancelled if CertIssuersIter is destroyed. 117 // cancelled if CertIssuersIter is destroyed.
126 std::vector<std::unique_ptr<CertIssuerSource::Request>> 118 std::vector<std::unique_ptr<CertIssuerSource::Request>>
127 pending_async_requests_; 119 pending_async_requests_;
128 std::unique_ptr<TrustStore::Request> pending_anchor_request_;
129
130 // When GetNextIssuer was called and returned asynchronously, |*out_| is
131 // where the result will be stored, and |callback_| will be run when the
132 // result is ready.
133 CertificateOrTrustAnchor* out_;
134 base::Closure callback_;
135 120
136 DISALLOW_COPY_AND_ASSIGN(CertIssuersIter); 121 DISALLOW_COPY_AND_ASSIGN(CertIssuersIter);
137 }; 122 };
138 123
139 CertIssuersIter::CertIssuersIter(scoped_refptr<ParsedCertificate> in_cert, 124 CertIssuersIter::CertIssuersIter(scoped_refptr<ParsedCertificate> in_cert,
140 CertIssuerSources* cert_issuer_sources, 125 CertIssuerSources* cert_issuer_sources,
141 const TrustStore* trust_store) 126 const TrustStore* trust_store)
142 : cert_(in_cert), 127 : cert_(in_cert),
143 cert_issuer_sources_(cert_issuer_sources), 128 cert_issuer_sources_(cert_issuer_sources),
144 trust_store_(trust_store) { 129 trust_store_(trust_store) {
145 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) << ") created"; 130 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) << ") created";
146 } 131 }
147 132
148 CompletionStatus CertIssuersIter::GetNextIssuer(CertificateOrTrustAnchor* out, 133 void CertIssuersIter::GetNextIssuer(CertificateOrTrustAnchor* out) {
149 const base::Closure& callback) {
150 // Should not be called again while already waiting for an async result.
151 DCHECK(callback_.is_null());
152
153 if (!did_initial_query_) { 134 if (!did_initial_query_) {
154 did_initial_query_ = true; 135 did_initial_query_ = true;
155 trust_store_->FindTrustAnchorsForCert( 136 trust_store_->FindTrustAnchorsForCert(cert_, &anchors_);
156 cert_,
157 callback.is_null() ? TrustStore::TrustAnchorsCallback()
158 : base::Bind(&CertIssuersIter::GotAsyncAnchors,
159 base::Unretained(this)),
160 &anchors_, &pending_anchor_request_);
161 137
162 for (auto* cert_issuer_source : *cert_issuer_sources_) { 138 for (auto* cert_issuer_source : *cert_issuer_sources_) {
163 ParsedCertificateList new_issuers; 139 ParsedCertificateList new_issuers;
164 cert_issuer_source->SyncGetIssuersOf(cert(), &new_issuers); 140 cert_issuer_source->SyncGetIssuersOf(cert(), &new_issuers);
165 for (scoped_refptr<ParsedCertificate>& issuer : new_issuers) { 141 AddIssuers(std::move(new_issuers));
166 if (present_issuers_.find(issuer->der_cert().AsStringPiece()) !=
167 present_issuers_.end())
168 continue;
169 present_issuers_.insert(issuer->der_cert().AsStringPiece());
170 issuers_.push_back(std::move(issuer));
171 }
172 } 142 }
173 DVLOG(1) << anchors_.size() << " sync anchors, " << issuers_.size() 143 DVLOG(1) << anchors_.size() << " sync anchors, " << issuers_.size()
174 << " sync issuers"; 144 << " sync issuers";
175 // TODO(mattm): sort by notbefore, etc (eg if cert issuer matches a trust 145 // TODO(mattm): sort by notbefore, etc (eg if cert issuer matches a trust
176 // anchor subject (or is a trust anchor), that should be sorted higher too. 146 // anchor subject (or is a trust anchor), that should be sorted higher too.
177 // See big list of possible sorting hints in RFC 4158.) 147 // See big list of possible sorting hints in RFC 4158.)
178 // (Update PathBuilderKeyRolloverTest.TestRolloverBothRootsTrusted once that 148 // (Update PathBuilderKeyRolloverTest.TestRolloverBothRootsTrusted once that
179 // is done) 149 // is done)
180 } 150 }
181 151
182 // Return possible trust anchors first. 152 // Return possible trust anchors first.
183 if (cur_anchor_ < anchors_.size()) { 153 if (cur_anchor_ < anchors_.size()) {
184 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) 154 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
185 << "): returning anchor " << cur_anchor_ << " of " 155 << "): returning anchor " << cur_anchor_ << " of "
186 << anchors_.size(); 156 << anchors_.size();
187 // Still have anchors that haven't been returned yet, return one of them. 157 // Still have anchors that haven't been returned yet, return one of them.
188 *out = CertificateOrTrustAnchor(anchors_[cur_anchor_++]); 158 *out = CertificateOrTrustAnchor(anchors_[cur_anchor_++]);
189 return CompletionStatus::SYNC; 159 return;
190 } 160 }
191 161
192 if (pending_anchor_request_) { 162 // If there aren't any issuers left, block until async results are ready.
193 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) 163 if (cur_issuer_ >= issuers_.size()) {
194 << ") Still waiting for async trust anchor results."; 164 if (!did_async_issuer_query_) {
195 out_ = out; 165 // Now issue request(s) for async ones (AIA, etc).
196 callback_ = callback; 166 DoAsyncIssuerQuery();
197 return CompletionStatus::ASYNC; 167 }
168
169 // TODO(eroman): Rather than blocking on the async requests in FIFO order,
170 // consume in the order they become ready.
171 while (cur_async_request_ < pending_async_requests_.size()) {
172 ParsedCertificateList new_issuers;
173 pending_async_requests_[cur_async_request_]->GetNext(&new_issuers);
174 if (new_issuers.empty()) {
175 // Request is exhausted, no more results pending from that
176 // CertIssuerSource.
177 pending_async_requests_[cur_async_request_++].reset();
178 continue;
179 }
180
181 AddIssuers(std::move(new_issuers));
182 break;
183 }
198 } 184 }
199 185
200 if (cur_issuer_ < issuers_.size()) { 186 if (cur_issuer_ < issuers_.size()) {
201 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) 187 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
202 << "): returning issuer " << cur_issuer_ << " of " 188 << "): returning issuer " << cur_issuer_ << " of "
203 << issuers_.size(); 189 << issuers_.size();
204 // Still have issuers that haven't been returned yet, return one of them. 190 // Still have issuers that haven't been returned yet, return one of them.
205 // A reference to the returned issuer is retained, since |present_issuers_| 191 // A reference to the returned issuer is retained, since |present_issuers_|
206 // points to data owned by it. 192 // points to data owned by it.
207 *out = CertificateOrTrustAnchor(issuers_[cur_issuer_++]); 193 *out = CertificateOrTrustAnchor(issuers_[cur_issuer_++]);
208 return CompletionStatus::SYNC; 194 return;
209 }
210
211 if (did_async_issuer_query_) {
212 if (pending_async_results_ == 0) {
213 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
214 << ") Reached the end of all available issuers.";
215 // Reached the end of all available issuers.
216 *out = CertificateOrTrustAnchor();
217 return CompletionStatus::SYNC;
218 }
219
220 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
221 << ") Still waiting for async results from other "
222 "CertIssuerSources.";
223 // Still waiting for async results from other CertIssuerSources.
224 out_ = out;
225 callback_ = callback;
226 return CompletionStatus::ASYNC;
227 }
228 // Reached the end of synchronously gathered issuers.
229
230 if (callback.is_null()) {
231 // Synchronous-only mode, don't try to query async sources.
232 *out = CertificateOrTrustAnchor();
233 return CompletionStatus::SYNC;
234 }
235
236 // Now issue request(s) for async ones (AIA, etc).
237 DoAsyncIssuerQuery();
238
239 if (pending_async_results_ == 0) {
240 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
241 << ") No cert sources have async results.";
242 // No cert sources have async results.
243 *out = CertificateOrTrustAnchor();
244 return CompletionStatus::SYNC;
245 } 195 }
246 196
247 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) 197 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
248 << ") issued AsyncGetIssuersOf call(s) (n=" << pending_async_results_ 198 << ") Reached the end of all available issuers.";
249 << ")"; 199 // Reached the end of all available issuers.
250 out_ = out; 200 *out = CertificateOrTrustAnchor();
251 callback_ = callback; 201 }
252 return CompletionStatus::ASYNC; 202
203 void CertIssuersIter::AddIssuers(ParsedCertificateList new_issuers) {
204 for (scoped_refptr<ParsedCertificate>& issuer : new_issuers) {
205 if (present_issuers_.find(issuer->der_cert().AsStringPiece()) !=
206 present_issuers_.end())
207 continue;
208 present_issuers_.insert(issuer->der_cert().AsStringPiece());
209 issuers_.push_back(std::move(issuer));
210 }
253 } 211 }
254 212
255 void CertIssuersIter::DoAsyncIssuerQuery() { 213 void CertIssuersIter::DoAsyncIssuerQuery() {
256 DCHECK(!did_async_issuer_query_); 214 DCHECK(!did_async_issuer_query_);
257 did_async_issuer_query_ = true; 215 did_async_issuer_query_ = true;
258 pending_async_results_ = 0; 216 cur_async_request_ = 0;
259 for (auto* cert_issuer_source : *cert_issuer_sources_) { 217 for (auto* cert_issuer_source : *cert_issuer_sources_) {
260 std::unique_ptr<CertIssuerSource::Request> request; 218 std::unique_ptr<CertIssuerSource::Request> request;
261 cert_issuer_source->AsyncGetIssuersOf( 219 cert_issuer_source->AsyncGetIssuersOf(cert(), &request);
262 cert(),
263 base::Bind(&CertIssuersIter::GotAsyncCerts, base::Unretained(this)),
264 &request);
265 if (request) { 220 if (request) {
266 DVLOG(1) << "AsyncGetIssuersOf(" << CertDebugString(cert()) 221 DVLOG(1) << "AsyncGetIssuersOf(" << CertDebugString(cert())
267 << ") pending..."; 222 << ") pending...";
268 pending_async_results_++;
269 pending_async_requests_.push_back(std::move(request)); 223 pending_async_requests_.push_back(std::move(request));
270 } 224 }
271 } 225 }
272 } 226 }
273 227
274 void CertIssuersIter::GotAsyncAnchors(TrustAnchors anchors) {
275 DVLOG(1) << "CertIssuersIter::GotAsyncAnchors(" << CertDebugString(cert())
276 << "): " << anchors.size() << " anchors";
277 for (scoped_refptr<TrustAnchor>& anchor : anchors)
278 anchors_.push_back(std::move(anchor));
279 pending_anchor_request_.reset();
280
281 NotifyIfNecessary();
282 }
283
284 void CertIssuersIter::GotAsyncCerts(CertIssuerSource::Request* request) {
285 DVLOG(1) << "CertIssuersIter::GotAsyncCerts(" << CertDebugString(cert())
286 << ")";
287 while (true) {
288 scoped_refptr<ParsedCertificate> cert;
289 CompletionStatus status = request->GetNext(&cert);
290 if (!cert) {
291 if (status == CompletionStatus::SYNC) {
292 // Request is exhausted, no more results pending from that
293 // CertIssuerSource.
294 DCHECK_GT(pending_async_results_, 0U);
295 pending_async_results_--;
296 }
297 break;
298 }
299 DCHECK_EQ(status, CompletionStatus::SYNC);
300 if (present_issuers_.find(cert->der_cert().AsStringPiece()) !=
301 present_issuers_.end())
302 continue;
303 present_issuers_.insert(cert->der_cert().AsStringPiece());
304 issuers_.push_back(std::move(cert));
305 }
306
307 // TODO(mattm): re-sort remaining elements of issuers_ (remaining elements may
308 // be more than the ones just inserted, depending on |cur_| value).
309
310 NotifyIfNecessary();
311 }
312
313 void CertIssuersIter::NotifyIfNecessary() {
314 // Notify that more results are available, if necessary.
315 if (!callback_.is_null()) {
316 if (cur_anchor_ < anchors_.size()) {
317 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
318 << "): async returning anchor " << cur_anchor_ << " of "
319 << anchors_.size();
320 *out_ = CertificateOrTrustAnchor(std::move(anchors_[cur_anchor_++]));
321 base::ResetAndReturn(&callback_).Run();
322 return;
323 }
324 if (cur_issuer_ < issuers_.size()) {
325 DCHECK(!pending_anchor_request_);
326 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
327 << "): async returning issuer " << cur_issuer_ << " of "
328 << issuers_.size();
329 *out_ = CertificateOrTrustAnchor(std::move(issuers_[cur_issuer_++]));
330 base::ResetAndReturn(&callback_).Run();
331 return;
332 }
333
334 if (!did_async_issuer_query_)
335 DoAsyncIssuerQuery();
336
337 if (pending_async_results_ == 0) {
338 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
339 << "): async returning empty result";
340 *out_ = CertificateOrTrustAnchor();
341 base::ResetAndReturn(&callback_).Run();
342 return;
343 }
344 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
345 << "): empty result, but other async results "
346 "pending, waiting..";
347 }
348 }
349
350 // CertIssuerIterPath tracks which certs are present in the path and prevents 228 // CertIssuerIterPath tracks which certs are present in the path and prevents
351 // paths from being built which repeat any certs (including different versions 229 // paths from being built which repeat any certs (including different versions
352 // of the same cert, based on Subject+SubjectAltName+SPKI). 230 // of the same cert, based on Subject+SubjectAltName+SPKI).
353 class CertIssuerIterPath { 231 class CertIssuerIterPath {
354 public: 232 public:
355 // Returns true if |cert| is already present in the path. 233 // Returns true if |cert| is already present in the path.
356 bool IsPresent(const ParsedCertificate* cert) const { 234 bool IsPresent(const ParsedCertificate* cert) const {
357 return present_certs_.find(GetKey(cert)) != present_certs_.end(); 235 return present_certs_.find(GetKey(cert)) != present_certs_.end();
358 } 236 }
359 237
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 class CertPathIter { 317 class CertPathIter {
440 public: 318 public:
441 CertPathIter(scoped_refptr<ParsedCertificate> cert, 319 CertPathIter(scoped_refptr<ParsedCertificate> cert,
442 const TrustStore* trust_store); 320 const TrustStore* trust_store);
443 321
444 // Adds a CertIssuerSource to provide intermediates for use in path building. 322 // Adds a CertIssuerSource to provide intermediates for use in path building.
445 // The |*cert_issuer_source| must remain valid for the lifetime of the 323 // The |*cert_issuer_source| must remain valid for the lifetime of the
446 // CertPathIter. 324 // CertPathIter.
447 void AddCertIssuerSource(CertIssuerSource* cert_issuer_source); 325 void AddCertIssuerSource(CertIssuerSource* cert_issuer_source);
448 326
449 // Gets the next candidate path. If a path is ready synchronously, SYNC is 327 // Gets the next candidate path, or clears |*path| when all paths have been
450 // returned and the path is stored in |*path|. If a path is not ready, 328 // exhausted.
451 // ASYNC is returned and |callback| will be called once |*path| has been set. 329 void GetNextPath(CertPath* path);
452 // In either case, if all paths have been exhausted, |*path| is cleared.
453 CompletionStatus GetNextPath(CertPath* path, const base::Closure& callback);
454 330
455 private: 331 private:
456 enum State { 332 enum State {
457 STATE_NONE, 333 STATE_NONE,
458 STATE_GET_NEXT_ISSUER, 334 STATE_GET_NEXT_ISSUER,
459 STATE_GET_NEXT_ISSUER_COMPLETE, 335 STATE_GET_NEXT_ISSUER_COMPLETE,
460 STATE_RETURN_A_PATH, 336 STATE_RETURN_A_PATH,
461 STATE_BACKTRACK, 337 STATE_BACKTRACK,
462 }; 338 };
463 339
464 CompletionStatus DoLoop(bool allow_async); 340 void DoGetNextIssuer();
465 341 void DoGetNextIssuerComplete();
466 CompletionStatus DoGetNextIssuer(bool allow_async); 342 void DoBackTrack();
467 CompletionStatus DoGetNextIssuerComplete();
468 CompletionStatus DoBackTrack();
469
470 void HandleGotNextIssuer(void);
471 343
472 // Stores the next candidate issuer, until it is used during the 344 // Stores the next candidate issuer, until it is used during the
473 // STATE_GET_NEXT_ISSUER_COMPLETE step. 345 // STATE_GET_NEXT_ISSUER_COMPLETE step.
474 CertificateOrTrustAnchor next_issuer_; 346 CertificateOrTrustAnchor next_issuer_;
475 // The current path being explored, made up of CertIssuerIters. Each node 347 // The current path being explored, made up of CertIssuerIters. Each node
476 // keeps track of the state of searching for issuers of that cert, so that 348 // keeps track of the state of searching for issuers of that cert, so that
477 // when backtracking it can resume the search where it left off. 349 // when backtracking it can resume the search where it left off.
478 CertIssuerIterPath cur_path_; 350 CertIssuerIterPath cur_path_;
479 // The CertIssuerSources for retrieving candidate issuers. 351 // The CertIssuerSources for retrieving candidate issuers.
480 CertIssuerSources cert_issuer_sources_; 352 CertIssuerSources cert_issuer_sources_;
481 // The TrustStore for checking if a path ends in a trust anchor. 353 // The TrustStore for checking if a path ends in a trust anchor.
482 const TrustStore* trust_store_; 354 const TrustStore* trust_store_;
483 // The output variable for storing the next candidate path, which the client 355 // The output variable for storing the next candidate path, which the client
484 // passes in to GetNextPath. Only used for a single path output. 356 // passes in to GetNextPath. Only used for a single path output.
485 CertPath* out_path_; 357 CertPath* out_path_;
486 // The callback to be called if an async lookup generated a candidate path.
487 base::Closure callback_;
488 // Current state of the state machine. 358 // Current state of the state machine.
489 State next_state_; 359 State next_state_;
490 360
491 DISALLOW_COPY_AND_ASSIGN(CertPathIter); 361 DISALLOW_COPY_AND_ASSIGN(CertPathIter);
492 }; 362 };
493 363
494 CertPathIter::CertPathIter(scoped_refptr<ParsedCertificate> cert, 364 CertPathIter::CertPathIter(scoped_refptr<ParsedCertificate> cert,
495 const TrustStore* trust_store) 365 const TrustStore* trust_store)
496 : next_issuer_(std::move(cert)), 366 : next_issuer_(std::move(cert)),
497 trust_store_(trust_store), 367 trust_store_(trust_store),
498 next_state_(STATE_GET_NEXT_ISSUER_COMPLETE) {} 368 next_state_(STATE_GET_NEXT_ISSUER_COMPLETE) {}
499 369
500 void CertPathIter::AddCertIssuerSource(CertIssuerSource* cert_issuer_source) { 370 void CertPathIter::AddCertIssuerSource(CertIssuerSource* cert_issuer_source) {
501 cert_issuer_sources_.push_back(cert_issuer_source); 371 cert_issuer_sources_.push_back(cert_issuer_source);
502 } 372 }
503 373
504 CompletionStatus CertPathIter::GetNextPath(CertPath* path, 374 // TODO(eroman): Simplify (doesn't need to use the "DoLoop" pattern).
505 const base::Closure& callback) { 375 void CertPathIter::GetNextPath(CertPath* path) {
506 out_path_ = path; 376 out_path_ = path;
507 out_path_->Clear(); 377 out_path_->Clear();
508 CompletionStatus rv = DoLoop(!callback.is_null());
509 if (rv == CompletionStatus::ASYNC) {
510 callback_ = callback;
511 } else {
512 // Clear the reference to the output parameter as a precaution.
513 out_path_ = nullptr;
514 }
515 return rv;
516 }
517
518 CompletionStatus CertPathIter::DoLoop(bool allow_async) {
519 CompletionStatus result = CompletionStatus::SYNC;
520 do { 378 do {
521 State state = next_state_; 379 State state = next_state_;
522 next_state_ = STATE_NONE; 380 next_state_ = STATE_NONE;
523 switch (state) { 381 switch (state) {
524 case STATE_NONE: 382 case STATE_NONE:
525 NOTREACHED(); 383 NOTREACHED();
526 break; 384 break;
527 case STATE_GET_NEXT_ISSUER: 385 case STATE_GET_NEXT_ISSUER:
528 result = DoGetNextIssuer(allow_async); 386 DoGetNextIssuer();
529 break; 387 break;
530 case STATE_GET_NEXT_ISSUER_COMPLETE: 388 case STATE_GET_NEXT_ISSUER_COMPLETE:
531 result = DoGetNextIssuerComplete(); 389 DoGetNextIssuerComplete();
532 break; 390 break;
533 case STATE_RETURN_A_PATH: 391 case STATE_RETURN_A_PATH:
534 // If the returned path did not verify, keep looking for other paths 392 // If the returned path did not verify, keep looking for other paths
535 // (the trust root is not part of cur_path_, so don't need to 393 // (the trust root is not part of cur_path_, so don't need to
536 // backtrack). 394 // backtrack).
537 next_state_ = STATE_GET_NEXT_ISSUER; 395 next_state_ = STATE_GET_NEXT_ISSUER;
538 result = CompletionStatus::SYNC;
539 break; 396 break;
540 case STATE_BACKTRACK: 397 case STATE_BACKTRACK:
541 result = DoBackTrack(); 398 DoBackTrack();
542 break; 399 break;
543 } 400 }
544 } while (result == CompletionStatus::SYNC && next_state_ != STATE_NONE && 401 } while (next_state_ != STATE_NONE && next_state_ != STATE_RETURN_A_PATH);
545 next_state_ != STATE_RETURN_A_PATH);
546 402
547 return result; 403 out_path_ = nullptr;
548 } 404 }
549 405
550 CompletionStatus CertPathIter::DoGetNextIssuer(bool allow_async) { 406 void CertPathIter::DoGetNextIssuer() {
551 next_state_ = STATE_GET_NEXT_ISSUER_COMPLETE; 407 next_state_ = STATE_GET_NEXT_ISSUER_COMPLETE;
552 CompletionStatus rv = cur_path_.back()->GetNextIssuer( 408 cur_path_.back()->GetNextIssuer(&next_issuer_);
553 &next_issuer_, allow_async
554 ? base::Bind(&CertPathIter::HandleGotNextIssuer,
555 base::Unretained(this))
556 : base::Closure());
557 return rv;
558 } 409 }
559 410
560 CompletionStatus CertPathIter::DoGetNextIssuerComplete() { 411 void CertPathIter::DoGetNextIssuerComplete() {
561 // If the issuer is a trust anchor signal readiness. 412 // If the issuer is a trust anchor signal readiness.
562 if (next_issuer_.IsTrustAnchor()) { 413 if (next_issuer_.IsTrustAnchor()) {
563 DVLOG(1) << "CertPathIter got anchor(" 414 DVLOG(1) << "CertPathIter got anchor("
564 << CertDebugString(next_issuer_.anchor->cert().get()); 415 << CertDebugString(next_issuer_.anchor->cert().get());
565 next_state_ = STATE_RETURN_A_PATH; 416 next_state_ = STATE_RETURN_A_PATH;
566 cur_path_.CopyPath(&out_path_->certs); 417 cur_path_.CopyPath(&out_path_->certs);
567 out_path_->trust_anchor = std::move(next_issuer_.anchor); 418 out_path_->trust_anchor = std::move(next_issuer_.anchor);
568 next_issuer_ = CertificateOrTrustAnchor(); 419 next_issuer_ = CertificateOrTrustAnchor();
569 return CompletionStatus::SYNC; 420 return;
570 } 421 }
571 422
572 if (next_issuer_.IsCertificate()) { 423 if (next_issuer_.IsCertificate()) {
573 // Skip this cert if it is already in the chain. 424 // Skip this cert if it is already in the chain.
574 if (cur_path_.IsPresent(next_issuer_.cert.get())) { 425 if (cur_path_.IsPresent(next_issuer_.cert.get())) {
575 next_state_ = STATE_GET_NEXT_ISSUER; 426 next_state_ = STATE_GET_NEXT_ISSUER;
576 return CompletionStatus::SYNC; 427 return;
577 } 428 }
578 429
579 cur_path_.Append(base::MakeUnique<CertIssuersIter>( 430 cur_path_.Append(base::MakeUnique<CertIssuersIter>(
580 std::move(next_issuer_.cert), &cert_issuer_sources_, trust_store_)); 431 std::move(next_issuer_.cert), &cert_issuer_sources_, trust_store_));
581 next_issuer_ = CertificateOrTrustAnchor(); 432 next_issuer_ = CertificateOrTrustAnchor();
582 DVLOG(1) << "CertPathIter cur_path_ = " << cur_path_.PathDebugString(); 433 DVLOG(1) << "CertPathIter cur_path_ = " << cur_path_.PathDebugString();
583 // Continue descending the tree. 434 // Continue descending the tree.
584 next_state_ = STATE_GET_NEXT_ISSUER; 435 next_state_ = STATE_GET_NEXT_ISSUER;
585 } else { 436 } else {
586 // TODO(mattm): should also include such paths in CertPathBuilder::Result, 437 // TODO(mattm): should also include such paths in CertPathBuilder::Result,
587 // maybe with a flag to enable it. Or use a visitor pattern so the caller 438 // maybe with a flag to enable it. Or use a visitor pattern so the caller
588 // can decide what to do with any failed paths. 439 // can decide what to do with any failed paths.
589 // No more issuers for current chain, go back up and see if there are any 440 // No more issuers for current chain, go back up and see if there are any
590 // more for the previous cert. 441 // more for the previous cert.
591 next_state_ = STATE_BACKTRACK; 442 next_state_ = STATE_BACKTRACK;
592 } 443 }
593 return CompletionStatus::SYNC;
594 } 444 }
595 445
596 CompletionStatus CertPathIter::DoBackTrack() { 446 void CertPathIter::DoBackTrack() {
597 DVLOG(1) << "CertPathIter backtracking..."; 447 DVLOG(1) << "CertPathIter backtracking...";
598 cur_path_.Pop(); 448 cur_path_.Pop();
599 if (cur_path_.Empty()) { 449 if (cur_path_.Empty()) {
600 // Exhausted all paths. 450 // Exhausted all paths.
601 next_state_ = STATE_NONE; 451 next_state_ = STATE_NONE;
602 } else { 452 } else {
603 // Continue exploring issuers of the previous path. 453 // Continue exploring issuers of the previous path.
604 next_state_ = STATE_GET_NEXT_ISSUER; 454 next_state_ = STATE_GET_NEXT_ISSUER;
605 } 455 }
606 return CompletionStatus::SYNC;
607 }
608
609 void CertPathIter::HandleGotNextIssuer(void) {
610 DCHECK(!callback_.is_null());
611 CompletionStatus rv = DoLoop(true /* allow_async */);
612 if (rv == CompletionStatus::SYNC) {
613 // Clear the reference to the output parameter as a precaution.
614 out_path_ = nullptr;
615 base::ResetAndReturn(&callback_).Run();
616 }
617 } 456 }
618 457
619 CertPathBuilder::ResultPath::ResultPath() = default; 458 CertPathBuilder::ResultPath::ResultPath() = default;
620 CertPathBuilder::ResultPath::~ResultPath() = default; 459 CertPathBuilder::ResultPath::~ResultPath() = default;
621 CertPathBuilder::Result::Result() = default; 460 CertPathBuilder::Result::Result() = default;
622 CertPathBuilder::Result::~Result() = default; 461 CertPathBuilder::Result::~Result() = default;
623 462
624 const CertPathBuilder::ResultPath* CertPathBuilder::Result::GetBestValidPath() 463 const CertPathBuilder::ResultPath* CertPathBuilder::Result::GetBestValidPath()
625 const { 464 const {
626 DCHECK((paths.empty() && best_result_index == 0) || 465 DCHECK((paths.empty() && best_result_index == 0) ||
(...skipping 24 matching lines...) Expand all
651 next_state_(STATE_NONE), 490 next_state_(STATE_NONE),
652 out_result_(result) {} 491 out_result_(result) {}
653 492
654 CertPathBuilder::~CertPathBuilder() {} 493 CertPathBuilder::~CertPathBuilder() {}
655 494
656 void CertPathBuilder::AddCertIssuerSource( 495 void CertPathBuilder::AddCertIssuerSource(
657 CertIssuerSource* cert_issuer_source) { 496 CertIssuerSource* cert_issuer_source) {
658 cert_path_iter_->AddCertIssuerSource(cert_issuer_source); 497 cert_path_iter_->AddCertIssuerSource(cert_issuer_source);
659 } 498 }
660 499
661 CompletionStatus CertPathBuilder::Run(const base::Closure& callback) { 500 // TODO(eroman): Simplify (doesn't need to use the "DoLoop" pattern).
501 void CertPathBuilder::Run() {
662 DCHECK_EQ(STATE_NONE, next_state_); 502 DCHECK_EQ(STATE_NONE, next_state_);
663 next_state_ = STATE_GET_NEXT_PATH; 503 next_state_ = STATE_GET_NEXT_PATH;
664 CompletionStatus rv = DoLoop(!callback.is_null());
665
666 if (rv == CompletionStatus::ASYNC)
667 callback_ = callback;
668
669 return rv;
670 }
671
672 CompletionStatus CertPathBuilder::DoLoop(bool allow_async) {
673 CompletionStatus result = CompletionStatus::SYNC;
674 504
675 do { 505 do {
676 State state = next_state_; 506 State state = next_state_;
677 next_state_ = STATE_NONE; 507 next_state_ = STATE_NONE;
678 switch (state) { 508 switch (state) {
679 case STATE_NONE: 509 case STATE_NONE:
680 NOTREACHED(); 510 NOTREACHED();
681 break; 511 break;
682 case STATE_GET_NEXT_PATH: 512 case STATE_GET_NEXT_PATH:
683 result = DoGetNextPath(allow_async); 513 DoGetNextPath();
684 break; 514 break;
685 case STATE_GET_NEXT_PATH_COMPLETE: 515 case STATE_GET_NEXT_PATH_COMPLETE:
686 result = DoGetNextPathComplete(); 516 DoGetNextPathComplete();
687 break; 517 break;
688 } 518 }
689 } while (result == CompletionStatus::SYNC && next_state_ != STATE_NONE); 519 } while (next_state_ != STATE_NONE);
690
691 return result;
692 } 520 }
693 521
694 CompletionStatus CertPathBuilder::DoGetNextPath(bool allow_async) { 522 void CertPathBuilder::DoGetNextPath() {
695 next_state_ = STATE_GET_NEXT_PATH_COMPLETE; 523 next_state_ = STATE_GET_NEXT_PATH_COMPLETE;
696 CompletionStatus rv = cert_path_iter_->GetNextPath( 524 cert_path_iter_->GetNextPath(&next_path_);
697 &next_path_, allow_async ? base::Bind(&CertPathBuilder::HandleGotNextPath,
698 base::Unretained(this))
699 : base::Closure());
700 return rv;
701 } 525 }
702 526
703 void CertPathBuilder::HandleGotNextPath() { 527 void CertPathBuilder::DoGetNextPathComplete() {
704 DCHECK(!callback_.is_null());
705 CompletionStatus rv = DoLoop(true /* allow_async */);
706 if (rv == CompletionStatus::SYNC)
707 base::ResetAndReturn(&callback_).Run();
708 }
709
710 CompletionStatus CertPathBuilder::DoGetNextPathComplete() {
711 if (next_path_.IsEmpty()) { 528 if (next_path_.IsEmpty()) {
712 // No more paths to check, signal completion. 529 // No more paths to check, signal completion.
713 next_state_ = STATE_NONE; 530 next_state_ = STATE_NONE;
714 return CompletionStatus::SYNC; 531 return;
715 } 532 }
716 533
717 // Verify the entire certificate chain. 534 // Verify the entire certificate chain.
718 auto result_path = base::MakeUnique<ResultPath>(); 535 auto result_path = base::MakeUnique<ResultPath>();
719 bool verify_result = 536 bool verify_result =
720 VerifyCertificateChain(next_path_.certs, next_path_.trust_anchor.get(), 537 VerifyCertificateChain(next_path_.certs, next_path_.trust_anchor.get(),
721 signature_policy_, time_, &result_path->errors); 538 signature_policy_, time_, &result_path->errors);
722 DVLOG(1) << "CertPathBuilder VerifyCertificateChain result = " 539 DVLOG(1) << "CertPathBuilder VerifyCertificateChain result = "
723 << result_path->valid; 540 << result_path->valid;
724 result_path->path = next_path_; 541 result_path->path = next_path_;
725 result_path->valid = verify_result; 542 result_path->valid = verify_result;
726 AddResultPath(std::move(result_path)); 543 AddResultPath(std::move(result_path));
727 544
728 if (verify_result) { 545 if (verify_result) {
729 // Found a valid path, return immediately. 546 // Found a valid path, return immediately.
730 // TODO(mattm): add debug/test mode that tries all possible paths. 547 // TODO(mattm): add debug/test mode that tries all possible paths.
731 next_state_ = STATE_NONE; 548 next_state_ = STATE_NONE;
732 return CompletionStatus::SYNC; 549 return;
733 } 550 }
734 551
735 // Path did not verify. Try more paths. If there are no more paths, the result 552 // Path did not verify. Try more paths. If there are no more paths, the result
736 // will be returned next time DoGetNextPathComplete is called with next_path_ 553 // will be returned next time DoGetNextPathComplete is called with next_path_
737 // empty. 554 // empty.
738 next_state_ = STATE_GET_NEXT_PATH; 555 next_state_ = STATE_GET_NEXT_PATH;
739 return CompletionStatus::SYNC;
740 } 556 }
741 557
742 void CertPathBuilder::AddResultPath(std::unique_ptr<ResultPath> result_path) { 558 void CertPathBuilder::AddResultPath(std::unique_ptr<ResultPath> result_path) {
743 // TODO(mattm): set best_result_index based on number or severity of errors. 559 // TODO(mattm): set best_result_index based on number or severity of errors.
744 if (result_path->valid) 560 if (result_path->valid)
745 out_result_->best_result_index = out_result_->paths.size(); 561 out_result_->best_result_index = out_result_->paths.size();
746 // TODO(mattm): add flag to only return a single path or all attempted paths? 562 // TODO(mattm): add flag to only return a single path or all attempted paths?
747 out_result_->paths.push_back(std::move(result_path)); 563 out_result_->paths.push_back(std::move(result_path));
748 } 564 }
749 565
750 } // namespace net 566 } // namespace net
OLDNEW
« no previous file with comments | « net/cert/internal/path_builder.h ('k') | net/cert/internal/path_builder_pkits_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698