OLD | NEW |
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" | 10 #include "base/callback_helpers.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 bool IsEmpty() const { return !IsTrustAnchor() && !IsCertificate(); } | 58 bool IsEmpty() const { return !IsTrustAnchor() && !IsCertificate(); } |
59 | 59 |
60 scoped_refptr<ParsedCertificate> cert; | 60 scoped_refptr<ParsedCertificate> cert; |
61 scoped_refptr<TrustAnchor> anchor; | 61 scoped_refptr<TrustAnchor> anchor; |
62 }; | 62 }; |
63 | 63 |
64 // CertIssuersIter iterates through the intermediates from |cert_issuer_sources| | 64 // CertIssuersIter iterates through the intermediates from |cert_issuer_sources| |
65 // which may be issuers of |cert|. | 65 // which may be issuers of |cert|. |
66 class CertIssuersIter { | 66 class CertIssuersIter { |
67 public: | 67 public: |
68 // Constructs the CertIssuersIter. |*cert_issuer_sources| must be valid for | 68 // Constructs the CertIssuersIter. |*cert_issuer_sources| and |*trust_store| |
69 // the lifetime of the CertIssuersIter. | 69 // must be valid for the lifetime of the CertIssuersIter. |
70 CertIssuersIter(scoped_refptr<ParsedCertificate> cert, | 70 CertIssuersIter(scoped_refptr<ParsedCertificate> cert, |
71 CertIssuerSources* cert_issuer_sources, | 71 CertIssuerSources* cert_issuer_sources, |
72 const TrustStore& trust_store); | 72 const TrustStore* trust_store); |
73 | 73 |
74 // Gets the next candidate issuer. If an issuer is ready synchronously, SYNC | 74 // Gets the next candidate issuer. If an issuer is ready synchronously, SYNC |
75 // is returned and the cert is stored in |*cert|. If an issuer is not | 75 // is returned and the cert is stored in |*cert|. If an issuer is not |
76 // ready, ASYNC is returned and |callback| will be called once |*out_cert| has | 76 // ready, ASYNC is returned and |callback| will be called once |*out_cert| has |
77 // been set. If |callback| is null, always completes synchronously. | 77 // been set. If |callback| is null, always completes synchronously. |
78 // | 78 // |
79 // In either case, if all issuers have been exhausted, |*out| is cleared. | 79 // In either case, if all issuers have been exhausted, |*out| is cleared. |
80 CompletionStatus GetNextIssuer(CertificateOrTrustAnchor* out, | 80 CompletionStatus GetNextIssuer(CertificateOrTrustAnchor* out, |
81 const base::Closure& callback); | 81 const base::Closure& callback); |
82 | 82 |
83 // Returns the |cert| for which issuers are being retrieved. | 83 // Returns the |cert| for which issuers are being retrieved. |
84 const ParsedCertificate* cert() const { return cert_.get(); } | 84 const ParsedCertificate* cert() const { return cert_.get(); } |
85 scoped_refptr<ParsedCertificate> reference_cert() const { return cert_; } | 85 scoped_refptr<ParsedCertificate> reference_cert() const { return cert_; } |
86 | 86 |
87 private: | 87 private: |
| 88 void DoAsyncIssuerQuery(); |
| 89 void GotAsyncAnchors(TrustAnchors anchors); |
88 void GotAsyncCerts(CertIssuerSource::Request* request); | 90 void GotAsyncCerts(CertIssuerSource::Request* request); |
| 91 void NotifyIfNecessary(); |
89 | 92 |
90 scoped_refptr<ParsedCertificate> cert_; | 93 scoped_refptr<ParsedCertificate> cert_; |
91 CertIssuerSources* cert_issuer_sources_; | 94 CertIssuerSources* cert_issuer_sources_; |
| 95 const TrustStore* trust_store_; |
92 | 96 |
93 // The list of trust anchors that match the issuer name for |cert_|. | 97 // The list of trust anchors that match the issuer name for |cert_|. |
94 TrustAnchors anchors_; | 98 TrustAnchors anchors_; |
95 // The index of the next trust anchor in |anchors_| to return. | 99 // The index of the next trust anchor in |anchors_| to return. |
96 size_t cur_anchor_ = 0; | 100 size_t cur_anchor_ = 0; |
97 | 101 |
98 // The list of issuers for |cert_|. This is added to incrementally (first | 102 // The list of issuers for |cert_|. This is added to incrementally (first |
99 // synchronous results, then possibly multiple times as asynchronous results | 103 // synchronous results, then possibly multiple times as asynchronous results |
100 // arrive.) The issuers may be re-sorted each time new issuers are added, but | 104 // arrive.) The issuers may be re-sorted each time new issuers are added, but |
101 // only the results from |cur_| onwards should be sorted, since the earlier | 105 // only the results from |cur_| onwards should be sorted, since the earlier |
102 // results were already returned. | 106 // results were already returned. |
103 // Elements should not be removed from |issuers_| once added, since | 107 // Elements should not be removed from |issuers_| once added, since |
104 // |present_issuers_| will point to data owned by the certs. | 108 // |present_issuers_| will point to data owned by the certs. |
105 ParsedCertificateList issuers_; | 109 ParsedCertificateList issuers_; |
106 // The index of the next cert in |issuers_| to return. | 110 // The index of the next cert in |issuers_| to return. |
107 size_t cur_issuer_ = 0; | 111 size_t cur_issuer_ = 0; |
108 | 112 |
109 // Set of DER-encoded values for the certs in |issuers_|. Used to prevent | 113 // Set of DER-encoded values for the certs in |issuers_|. Used to prevent |
110 // duplicates. This is based on the full DER of the cert to allow different | 114 // duplicates. This is based on the full DER of the cert to allow different |
111 // versions of the same certificate to be tried in different candidate paths. | 115 // versions of the same certificate to be tried in different candidate paths. |
112 // This points to data owned by |issuers_|. | 116 // This points to data owned by |issuers_|. |
113 std::unordered_set<base::StringPiece, base::StringPieceHash> present_issuers_; | 117 std::unordered_set<base::StringPiece, base::StringPieceHash> present_issuers_; |
114 | 118 |
115 // Tracks whether asynchronous requests have been made yet. | 119 // Tracks which requests have been made yet. |
116 bool did_async_query_ = false; | 120 bool did_initial_query_ = false; |
| 121 bool did_async_issuer_query_ = false; |
117 // If asynchronous requests were made, how many of them are still outstanding? | 122 // If asynchronous requests were made, how many of them are still outstanding? |
118 size_t pending_async_results_; | 123 size_t pending_async_results_; |
119 // Owns the Request objects for any asynchronous requests so that they will be | 124 // Owns the Request objects for any asynchronous requests so that they will be |
120 // cancelled if CertIssuersIter is destroyed. | 125 // cancelled if CertIssuersIter is destroyed. |
121 std::vector<std::unique_ptr<CertIssuerSource::Request>> | 126 std::vector<std::unique_ptr<CertIssuerSource::Request>> |
122 pending_async_requests_; | 127 pending_async_requests_; |
| 128 std::unique_ptr<TrustStore::Request> pending_anchor_request_; |
123 | 129 |
124 // When GetNextIssuer was called and returned asynchronously, |*out_| is | 130 // When GetNextIssuer was called and returned asynchronously, |*out_| is |
125 // where the result will be stored, and |callback_| will be run when the | 131 // where the result will be stored, and |callback_| will be run when the |
126 // result is ready. | 132 // result is ready. |
127 CertificateOrTrustAnchor* out_; | 133 CertificateOrTrustAnchor* out_; |
128 base::Closure callback_; | 134 base::Closure callback_; |
129 | 135 |
130 DISALLOW_COPY_AND_ASSIGN(CertIssuersIter); | 136 DISALLOW_COPY_AND_ASSIGN(CertIssuersIter); |
131 }; | 137 }; |
132 | 138 |
133 CertIssuersIter::CertIssuersIter(scoped_refptr<ParsedCertificate> in_cert, | 139 CertIssuersIter::CertIssuersIter(scoped_refptr<ParsedCertificate> in_cert, |
134 CertIssuerSources* cert_issuer_sources, | 140 CertIssuerSources* cert_issuer_sources, |
135 const TrustStore& trust_store) | 141 const TrustStore* trust_store) |
136 : cert_(in_cert), cert_issuer_sources_(cert_issuer_sources) { | 142 : cert_(in_cert), |
| 143 cert_issuer_sources_(cert_issuer_sources), |
| 144 trust_store_(trust_store) { |
137 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) << ") created"; | 145 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) << ") created"; |
138 trust_store.FindTrustAnchorsByNormalizedName(in_cert->normalized_issuer(), | |
139 &anchors_); | |
140 | |
141 for (auto* cert_issuer_source : *cert_issuer_sources_) { | |
142 ParsedCertificateList new_issuers; | |
143 cert_issuer_source->SyncGetIssuersOf(cert(), &new_issuers); | |
144 for (scoped_refptr<ParsedCertificate>& issuer : new_issuers) { | |
145 if (present_issuers_.find(issuer->der_cert().AsStringPiece()) != | |
146 present_issuers_.end()) | |
147 continue; | |
148 present_issuers_.insert(issuer->der_cert().AsStringPiece()); | |
149 issuers_.push_back(std::move(issuer)); | |
150 } | |
151 } | |
152 // TODO(mattm): sort by notbefore, etc (eg if cert issuer matches a trust | |
153 // anchor subject (or is a trust anchor), that should be sorted higher too. | |
154 // See big list of possible sorting hints in RFC 4158.) | |
155 // (Update PathBuilderKeyRolloverTest.TestRolloverBothRootsTrusted once that | |
156 // is done) | |
157 } | 146 } |
158 | 147 |
159 CompletionStatus CertIssuersIter::GetNextIssuer(CertificateOrTrustAnchor* out, | 148 CompletionStatus CertIssuersIter::GetNextIssuer(CertificateOrTrustAnchor* out, |
160 const base::Closure& callback) { | 149 const base::Closure& callback) { |
161 // Should not be called again while already waiting for an async result. | 150 // Should not be called again while already waiting for an async result. |
162 DCHECK(callback_.is_null()); | 151 DCHECK(callback_.is_null()); |
163 | 152 |
| 153 if (!did_initial_query_) { |
| 154 did_initial_query_ = true; |
| 155 trust_store_->FindTrustAnchorsForCert( |
| 156 cert_.get(), |
| 157 callback.is_null() ? TrustStore::TrustAnchorsCallback() |
| 158 : base::Bind(&CertIssuersIter::GotAsyncAnchors, |
| 159 base::Unretained(this)), |
| 160 &anchors_, &pending_anchor_request_); |
| 161 |
| 162 for (auto* cert_issuer_source : *cert_issuer_sources_) { |
| 163 ParsedCertificateList new_issuers; |
| 164 cert_issuer_source->SyncGetIssuersOf(cert(), &new_issuers); |
| 165 for (scoped_refptr<ParsedCertificate>& issuer : 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 } |
| 173 DVLOG(1) << anchors_.size() << " sync anchors, " << issuers_.size() |
| 174 << " sync issuers"; |
| 175 // 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. |
| 177 // See big list of possible sorting hints in RFC 4158.) |
| 178 // (Update PathBuilderKeyRolloverTest.TestRolloverBothRootsTrusted once that |
| 179 // is done) |
| 180 } |
| 181 |
164 // Return possible trust anchors first. | 182 // Return possible trust anchors first. |
165 if (cur_anchor_ < anchors_.size()) { | 183 if (cur_anchor_ < anchors_.size()) { |
166 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) | 184 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
167 << "): returning anchor " << cur_anchor_ << " of " | 185 << "): returning anchor " << cur_anchor_ << " of " |
168 << anchors_.size(); | 186 << anchors_.size(); |
169 // Still have anchors that haven't been returned yet, return one of them. | 187 // Still have anchors that haven't been returned yet, return one of them. |
170 *out = CertificateOrTrustAnchor(anchors_[cur_anchor_++]); | 188 *out = CertificateOrTrustAnchor(anchors_[cur_anchor_++]); |
171 return CompletionStatus::SYNC; | 189 return CompletionStatus::SYNC; |
172 } | 190 } |
173 | 191 |
| 192 if (pending_anchor_request_) { |
| 193 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
| 194 << ") Still waiting for async trust anchor results."; |
| 195 out_ = out; |
| 196 callback_ = callback; |
| 197 return CompletionStatus::ASYNC; |
| 198 } |
| 199 |
174 if (cur_issuer_ < issuers_.size()) { | 200 if (cur_issuer_ < issuers_.size()) { |
175 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) | 201 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
176 << "): returning issuer " << cur_issuer_ << " of " | 202 << "): returning issuer " << cur_issuer_ << " of " |
177 << issuers_.size(); | 203 << issuers_.size(); |
178 // Still have issuers that haven't been returned yet, return one of them. | 204 // Still have issuers that haven't been returned yet, return one of them. |
179 // A reference to the returned issuer is retained, since |present_issuers_| | 205 // A reference to the returned issuer is retained, since |present_issuers_| |
180 // points to data owned by it. | 206 // points to data owned by it. |
181 *out = CertificateOrTrustAnchor(issuers_[cur_issuer_++]); | 207 *out = CertificateOrTrustAnchor(issuers_[cur_issuer_++]); |
182 return CompletionStatus::SYNC; | 208 return CompletionStatus::SYNC; |
183 } | 209 } |
184 if (did_async_query_) { | 210 |
| 211 if (did_async_issuer_query_) { |
185 if (pending_async_results_ == 0) { | 212 if (pending_async_results_ == 0) { |
186 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) | 213 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
187 << ") Reached the end of all available issuers."; | 214 << ") Reached the end of all available issuers."; |
188 // Reached the end of all available issuers. | 215 // Reached the end of all available issuers. |
189 *out = CertificateOrTrustAnchor(); | 216 *out = CertificateOrTrustAnchor(); |
190 return CompletionStatus::SYNC; | 217 return CompletionStatus::SYNC; |
191 } | 218 } |
192 | 219 |
193 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) | 220 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
194 << ") Still waiting for async results from other " | 221 << ") Still waiting for async results from other " |
195 "CertIssuerSources."; | 222 "CertIssuerSources."; |
196 // Still waiting for async results from other CertIssuerSources. | 223 // Still waiting for async results from other CertIssuerSources. |
197 out_ = out; | 224 out_ = out; |
198 callback_ = callback; | 225 callback_ = callback; |
199 return CompletionStatus::ASYNC; | 226 return CompletionStatus::ASYNC; |
200 } | 227 } |
201 // Reached the end of synchronously gathered issuers. | 228 // Reached the end of synchronously gathered issuers. |
202 | 229 |
203 if (callback.is_null()) { | 230 if (callback.is_null()) { |
204 // Synchronous-only mode, don't try to query async sources. | 231 // Synchronous-only mode, don't try to query async sources. |
205 *out = CertificateOrTrustAnchor(); | 232 *out = CertificateOrTrustAnchor(); |
206 return CompletionStatus::SYNC; | 233 return CompletionStatus::SYNC; |
207 } | 234 } |
208 | 235 |
209 // Now issue request(s) for async ones (AIA, etc). | 236 // Now issue request(s) for async ones (AIA, etc). |
210 did_async_query_ = true; | 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 } |
| 246 |
| 247 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
| 248 << ") issued AsyncGetIssuersOf call(s) (n=" << pending_async_results_ |
| 249 << ")"; |
| 250 out_ = out; |
| 251 callback_ = callback; |
| 252 return CompletionStatus::ASYNC; |
| 253 } |
| 254 |
| 255 void CertIssuersIter::DoAsyncIssuerQuery() { |
| 256 DCHECK(!did_async_issuer_query_); |
| 257 did_async_issuer_query_ = true; |
211 pending_async_results_ = 0; | 258 pending_async_results_ = 0; |
212 for (auto* cert_issuer_source : *cert_issuer_sources_) { | 259 for (auto* cert_issuer_source : *cert_issuer_sources_) { |
213 std::unique_ptr<CertIssuerSource::Request> request; | 260 std::unique_ptr<CertIssuerSource::Request> request; |
214 cert_issuer_source->AsyncGetIssuersOf( | 261 cert_issuer_source->AsyncGetIssuersOf( |
215 cert(), | 262 cert(), |
216 base::Bind(&CertIssuersIter::GotAsyncCerts, base::Unretained(this)), | 263 base::Bind(&CertIssuersIter::GotAsyncCerts, base::Unretained(this)), |
217 &request); | 264 &request); |
218 if (request) { | 265 if (request) { |
219 DVLOG(1) << "AsyncGetIssuersOf(" << CertDebugString(cert()) | 266 DVLOG(1) << "AsyncGetIssuersOf(" << CertDebugString(cert()) |
220 << ") pending..."; | 267 << ") pending..."; |
221 pending_async_results_++; | 268 pending_async_results_++; |
222 pending_async_requests_.push_back(std::move(request)); | 269 pending_async_requests_.push_back(std::move(request)); |
223 } | 270 } |
224 } | 271 } |
| 272 } |
225 | 273 |
226 if (pending_async_results_ == 0) { | 274 void CertIssuersIter::GotAsyncAnchors(TrustAnchors anchors) { |
227 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) | 275 DVLOG(1) << "CertIssuersIter::GotAsyncAnchors(" << CertDebugString(cert()) |
228 << ") No cert sources have async results."; | 276 << "): " << anchors.size() << " anchors"; |
229 // No cert sources have async results. | 277 for (scoped_refptr<TrustAnchor>& anchor : anchors) |
230 *out = CertificateOrTrustAnchor(); | 278 anchors_.push_back(std::move(anchor)); |
231 return CompletionStatus::SYNC; | 279 pending_anchor_request_.reset(); |
232 } | |
233 | 280 |
234 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) | 281 NotifyIfNecessary(); |
235 << ") issued AsyncGetIssuersOf call(s) (n=" << pending_async_results_ | |
236 << ")"; | |
237 out_ = out; | |
238 callback_ = callback; | |
239 return CompletionStatus::ASYNC; | |
240 } | 282 } |
241 | 283 |
242 void CertIssuersIter::GotAsyncCerts(CertIssuerSource::Request* request) { | 284 void CertIssuersIter::GotAsyncCerts(CertIssuerSource::Request* request) { |
243 DVLOG(1) << "CertIssuersIter::GotAsyncCerts(" << CertDebugString(cert()) | 285 DVLOG(1) << "CertIssuersIter::GotAsyncCerts(" << CertDebugString(cert()) |
244 << ")"; | 286 << ")"; |
245 while (true) { | 287 while (true) { |
246 scoped_refptr<ParsedCertificate> cert; | 288 scoped_refptr<ParsedCertificate> cert; |
247 CompletionStatus status = request->GetNext(&cert); | 289 CompletionStatus status = request->GetNext(&cert); |
248 if (!cert) { | 290 if (!cert) { |
249 if (status == CompletionStatus::SYNC) { | 291 if (status == CompletionStatus::SYNC) { |
250 // Request is exhausted, no more results pending from that | 292 // Request is exhausted, no more results pending from that |
251 // CertIssuerSource. | 293 // CertIssuerSource. |
252 DCHECK_GT(pending_async_results_, 0U); | 294 DCHECK_GT(pending_async_results_, 0U); |
253 pending_async_results_--; | 295 pending_async_results_--; |
254 } | 296 } |
255 break; | 297 break; |
256 } | 298 } |
257 DCHECK_EQ(status, CompletionStatus::SYNC); | 299 DCHECK_EQ(status, CompletionStatus::SYNC); |
258 if (present_issuers_.find(cert->der_cert().AsStringPiece()) != | 300 if (present_issuers_.find(cert->der_cert().AsStringPiece()) != |
259 present_issuers_.end()) | 301 present_issuers_.end()) |
260 continue; | 302 continue; |
261 present_issuers_.insert(cert->der_cert().AsStringPiece()); | 303 present_issuers_.insert(cert->der_cert().AsStringPiece()); |
262 issuers_.push_back(std::move(cert)); | 304 issuers_.push_back(std::move(cert)); |
263 } | 305 } |
264 | 306 |
265 // TODO(mattm): re-sort remaining elements of issuers_ (remaining elements may | 307 // TODO(mattm): re-sort remaining elements of issuers_ (remaining elements may |
266 // be more than the ones just inserted, depending on |cur_| value). | 308 // be more than the ones just inserted, depending on |cur_| value). |
267 | 309 |
| 310 NotifyIfNecessary(); |
| 311 } |
| 312 |
| 313 void CertIssuersIter::NotifyIfNecessary() { |
268 // Notify that more results are available, if necessary. | 314 // Notify that more results are available, if necessary. |
269 if (!callback_.is_null()) { | 315 if (!callback_.is_null()) { |
270 DCHECK_GE(cur_anchor_, anchors_.size()); | 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 } |
271 if (cur_issuer_ < issuers_.size()) { | 324 if (cur_issuer_ < issuers_.size()) { |
| 325 DCHECK(!pending_anchor_request_); |
272 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) | 326 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
273 << "): async returning item " << cur_issuer_ << " of " | 327 << "): async returning issuer " << cur_issuer_ << " of " |
274 << issuers_.size(); | 328 << issuers_.size(); |
275 *out_ = CertificateOrTrustAnchor(std::move(issuers_[cur_issuer_++])); | 329 *out_ = CertificateOrTrustAnchor(std::move(issuers_[cur_issuer_++])); |
276 base::ResetAndReturn(&callback_).Run(); | 330 base::ResetAndReturn(&callback_).Run(); |
277 } else if (pending_async_results_ == 0) { | 331 return; |
| 332 } |
| 333 |
| 334 if (!did_async_issuer_query_) |
| 335 DoAsyncIssuerQuery(); |
| 336 |
| 337 if (pending_async_results_ == 0) { |
278 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) | 338 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
279 << "): async returning empty result"; | 339 << "): async returning empty result"; |
280 *out_ = CertificateOrTrustAnchor(); | 340 *out_ = CertificateOrTrustAnchor(); |
281 base::ResetAndReturn(&callback_).Run(); | 341 base::ResetAndReturn(&callback_).Run(); |
282 } else { | 342 return; |
283 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) | |
284 << "): empty result, but other async results " | |
285 "pending, waiting.."; | |
286 } | 343 } |
| 344 DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert()) |
| 345 << "): empty result, but other async results " |
| 346 "pending, waiting.."; |
287 } | 347 } |
288 } | 348 } |
289 | 349 |
290 // CertIssuerIterPath tracks which certs are present in the path and prevents | 350 // CertIssuerIterPath tracks which certs are present in the path and prevents |
291 // paths from being built which repeat any certs (including different versions | 351 // paths from being built which repeat any certs (including different versions |
292 // of the same cert, based on Subject+SubjectAltName+SPKI). | 352 // of the same cert, based on Subject+SubjectAltName+SPKI). |
293 class CertIssuerIterPath { | 353 class CertIssuerIterPath { |
294 public: | 354 public: |
295 // Returns true if |cert| is already present in the path. | 355 // Returns true if |cert| is already present in the path. |
296 bool IsPresent(const ParsedCertificate* cert) const { | 356 bool IsPresent(const ParsedCertificate* cert) const { |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 } | 570 } |
511 | 571 |
512 if (next_issuer_.IsCertificate()) { | 572 if (next_issuer_.IsCertificate()) { |
513 // Skip this cert if it is already in the chain. | 573 // Skip this cert if it is already in the chain. |
514 if (cur_path_.IsPresent(next_issuer_.cert.get())) { | 574 if (cur_path_.IsPresent(next_issuer_.cert.get())) { |
515 next_state_ = STATE_GET_NEXT_ISSUER; | 575 next_state_ = STATE_GET_NEXT_ISSUER; |
516 return CompletionStatus::SYNC; | 576 return CompletionStatus::SYNC; |
517 } | 577 } |
518 | 578 |
519 cur_path_.Append(base::WrapUnique(new CertIssuersIter( | 579 cur_path_.Append(base::WrapUnique(new CertIssuersIter( |
520 std::move(next_issuer_.cert), &cert_issuer_sources_, *trust_store_))); | 580 std::move(next_issuer_.cert), &cert_issuer_sources_, trust_store_))); |
521 next_issuer_ = CertificateOrTrustAnchor(); | 581 next_issuer_ = CertificateOrTrustAnchor(); |
522 DVLOG(1) << "CertPathIter cur_path_ = " << cur_path_.PathDebugString(); | 582 DVLOG(1) << "CertPathIter cur_path_ = " << cur_path_.PathDebugString(); |
523 // Continue descending the tree. | 583 // Continue descending the tree. |
524 next_state_ = STATE_GET_NEXT_ISSUER; | 584 next_state_ = STATE_GET_NEXT_ISSUER; |
525 } else { | 585 } else { |
526 // TODO(mattm): should also include such paths in CertPathBuilder::Result, | 586 // TODO(mattm): should also include such paths in CertPathBuilder::Result, |
527 // maybe with a flag to enable it. Or use a visitor pattern so the caller | 587 // maybe with a flag to enable it. Or use a visitor pattern so the caller |
528 // can decide what to do with any failed paths. | 588 // can decide what to do with any failed paths. |
529 // No more issuers for current chain, go back up and see if there are any | 589 // No more issuers for current chain, go back up and see if there are any |
530 // more for the previous cert. | 590 // more for the previous cert. |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 result_path->error = is_success ? OK : ERR_CERT_AUTHORITY_INVALID; | 723 result_path->error = is_success ? OK : ERR_CERT_AUTHORITY_INVALID; |
664 // TODO(mattm): set best_result_index based on number or severity of errors. | 724 // TODO(mattm): set best_result_index based on number or severity of errors. |
665 if (result_path->error == OK) | 725 if (result_path->error == OK) |
666 out_result_->best_result_index = out_result_->paths.size(); | 726 out_result_->best_result_index = out_result_->paths.size(); |
667 // TODO(mattm): add flag to only return a single path or all attempted paths? | 727 // TODO(mattm): add flag to only return a single path or all attempted paths? |
668 result_path->path = path; | 728 result_path->path = path; |
669 out_result_->paths.push_back(std::move(result_path)); | 729 out_result_->paths.push_back(std::move(result_path)); |
670 } | 730 } |
671 | 731 |
672 } // namespace net | 732 } // namespace net |
OLD | NEW |