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_policy_constraints(&mut self, _constraints: &PolicyConstraints) {}
139
140 fn visit_extension_extended_key_usage(&mut self, _usage: &ExtendedKeyUsage) {}
142
143 fn visit_extension_crl_distribution_points(&mut self, _crl: &CRLDistributionPoints) {}
145
146 fn visit_extension_inhibit_anypolicy(&mut self, _policy: &InhibitAnyPolicy) {}
148
149 fn visit_extension_authority_information_access(&mut self, _info: &AuthorityInfoAccess) {}
151
152 fn visit_extension_sct(&mut self, _sct: &[SignedCertificateTimestamp]) {}
154}
155
156impl X509Certificate<'_> {
157 pub fn walk<V: X509CertificateVisitor>(&self, visitor: &mut V) {
159 visitor.visit_tbs_certificate(&self.tbs_certificate);
160 self.tbs_certificate.walk(visitor);
161 visitor.visit_signature_algorithm(&self.signature_algorithm);
162 visitor.visit_signature_value(&self.signature_value);
163 }
164}
165
166impl TbsCertificate<'_> {
167 pub fn walk<V: X509CertificateVisitor>(&self, visitor: &mut V) {
169 visitor.visit_version(&self.version);
170 visitor.visit_serial_number(self.raw_serial());
171 visitor.visit_tbs_signature_algorithm(&self.signature);
172 visitor.visit_issuer(&self.issuer);
173 visitor.visit_validity(&self.validity);
174 visitor.visit_subject(&self.subject);
175 visitor.visit_subject_public_key_info(&self.subject_pki);
176 visitor.visit_issuer_unique_id(self.issuer_uid.as_ref());
177 visitor.visit_subject_unique_id(self.subject_uid.as_ref());
178 visitor.pre_visit_extensions(self.extensions());
179 for extension in self.extensions() {
180 visitor.visit_extension(extension);
181
182 if extension.oid == OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER {
183 if let ParsedExtension::AuthorityKeyIdentifier(aki) = &extension.parsed_extension {
184 visitor.visit_extension_aki(aki);
185 }
186 } else if extension.oid == OID_X509_EXT_SUBJECT_KEY_IDENTIFIER {
187 if let ParsedExtension::SubjectKeyIdentifier(id) = &extension.parsed_extension {
188 visitor.visit_extension_ski(id);
189 }
190 } else if extension.oid == OID_X509_EXT_KEY_USAGE {
191 if let ParsedExtension::KeyUsage(usage) = &extension.parsed_extension {
192 visitor.visit_extension_key_usage(usage);
193 }
194 } else if extension.oid == OID_X509_EXT_CERTIFICATE_POLICIES {
195 if let ParsedExtension::CertificatePolicies(policies) = &extension.parsed_extension
196 {
197 visitor.visit_extension_certificate_policies(policies);
198 }
199 } else if extension.oid == OID_X509_EXT_SUBJECT_ALT_NAME {
200 if let ParsedExtension::SubjectAlternativeName(san) = &extension.parsed_extension {
201 visitor.visit_extension_subject_alternative_name(san);
202 }
203 } else if extension.oid == OID_X509_EXT_ISSUER_ALT_NAME {
204 if let ParsedExtension::IssuerAlternativeName(ian) = &extension.parsed_extension {
205 visitor.visit_extension_issuer_alternative_name(ian);
206 }
207 } else if extension.oid == OID_X509_EXT_BASIC_CONSTRAINTS {
208 if let ParsedExtension::BasicConstraints(bc) = &extension.parsed_extension {
209 visitor.visit_extension_basic_constraints(bc);
210 }
211 } else if extension.oid == OID_X509_EXT_NAME_CONSTRAINTS {
212 if let ParsedExtension::NameConstraints(constraints) = &extension.parsed_extension {
213 visitor.visit_extension_name_constraints(constraints);
214 }
215 } else if extension.oid == OID_X509_EXT_POLICY_CONSTRAINTS {
216 if let ParsedExtension::PolicyConstraints(constraints) = &extension.parsed_extension
217 {
218 visitor.visit_extension_policy_constraints(constraints);
219 }
220 } else if extension.oid == OID_X509_EXT_EXTENDED_KEY_USAGE {
221 if let ParsedExtension::ExtendedKeyUsage(usage) = &extension.parsed_extension {
222 visitor.visit_extension_extended_key_usage(usage);
223 }
224 } else if extension.oid == OID_X509_EXT_CRL_DISTRIBUTION_POINTS {
225 if let ParsedExtension::CRLDistributionPoints(crl) = &extension.parsed_extension {
226 visitor.visit_extension_crl_distribution_points(crl);
227 }
228 } else if extension.oid == OID_X509_EXT_INHIBITANT_ANY_POLICY {
229 if let ParsedExtension::InhibitAnyPolicy(policy) = &extension.parsed_extension {
230 visitor.visit_extension_inhibit_anypolicy(policy);
231 }
232 } else if extension.oid == OID_PKIX_AUTHORITY_INFO_ACCESS {
233 if let ParsedExtension::AuthorityInfoAccess(info) = &extension.parsed_extension {
234 visitor.visit_extension_authority_information_access(info);
235 }
236 } else if extension.oid == OID_CT_LIST_SCT {
237 if let ParsedExtension::SCT(sct) = &extension.parsed_extension {
238 visitor.visit_extension_sct(sct);
239 }
240 }
241 }
242 visitor.post_visit_extensions(self.extensions());
243 }
244}
245
246#[cfg(test)]
247mod tests {
248 use super::*;
249 use crate::FromDer;
250
251 static IGCA_DER: &[u8] = include_bytes!("../../assets/IGC_A.der");
252
253 #[test]
254 fn visitor_certificate() {
255 #[derive(Debug, Default)]
256 struct SubjectIssuerVisitor {
257 issuer: String,
258 subject: String,
259 is_ca: bool,
260 }
261
262 impl X509CertificateVisitor for SubjectIssuerVisitor {
263 fn visit_issuer(&mut self, name: &X509Name) {
264 self.issuer = name.to_string();
265 }
266
267 fn visit_subject(&mut self, name: &X509Name) {
268 self.subject = name.to_string();
269 }
270
271 fn visit_extension_basic_constraints(&mut self, bc: &BasicConstraints) {
272 self.is_ca = bc.ca;
273 }
274 }
275
276 let mut visitor = SubjectIssuerVisitor::default();
277 let (_, x509) = X509Certificate::from_der(IGCA_DER).unwrap();
278
279 x509.walk(&mut visitor);
280 assert!(!visitor.issuer.is_empty());
281 assert!(visitor.is_ca);
282 assert_eq!(&visitor.issuer, &visitor.subject);
283 }
284}