OLD | NEW |
---|---|
(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/path_builder.h" | |
6 | |
7 #include <unordered_set> | |
8 | |
9 #include "base/callback_helpers.h" | |
10 #include "base/memory/ptr_util.h" | |
11 #include "net/base/net_errors.h" | |
12 #include "net/cert/internal/parse_certificate.h" | |
13 #include "net/cert/internal/parse_name.h" // XXX for DumpPath. Remove. | |
14 #include "net/cert/internal/verify_name_match.h" | |
15 #include "net/der/parser.h" | |
16 #include "net/der/tag.h" | |
17 | |
18 namespace net { | |
19 | |
20 namespace { | |
21 | |
22 // LoopChecker tracks which certs are present in the path and prevents paths | |
23 // from being built which repeat any certs. | |
24 class LoopChecker { | |
25 public: | |
26 // Attempts to add |cert| to the list of certs to check. If it has not already | |
27 // been added, true is returned and |cert| is added, such that any future | |
28 // attempts will return false. | |
29 // The |cert| data is not copied, Remove must be called before the |cert| data | |
30 // is destroyed. | |
31 bool Insert(const CertThing& cert) { | |
32 if (present_certs_.find(cert.der_cert().AsStringPiece()) != | |
33 present_certs_.end()) | |
34 return false; | |
35 present_certs_.insert(cert.der_cert().AsStringPiece()); | |
36 return true; | |
37 } | |
38 // Removes a cert from being disallowed. | |
39 void Remove(const CertThing& cert) { | |
40 present_certs_.erase(cert.der_cert().AsStringPiece()); | |
41 } | |
42 | |
43 private: | |
44 // TODO: this should be keyed on Name+SAN+SPKI. (Update | |
45 // PathBuilderKeyRolloverTest.TestRolloverLongChain once that is done) | |
46 std::unordered_set<base::StringPiece, base::StringPieceHash> present_certs_; | |
47 }; | |
48 | |
49 // CertIssuersIter iterates through the intermediates from |cert_sources| which | |
50 // may be issuers of |cert|. | |
51 // TODO: It should return the issuers in order most likely to succeed. | |
52 class CertIssuersIter { | |
53 public: | |
54 // Constructs the CertIssuersIter. Takes ownership of |cert|. |*cert_sources| | |
55 // must be valid for the lifetime of the CertIssuersIter. | |
56 CertIssuersIter(std::unique_ptr<CertThing> cert, | |
57 CertPathBuilder::CertSources* cert_sources); | |
58 | |
59 // Gets the next candidate issuer for |cert_|. If one is not ready | |
60 // synchronously, the return value ERR_IO_PENDING is returned and |callback| | |
61 // will be called once an issuer is ready. | |
62 // In either case, the next issuer will be set in |*out_cert|, or if there are | |
63 // no | |
64 // more issuers available, |*out_cert| will be cleared. | |
65 // and it will have been stored in |*out_cert| | |
66 // it. If an issuer is ready, OK is returned and the cert is stored in | |
67 // |*out_cert|. | |
68 // If all issuers have been exhausted, OK is returned and |*out_cert| is | |
69 // cleared. | |
70 int GetNextIssuer(std::unique_ptr<CertThing>* out_cert, | |
71 const base::Closure& callback); | |
72 | |
73 // Returns the |cert| for which issuers are being retrieved. | |
74 const CertThing& cert() const { return *cert_; } | |
75 | |
76 private: | |
77 void GotAsyncCerts(CertVector certs); | |
78 | |
79 std::unique_ptr<CertThing> cert_; | |
80 CertPathBuilder::CertSources* cert_sources_; | |
81 | |
82 // The list of issuers for |cert_|. This is added to incrementally (first | |
83 // synchronous, results, then possibly multiple times as asynchronous results | |
84 // arrive.) The issuers may be re-sorted each time new issuers are added, but | |
85 // only the results from |cur_| onwards should be sorted, since the earlier | |
86 // results were already returned. | |
87 CertVector issuers_; | |
88 // The index of the next cert in |issuers_| to return. | |
89 size_t cur_ = 0; | |
90 | |
91 // Tracks whether asynchronous requests have been made yet. | |
92 bool did_async_query_ = false; | |
93 // If asynchronous requests were made, how many of them are still outstanding? | |
94 int pending_async_results_; | |
95 // Owns the Request objects for any asynchronous requests so that they will be | |
96 // cancelled if CertIssuersIter is destroyed. | |
97 std::vector<std::unique_ptr<CertSource::Request>> pending_async_requests_; | |
98 | |
99 // When GetNextIssuer was called and returned asynchronously, |out_cert_| is | |
100 // where the result will be stored, and |callback_| will be run when the | |
101 // result is ready. | |
102 std::unique_ptr<CertThing>* out_cert_; | |
103 base::Closure callback_; | |
104 | |
105 DISALLOW_COPY_AND_ASSIGN(CertIssuersIter); | |
106 }; | |
107 | |
108 CertIssuersIter::CertIssuersIter(std::unique_ptr<CertThing> in_cert, | |
109 CertPathBuilder::CertSources* cert_sources) | |
110 : cert_(std::move(in_cert)), cert_sources_(cert_sources) { | |
111 for (auto* cert_source : *cert_sources_) { | |
112 if (!cert_source->SyncGetIssuersOf(cert(), &issuers_)) | |
113 LOG(ERROR) << "SyncGetIssuersOf error"; // XXX what to do with errors | |
114 // here? Change SyncGetIssuersOf | |
115 // to never fail now that it | |
116 // doesn't do parsing? | |
117 } | |
118 // TODO: sort by notbefore, etc (eg if cert issuer matches a trust anchor | |
119 // subject, that should be sorted higher too. See big list of possible sorting | |
120 // hints in RFC 4158.) | |
121 // (Update PathBuilderKeyRolloverTest.TestRolloverBothRootsTrusted once that | |
122 // is done) | |
123 } | |
124 | |
125 int CertIssuersIter::GetNextIssuer(std::unique_ptr<CertThing>* out_cert, | |
126 const base::Closure& callback) { | |
127 // Should not be called again while already waiting for an async result. | |
128 DCHECK(callback_.is_null()); | |
129 | |
130 if (cur_ < issuers_.size()) { | |
131 DVLOG(1) << "CertIssuersIter: returning item " << cur_ << " of " | |
132 << issuers_.size(); | |
133 // Still have issuers that haven't been returned yet, return one of them. | |
134 *out_cert = std::move(issuers_[cur_++]); | |
135 return OK; | |
136 } | |
137 if (did_async_query_) { | |
138 if (pending_async_results_ == 0) { | |
139 DVLOG(1) << "CertIssuersIter Reached the end of all available issuers."; | |
140 // Reached the end of all available issuers. | |
141 out_cert->reset(); | |
142 return OK; | |
143 } | |
144 | |
145 DVLOG(1) << "CertIssuersIter Still waiting for async results from other " | |
146 "CertSources."; | |
147 // Still waiting for async results from other CertSources. | |
148 out_cert_ = out_cert; | |
149 callback_ = callback; | |
150 return ERR_IO_PENDING; | |
151 } | |
152 | |
153 // Reached the end of synchronously gathered issuers, now issue request(s) for | |
154 // async ones (AIA, etc). | |
155 | |
156 did_async_query_ = true; | |
157 pending_async_results_ = 0; | |
158 for (auto* cert_source : *cert_sources_) { | |
159 std::unique_ptr<CertSource::Request> request; | |
160 int rv = cert_source->AsyncGetIssuersOf( | |
161 cert(), | |
162 base::Bind(&CertIssuersIter::GotAsyncCerts, base::Unretained(this)), | |
163 &request); | |
164 DVLOG(1) << "AsyncGetIssuersOf v=" << rv; | |
165 // XXX any other error handling here? | |
166 if (rv == ERR_IO_PENDING) | |
167 pending_async_results_++; | |
168 if (request) | |
169 pending_async_requests_.push_back(std::move(request)); | |
170 } | |
171 | |
172 if (pending_async_results_ == 0) { | |
173 DVLOG(1) << "CertIssuersIter No cert sources have async results."; | |
174 // No cert sources have async results. | |
175 out_cert->reset(); | |
176 return OK; | |
177 } | |
178 | |
179 DVLOG(1) << "CertIssuersIter issued AsyncGetIssuersOf call(s) (n=" | |
180 << pending_async_results_ << ")"; | |
181 out_cert_ = out_cert; | |
182 callback_ = callback; | |
183 return ERR_IO_PENDING; | |
184 } | |
185 | |
186 void CertIssuersIter::GotAsyncCerts(CertVector certs) { | |
187 DVLOG(1) << "CertIssuersIter::GotAsyncCerts n=" << certs.size(); | |
188 pending_async_results_--; | |
189 for (auto& c : certs) | |
190 issuers_.push_back(std::move(c)); | |
191 | |
192 // TODO: re-sort remaining elements of issuers_ (remaining elements may be | |
193 // more than the ones just inserted, depending on |cur_| value). | |
194 | |
195 // Notify that more results are available, if necessary. | |
196 if (!callback_.is_null()) { | |
197 if (cur_ < issuers_.size()) { | |
198 DVLOG(1) << "CertIssuersIter: async returning item " << cur_ << " of " | |
199 << issuers_.size(); | |
200 *out_cert_ = std::move(issuers_[cur_++]); | |
201 base::ResetAndReturn(&callback_).Run(); | |
202 } else if (pending_async_results_ == 0) { | |
203 DVLOG(1) << "CertIssuersIter: async returning empty result"; | |
204 out_cert_->reset(); | |
205 base::ResetAndReturn(&callback_).Run(); | |
206 } else { | |
207 DVLOG(1) << "CertIssuersIter: empty result, but other async results " | |
208 "pending, waiting.."; | |
209 } | |
210 } | |
211 } | |
212 | |
213 } // namespace | |
214 | |
215 StaticCertsSource::StaticCertsSource() {} | |
216 StaticCertsSource::~StaticCertsSource() {} | |
217 | |
218 bool StaticCertsSource::Init(std::vector<der::Input> certs) { | |
219 for (auto cert_der : certs) { | |
220 std::unique_ptr<CertThing> cert(CertThing::CreateFromCertificateData( | |
221 cert_der.UnsafeData(), cert_der.Length(), | |
222 CertThing::DataSource::EXTERNAL_REFERENCE)); | |
223 if (!cert) | |
224 return false; | |
225 intermediates_.insert( | |
226 std::make_pair(cert->normalized_subject(), std::move(cert))); | |
227 } | |
228 return true; | |
229 } | |
230 | |
231 bool StaticCertsSource::SyncGetIssuersOf(const CertThing& cert, | |
232 CertVector* issuers) { | |
233 auto range = intermediates_.equal_range(cert.normalized_issuer()); | |
234 for (auto it = range.first; it != range.second; ++it) | |
235 issuers->push_back(it->second->Clone()); | |
236 return true; | |
237 } | |
238 | |
239 int StaticCertsSource::AsyncGetIssuersOf(const CertThing& cert, | |
240 const IssuerCallback& issuers_callback, | |
241 std::unique_ptr<Request>* out_req) { | |
242 // StaticCertsSource never returns asynchronous results. | |
243 return OK; | |
244 } | |
245 | |
246 // CertPathIter generates possible paths from |cert| to a trust anchor in | |
247 // |trust_store|, using intermediates from |cert_sources| if necessary. | |
248 class CertPathIter { | |
249 public: | |
250 CertPathIter(std::unique_ptr<CertThing> cert, | |
251 const CertPathBuilder::CertSources& cert_sources, | |
252 const TrustStore& trust_store); | |
253 | |
254 // Gets the next candidate path. If a path is ready synchronously, OK is | |
255 // returned and the path is stored in |*path|. If a path is not ready, | |
256 // ERR_IO_PENDING is returned and |async_ready_callback| will be called once | |
257 // |*path| has been set. | |
258 // In either case, if all paths have been exhausted, OK result is returned and | |
259 // |*path| is cleared. | |
260 // The cert data referred to in |*path| is only valid until the next | |
261 // GetNextPath call or until the CertPathIter is destroyed. | |
262 int GetNextPath(CertVector* path, const CompletionCallback& callback); | |
263 | |
264 private: | |
265 enum State { | |
266 STATE_NONE, | |
267 STATE_GET_NEXT_ISSUER, | |
268 STATE_GET_NEXT_ISSUER_COMPLETE, | |
269 STATE_RETURN_A_PATH, | |
270 }; | |
271 | |
272 bool IsIssuerTrusted(const CertThing& cert) const; | |
273 | |
274 int DoLoop(); | |
275 | |
276 int DoGetNextIssuer(); | |
277 int DoGetNextIssuerComplete(); | |
278 | |
279 void HandleGotNextIssuer(void); | |
280 | |
281 LoopChecker loop_checker_; | |
282 std::unique_ptr<CertThing> next_cert_; | |
283 std::vector<std::unique_ptr<CertIssuersIter>> cur_path_; | |
284 CertPathBuilder::CertSources cert_sources_; | |
285 const TrustStore& trust_store_; | |
286 CertVector* out_path_; | |
287 CompletionCallback callback_; | |
288 State next_state_; | |
289 | |
290 DISALLOW_COPY_AND_ASSIGN(CertPathIter); | |
291 }; | |
292 | |
293 CertPathIter::CertPathIter(std::unique_ptr<CertThing> cert, | |
294 const CertPathBuilder::CertSources& cert_sources, | |
295 const TrustStore& trust_store) | |
296 : next_cert_(std::move(cert)), | |
297 cert_sources_(cert_sources), | |
298 trust_store_(trust_store), | |
299 next_state_(STATE_GET_NEXT_ISSUER_COMPLETE) {} | |
300 | |
301 int CertPathIter::GetNextPath(CertVector* path, | |
302 const CompletionCallback& callback) { | |
303 out_path_ = path; | |
304 out_path_->clear(); | |
305 int rv = DoLoop(); | |
306 if (rv == ERR_IO_PENDING) | |
307 callback_ = callback; | |
308 return rv; | |
309 } | |
310 | |
311 bool CertPathIter::IsIssuerTrusted(const CertThing& cert) const { | |
312 // XXX make trust store do pre-normalization for searching | |
313 return !trust_store_ | |
314 .FindTrustAnchorsByNormalizedName(cert.normalized_issuer()) | |
315 .empty(); | |
316 } | |
317 | |
318 int CertPathIter::DoLoop() { | |
319 int result; | |
320 do { | |
321 State state = next_state_; | |
322 next_state_ = STATE_NONE; | |
323 switch (state) { | |
324 case STATE_NONE: | |
325 NOTREACHED(); | |
326 break; | |
327 case STATE_GET_NEXT_ISSUER: | |
328 result = DoGetNextIssuer(); | |
329 break; | |
330 case STATE_GET_NEXT_ISSUER_COMPLETE: | |
331 result = DoGetNextIssuerComplete(); | |
332 break; | |
333 case STATE_RETURN_A_PATH: | |
334 next_state_ = STATE_GET_NEXT_ISSUER; | |
335 break; | |
336 } | |
337 } while (result != ERR_IO_PENDING && next_state_ != STATE_NONE && | |
338 next_state_ != STATE_RETURN_A_PATH); | |
339 | |
340 return result; | |
341 } | |
342 | |
343 int CertPathIter::DoGetNextIssuer() { | |
344 next_state_ = STATE_GET_NEXT_ISSUER_COMPLETE; | |
345 int rv = cur_path_.back()->GetNextIssuer( | |
346 &next_cert_, | |
347 base::Bind(&CertPathIter::HandleGotNextIssuer, base::Unretained(this))); | |
348 return rv; | |
349 } | |
350 | |
351 std::string DumpPath( | |
352 const std::vector<std::unique_ptr<CertIssuersIter>>& cur_path) { | |
353 std::string s; | |
354 for (const auto& node : cur_path) { | |
355 const CertThing& cert = node->cert(); | |
356 | |
357 RDNSequence subject, issuer; | |
358 if (!ParseName(cert.parsed_tbs().subject_tlv, &subject)) | |
359 return std::string(); | |
360 if (!ParseName(cert.parsed_tbs().issuer_tlv, &issuer)) | |
361 return std::string(); | |
362 | |
363 std::string subject_str, issuer_str; | |
364 | |
365 if (!ConvertToRFC2253(subject, &subject_str)) | |
366 return std::string(); | |
367 if (!ConvertToRFC2253(issuer, &issuer_str)) | |
368 return std::string(); | |
369 if (!s.empty()) | |
370 s += " -> "; | |
371 s += subject_str + "(" + issuer_str + ")"; | |
372 } | |
373 return s; | |
374 } | |
375 | |
376 // Should we include trust anchors as a CertSource, or handle them separately? | |
377 // | |
378 // Pros/cons for handling them as a CertSource: | |
379 // + CertPathIter will automatically try each one as a separate path | |
380 // ? Could this cause LoopChecker issues? (preventing finding a trust anchor if | |
381 // it has same Name+SAN+SPKI as the last cert in chain. Or would there always be | |
382 // a better path by just removing that last cert and going directly to the trust | |
383 // anchor?) | |
384 // - Need special logic to not try to descend past a trust anchor (No reason | |
385 // to). | |
386 // - CertIssuersIter would need prioritization logic to put trust anchors first. | |
387 // + Automatically handles the case where the trust anchor is the end-entity. | |
388 // (Do we care about that?) | |
389 // | |
390 // Not as a Certsource, but Loop through trust anchors separately in | |
391 // CertPathIter: | |
392 // - requires another layer of logic to return the sequence of paths. bleh. | |
393 // | |
394 // Loop through trust anchors separately in CertPathBuilder: | |
395 // + pretty straightforward | |
396 // + doesn't require any special cases in CertPathIter for handling anchors. | |
397 // ? maybe requires little extra work to make a separate path/result for each? | |
398 // ? may want to sort/prioritize the anchors before trying them - but could | |
399 // probably re-use whatever sort function CertIssuersIter uses. | |
400 // - need to check TrustStore twice, unless CertPathIter returns the list of | |
401 // matching anchors. | |
402 // - means we can't just return a const-reference to the cur_path_, instead have | |
403 // to clone all the entries a new CertVector, since the CertPathBuilder will | |
404 // need to append the trust anchor to it. | |
405 // | |
406 // Conclusion: Loop through trust anchors separately in CertPathBuilder looks | |
407 // nice, except for having to clone the entries.. | |
408 | |
409 int CertPathIter::DoGetNextIssuerComplete() { | |
410 if (next_cert_) { | |
411 // Skip this cert if it is already in the chain. | |
412 if (!loop_checker_.Insert(*next_cert_)) { | |
413 next_state_ = STATE_GET_NEXT_ISSUER; | |
414 return OK; | |
415 } | |
416 // Note that loop_checker_.Insert does not make a copy of the cert data. | |
417 // Must call loop_checker_.Remove before destroying the cert data. | |
418 | |
419 cur_path_.push_back(base::WrapUnique( | |
420 new CertIssuersIter(std::move(next_cert_), &cert_sources_))); | |
421 next_cert_.reset(); | |
422 DVLOG(1) << "CertPathIter cur_path_ = " << DumpPath(cur_path_); | |
423 // If the issuer of the cert matches a trust root, this is a (possible) | |
424 // // complete path. Signal readiness. | |
425 // Note that if this path does not verify, further subpaths will still | |
426 // be checked. This is needed to handle cases like key rollover. | |
427 if (IsIssuerTrusted(cur_path_.back()->cert())) { | |
428 DVLOG(1) << "CertPathIter IsIssuerTrusted = true"; | |
429 next_state_ = STATE_RETURN_A_PATH; | |
430 for (const auto& node : cur_path_) | |
431 out_path_->push_back(node->cert().Clone()); // XXX see if we can clone | |
432 // without copying? Or just | |
433 // return a ref/pointer to | |
434 // the out_path_? | |
435 return OK; | |
436 } | |
437 // Continue descending the tree. | |
438 next_state_ = STATE_GET_NEXT_ISSUER; | |
439 } else { | |
440 DVLOG(1) << "CertPathIter backtracking..."; | |
441 // XXX should also include such paths in CertPathBuilder::Result? | |
442 // No more issuers for current chain, go back up and see if there are any | |
443 // more for the previous cert. | |
444 loop_checker_.Remove(cur_path_.back()->cert()); | |
445 cur_path_.pop_back(); | |
446 if (cur_path_.empty()) { | |
447 // Exhausted all paths. | |
448 next_state_ = STATE_NONE; | |
449 } else { | |
450 next_state_ = STATE_GET_NEXT_ISSUER; | |
451 } | |
452 } | |
453 return OK; | |
454 } | |
455 | |
456 void CertPathIter::HandleGotNextIssuer(void) { | |
457 DCHECK(!callback_.is_null()); | |
458 int rv = DoLoop(); | |
459 if (rv != ERR_IO_PENDING) | |
460 base::ResetAndReturn(&callback_).Run(rv); | |
461 } | |
462 | |
463 CertPathBuilder::ResultPath::ResultPath() {} | |
464 CertPathBuilder::ResultPath::~ResultPath() {} | |
465 CertPathBuilder::Result::Result() {} | |
466 CertPathBuilder::Result::~Result() {} | |
467 | |
468 CertPathBuilder::CertPathBuilder(std::unique_ptr<CertThing> cert, | |
469 const CertSources& cert_sources, | |
470 const TrustStore& trust_store, | |
471 const SignaturePolicy* signature_policy, | |
472 const der::GeneralizedTime& time, | |
473 Result* result) | |
474 : cert_path_iter_( | |
475 new CertPathIter(std::move(cert), cert_sources, trust_store)), | |
476 trust_store_(trust_store), | |
477 signature_policy_(signature_policy), | |
478 time_(time), | |
479 next_state_(STATE_NONE), | |
480 out_result_(result) {} | |
481 | |
482 CertPathBuilder::~CertPathBuilder() {} | |
483 | |
484 int CertPathBuilder::Run(const CompletionCallback& callback) { | |
485 DCHECK_EQ(STATE_NONE, next_state_); | |
486 next_state_ = STATE_GET_NEXT_PATH; | |
487 int rv = DoLoop(OK); | |
488 | |
489 if (rv == ERR_IO_PENDING) | |
490 callback_ = callback; | |
491 | |
492 return rv; | |
493 } | |
494 | |
495 int CertPathBuilder::DoLoop(int result) { | |
496 do { | |
497 State state = next_state_; | |
498 next_state_ = STATE_NONE; | |
499 switch (state) { | |
500 case STATE_NONE: | |
501 NOTREACHED(); | |
502 break; | |
503 case STATE_GET_NEXT_PATH: | |
504 DCHECK_EQ(OK, result); | |
505 result = DoGetNextPath(); | |
506 break; | |
507 case STATE_GET_NEXT_PATH_COMPLETE: | |
508 result = DoGetNextPathComplete(result); | |
509 break; | |
510 } | |
511 } while (result != ERR_IO_PENDING && next_state_ != STATE_NONE); | |
512 | |
513 return result; | |
514 } | |
515 | |
516 int CertPathBuilder::DoGetNextPath() { | |
517 next_state_ = STATE_GET_NEXT_PATH_COMPLETE; | |
518 int rv = cert_path_iter_->GetNextPath( | |
519 &next_path_, | |
520 base::Bind(&CertPathBuilder::HandleGotNextPath, base::Unretained(this))); | |
521 return rv; | |
522 } | |
523 | |
524 void CertPathBuilder::HandleGotNextPath(int result) { | |
525 DCHECK(!callback_.is_null()); | |
526 int rv = DoLoop(result); | |
527 if (rv != ERR_IO_PENDING) | |
528 base::ResetAndReturn(&callback_).Run(rv); | |
529 } | |
530 | |
531 int CertPathBuilder::DoGetNextPathComplete(int result) { | |
532 if (next_path_.empty()) { | |
533 // No more paths to check, cert failed to verify. Return the result code for | |
534 // the best path that was found. | |
535 next_state_ = STATE_NONE; | |
536 return out_result_->result(); | |
537 } | |
538 | |
539 std::vector<const CertThing*> matching_anchors( | |
540 trust_store_.FindTrustAnchorsByNormalizedName( | |
541 next_path_.back()->normalized_issuer())); | |
542 // TODO: sort/prioritize matching_anchors | |
543 | |
544 for (auto& trust_anchor : matching_anchors) { | |
eroman
2016/04/26 22:10:10
How does this work when the target cert being veri
mattm
2016/04/26 22:54:16
Yeah, that would be an issue with this approach.
| |
545 // CertVector full_path(next_path_); | |
546 // full_path.push_back(trust_anchor->cert()); | |
547 | |
548 next_path_.push_back(trust_anchor->Clone()); | |
549 bool verify_result = VerifyCertificateChainAssumingTrustedRoot( | |
550 next_path_, trust_store_, signature_policy_, time_); | |
551 DVLOG(1) << "CertPathBuilder VerifyCertificateChain result = " | |
552 << verify_result; | |
553 AddResultPath(next_path_, verify_result); | |
554 next_path_.pop_back(); | |
eroman
2016/04/26 22:10:10
Here it looks to be popping the trust anchor out o
mattm
2016/04/26 22:54:16
AddResultPath makes a copy of the path which is wh
| |
555 | |
556 if (verify_result) { | |
557 // Found a valid path, return immediately. | |
558 // XXX add debug/test mode that tries all possible paths. | |
559 next_state_ = STATE_NONE; | |
560 return out_result_->result(); | |
561 } | |
562 } | |
563 // Path did not verify. Try more paths. If there are no more paths, the result | |
564 // will be returned next time DoGetNextPathComplete is called with next_path_ | |
565 // empty. | |
566 next_state_ = STATE_GET_NEXT_PATH; | |
567 return OK; | |
568 } | |
569 | |
570 void CertPathBuilder::AddResultPath(const CertVector& path, bool result) { | |
571 std::unique_ptr<ResultPath> rp(new ResultPath()); | |
572 // XXX do better error mapping from VerifyCertificateChain results | |
573 rp->rv = result ? OK : ERR_CERT_AUTHORITY_INVALID; | |
574 // XXX set best_path_ if #errors(this) < #errors(best): | |
575 if (rp->rv == OK) | |
576 out_result_->best_result_index = out_result_->paths.size(); | |
577 // XXX only return a single path except in debug/test mode. | |
578 for (const auto& cert : path) | |
579 rp->path.push_back(cert->Clone()); | |
580 out_result_->paths.push_back(std::move(rp)); | |
581 } | |
582 | |
583 } // namespace net | |
OLD | NEW |