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

Side by Side Diff: net/tools/ct_mapper/my_visitor.cc

Issue 1238413004: Framework for iterating over certificates in CT database from Chromium code. (not for review) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Make samples page work Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/tools/ct_mapper/my_visitor.h ('k') | net/tools/ct_mapper/sync-ct-database.sh » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 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/tools/ct_mapper/my_visitor.h"
6
7 #include <algorithm>
8
9 #include "base/strings/stringprintf.h"
10 #include "net/cert/internal/parsed_certificate.h"
11 #include "net/cert/internal/signature_policy.h"
12 #include "net/cert/internal/trust_store.h"
13 #include "net/cert/internal/verify_certificate_chain.h"
14 #include "net/der/encode_values.h"
15 #include "net/der/input.h"
16 #include "net/tools/ct_mapper/entry.h"
17 #include "net/tools/ct_mapper/metrics.h"
18 #include "net/tools/ct_mapper/visitor.h"
19
20 namespace net {
21
22 namespace {
23
24 bool AddParsedCertificate(const der::Input& cert_data,
25 ParsedCertificateList* chain,
26 CertErrors* errors) {
27 ParseCertificateOptions options;
28 options.allow_invalid_serial_numbers = true;
29 scoped_refptr<ParsedCertificate> cert =
30 ParsedCertificate::CreateWithoutCopyingUnsafe(
31 cert_data.UnsafeData(), cert_data.Length(), options, errors);
32 if (!cert) {
33 return false;
34 }
35 chain->push_back(std::move(cert));
36 return true;
37 }
38
39 void LogCertPathErrors(CertPathErrors* errors,
40 const ParsedCertificateList& chain,
41 const std::string& name,
42 const Entry& entry,
43 CertError::Severity severity,
44 Metrics* metrics) {
45 if (errors->ContainsAnyErrorWithSeverity(severity)) {
46 MetricsItem* item = metrics->GetAndIncrementTotal(name);
47
48 // Identify all the errors.
49 std::set<std::string> error_set;
50 for (size_t i = 0; i < chain.size(); ++i) {
51 CertErrors* cert_errors = errors->GetErrorsForCert(i);
52 for (const auto& error_node : cert_errors->nodes()) {
53 if (error_node.severity == severity) {
54 error_set.insert(error_node.ToDebugString());
55 }
56 }
57 }
58
59 for (const auto& error : error_set) {
60 item->GetAndIncrementTotal(error)->AddSampleChain(entry);
61 }
62 }
63 }
64
65 void LogCertErrors(const CertErrors& errors,
66 const std::string& name,
67 const der::Input& cert,
68 CertError::Severity severity,
69 bool parsing_succeeded,
70 Metrics* metrics) {
71 if (errors.ContainsAnyErrorWithSeverity(severity)) {
72 MetricsItem* item = metrics->GetAndIncrementTotal(name);
73
74 // Identify all the errors.
75 std::set<std::string> error_set;
76 for (const auto& error_node : errors.nodes()) {
77 if (error_node.severity == severity) {
78 error_set.insert(error_node.ToDebugString());
79 }
80 }
81
82 for (const auto& error : error_set) {
83 item->GetAndIncrementTotal(error)->AddSampleCert(cert);
84 }
85 } else if (!parsing_succeeded && severity == CertError::SEVERITY_HIGH) {
86 metrics->GetAndIncrementTotal(name)
87 ->GetAndIncrementTotal("Unknown")
88 ->AddSampleCert(cert);
89 }
90 }
91
92 bool GetFullChain(const Entry& entry,
93 ParsedCertificateList* chain,
94 Metrics* metrics) {
95 chain->reserve(entry.extra_certs.size() + 1);
96
97 CertErrors errors;
98
99 MetricsItem* item = metrics->GetAndIncrementTotal("Parse Certificate");
100 bool parsing_succeeded = AddParsedCertificate(entry.cert, chain, &errors);
101
102 if (!parsing_succeeded) {
103 item->GetAndIncrementTotal("Failure");
104 } else {
105 item->GetAndIncrementTotal("Success");
106 }
107
108 LogCertErrors(errors, "Parse certificate Errors", entry.cert,
109 CertError::SEVERITY_HIGH, parsing_succeeded, metrics);
110 LogCertErrors(errors, "Parse certificate Warnings", entry.cert,
111 CertError::SEVERITY_WARNING, parsing_succeeded, metrics);
112
113 if (!parsing_succeeded)
114 return false;
115
116 for (const auto& extra_cert : entry.extra_certs) {
117 if (!AddParsedCertificate(extra_cert, chain, &errors)) {
118 return false;
119 }
120 }
121
122 return true;
123 }
124
125 base::Time GetTime(const der::GeneralizedTime& der_time) {
126 base::Time::Exploded exploded;
127 exploded.year = der_time.year;
128 exploded.month = der_time.month;
129 exploded.day_of_month = der_time.day;
130 exploded.hour = der_time.hours;
131 exploded.minute = der_time.minutes;
132 exploded.second = der_time.seconds;
133 exploded.millisecond = 0;
134
135 base::Time t;
136 if (!base::Time::FromUTCExploded(exploded, &t))
137 return base::Time();
138 return t;
139 }
140
141 class MyVisitor : public Visitor {
142 public:
143 MyVisitor() : signature_policy_rsa_1024_(1024) {
144 now_time_ = base::Time::Now();
145 CHECK(der::EncodeTimeAsGeneralizedTime(now_time_, &now_));
146 user_initial_policy_set_ = {AnyPolicy()};
147 }
148
149 void Visit(const Entry& entry, Metrics* metrics) override {
150 // Count the entry types.
151 {
152 MetricsItem* item = metrics->GetAndIncrementTotal("CT Entry types");
153
154 switch (entry.type) {
155 case Entry::Type::kLeafCert:
156 item->GetAndIncrementTotal("Leaf");
157 break;
158 case Entry::Type::kExtraCert:
159 item->GetAndIncrementTotal("Extra Cert");
160 break;
161 }
162 }
163
164 // Parse all the certificate.
165 ParsedCertificateList chain;
166 if (!GetFullChain(entry, &chain, metrics))
167 return;
168
169 if (entry.type != Entry::Type::kLeafCert)
170 return;
171
172 base::Time not_before;
173 base::Time not_after;
174
175 GetChainExpiration(chain, &not_before, &not_after);
176 bool chain_expired = now_time_ < not_before || now_time_ > not_after;
177
178 if (chain_expired) {
179 // Use the midpoint of the chain's validity.
180 base::Time avg_t = not_before + (not_after - not_before) / 2;
181
182 der::GeneralizedTime t;
183 der::EncodeTimeAsGeneralizedTime(avg_t, &t);
184
185 TestVerifyChain(chain, "[expired] ", entry, t, metrics);
186 } else {
187 TestVerifyChain(chain, "", entry, now_, metrics);
188 }
189 }
190
191 private:
192 void TestVerifyChain(const ParsedCertificateList& chain,
193 const std::string& name_prefix,
194 const Entry& entry,
195 const der::GeneralizedTime& time,
196 Metrics* metrics) {
197 KeyPurpose required_key_purpose = KeyPurpose::SERVER_AUTH;
198 CertPathErrors errors;
199 VerifyCertificateChain(
200 chain, CertificateTrust::ForTrustAnchor(), &signature_policy_rsa_1024_,
201 time, required_key_purpose, InitialExplicitPolicy::kFalse,
202 user_initial_policy_set_, InitialPolicyMappingInhibit ::kFalse,
203 InitialAnyPolicyInhibit::kFalse, nullptr, &errors);
204
205 // Log whether validation succeeded.
206 {
207 MetricsItem* item =
208 metrics->GetAndIncrementTotal(name_prefix + "Verify Chain");
209 if (errors.ContainsHighSeverityErrors()) {
210 item->GetAndIncrementTotal("Failure")->AddSampleChain(entry);
211 } else {
212 item->GetAndIncrementTotal("Success");
213 }
214 }
215
216 // Log the breakdown of the errors.
217 LogCertPathErrors(&errors, chain, name_prefix + "Verify Chain Errors",
218 entry, CertError::SEVERITY_HIGH, metrics);
219
220 LogCertPathErrors(&errors, chain,
221 name_prefix + "Verify Chain Warnings", entry,
222 CertError::SEVERITY_WARNING, metrics);
223 }
224
225 void GetChainExpiration(const ParsedCertificateList& chain,
226 base::Time* not_before,
227 base::Time* not_after) const {
228 *not_before = base::Time();
229 *not_after = base::Time::Max();
230
231 // Determine whether any certificate in the chain (except root) is expired.
232 for (size_t i = 0; i + 1 < chain.size(); ++i) {
233 const auto& tbs = chain[i]->tbs();
234 *not_before = std::max(GetTime(tbs.validity_not_before), *not_before);
235 *not_after = std::min(GetTime(tbs.validity_not_after), *not_after);
236 }
237 }
238
239 der::GeneralizedTime now_;
240 base::Time now_time_;
241 std::set<der::Input> user_initial_policy_set_;
242 SimpleSignaturePolicy signature_policy_rsa_1024_;
243 };
244
245 class MyVisitorFactory : public VisitorFactory {
246 public:
247 std::unique_ptr<Visitor> Create() override {
248 return base::MakeUnique<MyVisitor>();
249 }
250 };
251
252 } // namespace
253
254 std::unique_ptr<VisitorFactory> CreateMyVisitorFactory() {
255 return base::MakeUnique<MyVisitorFactory>();
256 }
257
258 } // namespace net
OLDNEW
« no previous file with comments | « net/tools/ct_mapper/my_visitor.h ('k') | net/tools/ct_mapper/sync-ct-database.sh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698