x509_parser/visitor/
certificate_visitor.rs1use asn1_rs::BitString;
2use oid_registry::*;
3
4use crate::certificate::*;
5use crate::extensions::*;
6use crate::x509::*;
7
8pub trait X509CertificateVisitor {
52 fn walk(&mut self, x509: &X509Certificate)
54 where
55 Self: Sized,
56 {
57 x509.walk(self);
58 }
59
60 fn visit_tbs_certificate(&mut self, _tbs: &TbsCertificate) {}
62
63 fn visit_signature_algorithm(&mut self, _algorithm: &AlgorithmIdentifier) {}
68
69 fn visit_signature_value(&mut self, _signature: &BitString) {}
71
72 fn visit_version(&mut self, _version: &X509Version) {}
74
75 fn visit_serial_number(&mut self, _serial: &[u8]) {}
77
78 fn visit_tbs_signature_algorithm(&mut self, _algorithm: &AlgorithmIdentifier) {}
83
84 fn visit_issuer(&mut self, _name: &X509Name) {}
86
87 fn visit_validity(&mut self, _validity: &Validity) {}
89
90 fn visit_subject(&mut self, _name: &X509Name) {}
92
93 fn visit_subject_public_key_info(&mut self, _subject_pki: &SubjectPublicKeyInfo) {}
95
96 fn visit_issuer_unique_id(&mut self, _id: Option<&UniqueIdentifier>) {}
98
99 fn visit_subject_unique_id(&mut self, _id: Option<&UniqueIdentifier>) {}
101
102 fn pre_visit_extensions(&mut self, _extensions: &[X509Extension]) {}
104
105 fn visit_extension(&mut self, _extension: &X509Extension) {}
109
110 fn post_visit_extensions(&mut self, _extensions: &[X509Extension]) {}
112
113 fn visit_extension_aki(&mut self, _aki: &AuthorityKeyIdentifier) {}
115
116 fn visit_extension_ski(&mut self, _id: &KeyIdentifier) {}
118
119 fn visit_extension_key_usage(&mut self, _usage: &KeyUsage) {}
121
122 fn visit_extension_certificate_policies(&mut self, _policies: &CertificatePolicies) {}
124
125 fn visit_extension_subject_alternative_name(&mut self, _san: &SubjectAlternativeName) {}
127
128 fn visit_extension_issuer_alternative_name(&mut self, _ian: &IssuerAlternativeName) {}
130
131 fn visit_extension_basic_constraints(&mut self, _bc: &BasicConstraints) {}
133
134 fn visit_extension_name_constraints(&mut self, _constraints: &NameConstraints) {}
136
137 fn visit_extension_nscert_comment(&mut self, _nscert_comment: &str) {}
139
140 fn visit_extension_nscert_type(&mut self, _nscert_type: &NSCertType) {}
142
143 fn visit_extension_policy_constraints(&mut self, _constraints: &PolicyConstraints) {}
145
146 fn visit_extension_policy_mappings(&mut self, _mappings: &PolicyMappings) {}
148
149 fn visit_extension_extended_key_usage(&mut self, _usage: &ExtendedKeyUsage) {}
151
152 fn visit_extension_crl_distribution_points(&mut self, _crl: &CRLDistributionPoints) {}
154
155 fn visit_extension_inhibit_anypolicy(&mut self, _policy: &InhibitAnyPolicy) {}
157
158 fn visit_extension_authority_information_access(&mut self, _info: &AuthorityInfoAccess) {}
160
161 fn visit_extension_sct(&mut self, _sct: &[SignedCertificateTimestamp]) {}
163
164 fn visit_extension_unknown(&mut self, _ext: &X509Extension) {}
171
172 fn visit_extension_parse_error(
177 &mut self,
178 _extension: &X509Extension,
179 _error: &asn1_rs::Err<asn1_rs::Error>,
180 ) {
181 }
182}
183
184impl X509Certificate<'_> {
185 pub fn walk<V: X509CertificateVisitor>(&self, visitor: &mut V) {
187 visitor.visit_tbs_certificate(&self.tbs_certificate);
188 self.tbs_certificate.walk(visitor);
189 visitor.visit_signature_algorithm(&self.signature_algorithm);
190 visitor.visit_signature_value(&self.signature_value);
191 }
192}
193
194impl TbsCertificate<'_> {
195 pub fn walk<V: X509CertificateVisitor>(&self, visitor: &mut V) {
197 let v = visitor;
199 v.visit_version(&self.version);
200 v.visit_serial_number(self.raw_serial());
201 v.visit_tbs_signature_algorithm(&self.signature);
202 v.visit_issuer(&self.issuer);
203 v.visit_validity(&self.validity);
204 v.visit_subject(&self.subject);
205 v.visit_subject_public_key_info(&self.subject_pki);
206 v.visit_issuer_unique_id(self.issuer_uid.as_ref());
207 v.visit_subject_unique_id(self.subject_uid.as_ref());
208 v.pre_visit_extensions(self.extensions());
209 for extension in self.extensions() {
210 v.visit_extension(extension);
211
212 match extension.parsed_extension() {
213 ParsedExtension::AuthorityInfoAccess(info) => {
214 v.visit_extension_authority_information_access(info)
215 }
216 ParsedExtension::AuthorityKeyIdentifier(aki) => v.visit_extension_aki(aki),
217 ParsedExtension::BasicConstraints(bc) => v.visit_extension_basic_constraints(bc),
218 ParsedExtension::CertificatePolicies(policies) => {
219 v.visit_extension_certificate_policies(policies)
220 }
221 ParsedExtension::CRLDistributionPoints(crl) => {
222 v.visit_extension_crl_distribution_points(crl)
223 }
224 ParsedExtension::ExtendedKeyUsage(usage) => {
225 v.visit_extension_extended_key_usage(usage)
226 }
227 ParsedExtension::InhibitAnyPolicy(policy) => {
228 v.visit_extension_inhibit_anypolicy(policy)
229 }
230 ParsedExtension::IssuerAlternativeName(ian) => {
231 v.visit_extension_issuer_alternative_name(ian)
232 }
233 ParsedExtension::KeyUsage(usage) => v.visit_extension_key_usage(usage),
234 ParsedExtension::NSCertType(nscert_type) => {
235 v.visit_extension_nscert_type(nscert_type)
236 }
237 ParsedExtension::NameConstraints(constraints) => {
238 v.visit_extension_name_constraints(constraints)
239 }
240 ParsedExtension::NsCertComment(comment) => {
241 v.visit_extension_nscert_comment(comment)
242 }
243 ParsedExtension::PolicyConstraints(constraints) => {
244 v.visit_extension_policy_constraints(constraints)
245 }
246 ParsedExtension::PolicyMappings(mappings) => {
247 v.visit_extension_policy_mappings(mappings)
248 }
249 ParsedExtension::SCT(sct) => v.visit_extension_sct(sct),
250 ParsedExtension::SubjectAlternativeName(san) => {
251 v.visit_extension_subject_alternative_name(san)
252 }
253 ParsedExtension::SubjectKeyIdentifier(id) => v.visit_extension_ski(id),
254 ParsedExtension::ParseError { error } => {
255 v.visit_extension_parse_error(extension, error)
256 }
257 _ => v.visit_extension_unknown(extension),
258 }
259 }
260 v.post_visit_extensions(self.extensions());
261 }
262}
263
264#[cfg(test)]
265mod tests {
266 use super::*;
267 use crate::FromDer;
268
269 static IGCA_DER: &[u8] = include_bytes!("../../assets/IGC_A.der");
270
271 #[test]
272 fn visitor_certificate() {
273 #[derive(Debug, Default)]
274 struct SubjectIssuerVisitor {
275 issuer: String,
276 subject: String,
277 is_ca: bool,
278 }
279
280 impl X509CertificateVisitor for SubjectIssuerVisitor {
281 fn visit_issuer(&mut self, name: &X509Name) {
282 self.issuer = name.to_string();
283 }
284
285 fn visit_subject(&mut self, name: &X509Name) {
286 self.subject = name.to_string();
287 }
288
289 fn visit_extension_basic_constraints(&mut self, bc: &BasicConstraints) {
290 self.is_ca = bc.ca;
291 }
292 }
293
294 let mut visitor = SubjectIssuerVisitor::default();
295 let (_, x509) = X509Certificate::from_der(IGCA_DER).unwrap();
296
297 x509.walk(&mut visitor);
298 assert!(!visitor.issuer.is_empty());
299 assert!(visitor.is_ca);
300 assert_eq!(&visitor.issuer, &visitor.subject);
301 }
302}