Index: net/cert/internal/path_builder.cc |
diff --git a/net/cert/internal/path_builder.cc b/net/cert/internal/path_builder.cc |
index 10b507bc594c3849d63aa2af78c35ad8a1c5d08a..26e366410e87bfe4844dfa1715db05400bc9bbeb 100644 |
--- a/net/cert/internal/path_builder.cc |
+++ b/net/cert/internal/path_builder.cc |
@@ -65,11 +65,11 @@ struct CertificateOrTrustAnchor { |
// which may be issuers of |cert|. |
class CertIssuersIter { |
public: |
- // Constructs the CertIssuersIter. |*cert_issuer_sources| must be valid for |
- // the lifetime of the CertIssuersIter. |
+ // Constructs the CertIssuersIter. |*cert_issuer_sources| and |*trust_store| |
+ // must be valid for the lifetime of the CertIssuersIter. |
CertIssuersIter(scoped_refptr<ParsedCertificate> cert, |
CertIssuerSources* cert_issuer_sources, |
- const TrustStore& trust_store); |
+ const TrustStore* trust_store); |
// Gets the next candidate issuer. If an issuer is ready synchronously, SYNC |
// is returned and the cert is stored in |*cert|. If an issuer is not |
@@ -85,10 +85,14 @@ class CertIssuersIter { |
scoped_refptr<ParsedCertificate> reference_cert() const { return cert_; } |
private: |
+ void DoAsyncIssuerQuery(); |
+ void GotAsyncAnchors(TrustAnchors anchors); |
void GotAsyncCerts(CertIssuerSource::Request* request); |
+ void NotifyIfNecessary(); |
scoped_refptr<ParsedCertificate> cert_; |
CertIssuerSources* cert_issuer_sources_; |
+ const TrustStore* trust_store_; |
// The list of trust anchors that match the issuer name for |cert_|. |
TrustAnchors anchors_; |
@@ -112,14 +116,16 @@ class CertIssuersIter { |
// This points to data owned by |issuers_|. |
std::unordered_set<base::StringPiece, base::StringPieceHash> present_issuers_; |
- // Tracks whether asynchronous requests have been made yet. |
- bool did_async_query_ = false; |
+ // Tracks which requests have been made yet. |
+ bool did_initial_query_ = false; |
+ bool did_async_issuer_query_ = false; |
// If asynchronous requests were made, how many of them are still outstanding? |
size_t pending_async_results_; |
// Owns the Request objects for any asynchronous requests so that they will be |
// cancelled if CertIssuersIter is destroyed. |
std::vector<std::unique_ptr<CertIssuerSource::Request>> |
pending_async_requests_; |
+ std::unique_ptr<TrustStore::Request> pending_anchor_request_; |
// When GetNextIssuer was called and returned asynchronously, |*out_| is |
// where the result will be stored, and |callback_| will be run when the |
@@ -132,28 +138,11 @@ class CertIssuersIter { |
CertIssuersIter::CertIssuersIter(scoped_refptr<ParsedCertificate> in_cert, |
CertIssuerSources* cert_issuer_sources, |
- const TrustStore& trust_store) |
- : cert_(in_cert), cert_issuer_sources_(cert_issuer_sources) { |
+ const TrustStore* trust_store) |
+ : cert_(in_cert), |
+ cert_issuer_sources_(cert_issuer_sources), |
+ trust_store_(trust_store) { |
DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) << ") created"; |
- trust_store.FindTrustAnchorsByNormalizedName(in_cert->normalized_issuer(), |
- &anchors_); |
- |
- for (auto* cert_issuer_source : *cert_issuer_sources_) { |
- ParsedCertificateList new_issuers; |
- cert_issuer_source->SyncGetIssuersOf(cert(), &new_issuers); |
- for (scoped_refptr<ParsedCertificate>& issuer : new_issuers) { |
- if (present_issuers_.find(issuer->der_cert().AsStringPiece()) != |
- present_issuers_.end()) |
- continue; |
- present_issuers_.insert(issuer->der_cert().AsStringPiece()); |
- issuers_.push_back(std::move(issuer)); |
- } |
- } |
- // TODO(mattm): sort by notbefore, etc (eg if cert issuer matches a trust |
- // anchor subject (or is a trust anchor), that should be sorted higher too. |
- // See big list of possible sorting hints in RFC 4158.) |
- // (Update PathBuilderKeyRolloverTest.TestRolloverBothRootsTrusted once that |
- // is done) |
} |
CompletionStatus CertIssuersIter::GetNextIssuer(CertificateOrTrustAnchor* out, |
@@ -161,6 +150,35 @@ CompletionStatus CertIssuersIter::GetNextIssuer(CertificateOrTrustAnchor* out, |
// Should not be called again while already waiting for an async result. |
DCHECK(callback_.is_null()); |
+ if (!did_initial_query_) { |
+ did_initial_query_ = true; |
+ trust_store_->FindTrustAnchorsForCert( |
+ cert_.get(), |
+ callback.is_null() ? TrustStore::TrustAnchorsCallback() |
+ : base::Bind(&CertIssuersIter::GotAsyncAnchors, |
+ base::Unretained(this)), |
+ &anchors_, &pending_anchor_request_); |
+ |
+ for (auto* cert_issuer_source : *cert_issuer_sources_) { |
+ ParsedCertificateList new_issuers; |
+ cert_issuer_source->SyncGetIssuersOf(cert(), &new_issuers); |
+ for (scoped_refptr<ParsedCertificate>& issuer : new_issuers) { |
+ if (present_issuers_.find(issuer->der_cert().AsStringPiece()) != |
+ present_issuers_.end()) |
+ continue; |
+ present_issuers_.insert(issuer->der_cert().AsStringPiece()); |
+ issuers_.push_back(std::move(issuer)); |
+ } |
+ } |
+ DVLOG(1) << anchors_.size() << " sync anchors, " << issuers_.size() |
+ << " sync issuers"; |
+ // TODO(mattm): sort by notbefore, etc (eg if cert issuer matches a trust |
+ // anchor subject (or is a trust anchor), that should be sorted higher too. |
+ // See big list of possible sorting hints in RFC 4158.) |
+ // (Update PathBuilderKeyRolloverTest.TestRolloverBothRootsTrusted once that |
+ // is done) |
+ } |
+ |
// Return possible trust anchors first. |
if (cur_anchor_ < anchors_.size()) { |
DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
@@ -171,6 +189,14 @@ CompletionStatus CertIssuersIter::GetNextIssuer(CertificateOrTrustAnchor* out, |
return CompletionStatus::SYNC; |
} |
+ if (pending_anchor_request_) { |
+ DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
+ << ") Still waiting for async trust anchor results."; |
+ out_ = out; |
+ callback_ = callback; |
+ return CompletionStatus::ASYNC; |
+ } |
+ |
if (cur_issuer_ < issuers_.size()) { |
DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
<< "): returning issuer " << cur_issuer_ << " of " |
@@ -181,7 +207,8 @@ CompletionStatus CertIssuersIter::GetNextIssuer(CertificateOrTrustAnchor* out, |
*out = CertificateOrTrustAnchor(issuers_[cur_issuer_++]); |
return CompletionStatus::SYNC; |
} |
- if (did_async_query_) { |
+ |
+ if (did_async_issuer_query_) { |
if (pending_async_results_ == 0) { |
DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
<< ") Reached the end of all available issuers."; |
@@ -207,7 +234,27 @@ CompletionStatus CertIssuersIter::GetNextIssuer(CertificateOrTrustAnchor* out, |
} |
// Now issue request(s) for async ones (AIA, etc). |
- did_async_query_ = true; |
+ DoAsyncIssuerQuery(); |
+ |
+ if (pending_async_results_ == 0) { |
+ DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
+ << ") No cert sources have async results."; |
+ // No cert sources have async results. |
+ *out = CertificateOrTrustAnchor(); |
+ return CompletionStatus::SYNC; |
+ } |
+ |
+ DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
+ << ") issued AsyncGetIssuersOf call(s) (n=" << pending_async_results_ |
+ << ")"; |
+ out_ = out; |
+ callback_ = callback; |
+ return CompletionStatus::ASYNC; |
+} |
+ |
+void CertIssuersIter::DoAsyncIssuerQuery() { |
+ DCHECK(!did_async_issuer_query_); |
+ did_async_issuer_query_ = true; |
pending_async_results_ = 0; |
for (auto* cert_issuer_source : *cert_issuer_sources_) { |
std::unique_ptr<CertIssuerSource::Request> request; |
@@ -222,21 +269,16 @@ CompletionStatus CertIssuersIter::GetNextIssuer(CertificateOrTrustAnchor* out, |
pending_async_requests_.push_back(std::move(request)); |
} |
} |
+} |
- if (pending_async_results_ == 0) { |
- DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
- << ") No cert sources have async results."; |
- // No cert sources have async results. |
- *out = CertificateOrTrustAnchor(); |
- return CompletionStatus::SYNC; |
- } |
+void CertIssuersIter::GotAsyncAnchors(TrustAnchors anchors) { |
+ DVLOG(1) << "CertIssuersIter::GotAsyncAnchors(" << CertDebugString(cert()) |
+ << "): " << anchors.size() << " anchors"; |
+ for (scoped_refptr<TrustAnchor>& anchor : anchors) |
+ anchors_.push_back(std::move(anchor)); |
+ pending_anchor_request_.reset(); |
- DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
- << ") issued AsyncGetIssuersOf call(s) (n=" << pending_async_results_ |
- << ")"; |
- out_ = out; |
- callback_ = callback; |
- return CompletionStatus::ASYNC; |
+ NotifyIfNecessary(); |
} |
void CertIssuersIter::GotAsyncCerts(CertIssuerSource::Request* request) { |
@@ -265,25 +307,43 @@ void CertIssuersIter::GotAsyncCerts(CertIssuerSource::Request* request) { |
// TODO(mattm): re-sort remaining elements of issuers_ (remaining elements may |
// be more than the ones just inserted, depending on |cur_| value). |
+ NotifyIfNecessary(); |
+} |
+ |
+void CertIssuersIter::NotifyIfNecessary() { |
// Notify that more results are available, if necessary. |
if (!callback_.is_null()) { |
- DCHECK_GE(cur_anchor_, anchors_.size()); |
+ if (cur_anchor_ < anchors_.size()) { |
+ DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
+ << "): async returning anchor " << cur_anchor_ << " of " |
+ << anchors_.size(); |
+ *out_ = CertificateOrTrustAnchor(std::move(anchors_[cur_anchor_++])); |
+ base::ResetAndReturn(&callback_).Run(); |
+ return; |
+ } |
if (cur_issuer_ < issuers_.size()) { |
+ DCHECK(!pending_anchor_request_); |
DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
- << "): async returning item " << cur_issuer_ << " of " |
+ << "): async returning issuer " << cur_issuer_ << " of " |
<< issuers_.size(); |
*out_ = CertificateOrTrustAnchor(std::move(issuers_[cur_issuer_++])); |
base::ResetAndReturn(&callback_).Run(); |
- } else if (pending_async_results_ == 0) { |
+ return; |
+ } |
+ |
+ if (!did_async_issuer_query_) |
+ DoAsyncIssuerQuery(); |
+ |
+ if (pending_async_results_ == 0) { |
DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
<< "): async returning empty result"; |
*out_ = CertificateOrTrustAnchor(); |
base::ResetAndReturn(&callback_).Run(); |
- } else { |
- DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
- << "): empty result, but other async results " |
- "pending, waiting.."; |
+ return; |
} |
+ DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
+ << "): empty result, but other async results " |
+ "pending, waiting.."; |
} |
} |
@@ -517,7 +577,7 @@ CompletionStatus CertPathIter::DoGetNextIssuerComplete() { |
} |
cur_path_.Append(base::WrapUnique(new CertIssuersIter( |
- std::move(next_issuer_.cert), &cert_issuer_sources_, *trust_store_))); |
+ std::move(next_issuer_.cert), &cert_issuer_sources_, trust_store_))); |
next_issuer_ = CertificateOrTrustAnchor(); |
DVLOG(1) << "CertPathIter cur_path_ = " << cur_path_.PathDebugString(); |
// Continue descending the tree. |