x509_parser/visitor/
certificate_visitor.rsuse asn1_rs::BitString;
use oid_registry::*;
use crate::certificate::*;
use crate::extensions::*;
use crate::x509::*;
pub trait X509CertificateVisitor {
fn walk(&mut self, x509: &X509Certificate)
where
Self: Sized,
{
x509.walk(self);
}
fn visit_tbs_certificate(&mut self, _tbs: &TbsCertificate) {}
fn visit_signature_algorithm(&mut self, _algorithm: &AlgorithmIdentifier) {}
fn visit_signature_value(&mut self, _signature: &BitString) {}
fn visit_version(&mut self, _version: &X509Version) {}
fn visit_serial_number(&mut self, _serial: &[u8]) {}
fn visit_tbs_signature_algorithm(&mut self, _algorithm: &AlgorithmIdentifier) {}
fn visit_issuer(&mut self, _name: &X509Name) {}
fn visit_validity(&mut self, _validity: &Validity) {}
fn visit_subject(&mut self, _name: &X509Name) {}
fn visit_subject_public_key_info(&mut self, _subject_pki: &SubjectPublicKeyInfo) {}
fn visit_issuer_unique_id(&mut self, _id: Option<&UniqueIdentifier>) {}
fn visit_subject_unique_id(&mut self, _id: Option<&UniqueIdentifier>) {}
fn pre_visit_extensions(&mut self, _extensions: &[X509Extension]) {}
fn visit_extension(&mut self, _extension: &X509Extension) {}
fn post_visit_extensions(&mut self, _extensions: &[X509Extension]) {}
fn visit_extension_aki(&mut self, _aki: &AuthorityKeyIdentifier) {}
fn visit_extension_ski(&mut self, _id: &KeyIdentifier) {}
fn visit_extension_key_usage(&mut self, _usage: &KeyUsage) {}
fn visit_extension_certificate_policies(&mut self, _policies: &CertificatePolicies) {}
fn visit_extension_subject_alternative_name(&mut self, _san: &SubjectAlternativeName) {}
fn visit_extension_issuer_alternative_name(&mut self, _ian: &IssuerAlternativeName) {}
fn visit_extension_basic_constraints(&mut self, _bc: &BasicConstraints) {}
fn visit_extension_name_constraints(&mut self, _constraints: &NameConstraints) {}
fn visit_extension_policy_constraints(&mut self, _constraints: &PolicyConstraints) {}
fn visit_extension_extended_key_usage(&mut self, _usage: &ExtendedKeyUsage) {}
fn visit_extension_crl_distribution_points(&mut self, _crl: &CRLDistributionPoints) {}
fn visit_extension_inhibit_anypolicy(&mut self, _policy: &InhibitAnyPolicy) {}
fn visit_extension_authority_information_access(&mut self, _info: &AuthorityInfoAccess) {}
fn visit_extension_sct(&mut self, _sct: &[SignedCertificateTimestamp]) {}
}
impl X509Certificate<'_> {
pub fn walk<V: X509CertificateVisitor>(&self, visitor: &mut V) {
visitor.visit_tbs_certificate(&self.tbs_certificate);
self.tbs_certificate.walk(visitor);
visitor.visit_signature_algorithm(&self.signature_algorithm);
visitor.visit_signature_value(&self.signature_value);
}
}
impl TbsCertificate<'_> {
pub fn walk<V: X509CertificateVisitor>(&self, visitor: &mut V) {
visitor.visit_version(&self.version);
visitor.visit_serial_number(self.raw_serial());
visitor.visit_tbs_signature_algorithm(&self.signature);
visitor.visit_issuer(&self.issuer);
visitor.visit_validity(&self.validity);
visitor.visit_subject(&self.subject);
visitor.visit_subject_public_key_info(&self.subject_pki);
visitor.visit_issuer_unique_id(self.issuer_uid.as_ref());
visitor.visit_subject_unique_id(self.subject_uid.as_ref());
visitor.pre_visit_extensions(self.extensions());
for extension in self.extensions() {
visitor.visit_extension(extension);
if extension.oid == OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER {
if let ParsedExtension::AuthorityKeyIdentifier(aki) = &extension.parsed_extension {
visitor.visit_extension_aki(aki);
}
} else if extension.oid == OID_X509_EXT_SUBJECT_KEY_IDENTIFIER {
if let ParsedExtension::SubjectKeyIdentifier(id) = &extension.parsed_extension {
visitor.visit_extension_ski(id);
}
} else if extension.oid == OID_X509_EXT_KEY_USAGE {
if let ParsedExtension::KeyUsage(usage) = &extension.parsed_extension {
visitor.visit_extension_key_usage(usage);
}
} else if extension.oid == OID_X509_EXT_CERTIFICATE_POLICIES {
if let ParsedExtension::CertificatePolicies(policies) = &extension.parsed_extension
{
visitor.visit_extension_certificate_policies(policies);
}
} else if extension.oid == OID_X509_EXT_SUBJECT_ALT_NAME {
if let ParsedExtension::SubjectAlternativeName(san) = &extension.parsed_extension {
visitor.visit_extension_subject_alternative_name(san);
}
} else if extension.oid == OID_X509_EXT_ISSUER_ALT_NAME {
if let ParsedExtension::IssuerAlternativeName(ian) = &extension.parsed_extension {
visitor.visit_extension_issuer_alternative_name(ian);
}
} else if extension.oid == OID_X509_EXT_BASIC_CONSTRAINTS {
if let ParsedExtension::BasicConstraints(bc) = &extension.parsed_extension {
visitor.visit_extension_basic_constraints(bc);
}
} else if extension.oid == OID_X509_EXT_NAME_CONSTRAINTS {
if let ParsedExtension::NameConstraints(constraints) = &extension.parsed_extension {
visitor.visit_extension_name_constraints(constraints);
}
} else if extension.oid == OID_X509_EXT_POLICY_CONSTRAINTS {
if let ParsedExtension::PolicyConstraints(constraints) = &extension.parsed_extension
{
visitor.visit_extension_policy_constraints(constraints);
}
} else if extension.oid == OID_X509_EXT_EXTENDED_KEY_USAGE {
if let ParsedExtension::ExtendedKeyUsage(usage) = &extension.parsed_extension {
visitor.visit_extension_extended_key_usage(usage);
}
} else if extension.oid == OID_X509_EXT_CRL_DISTRIBUTION_POINTS {
if let ParsedExtension::CRLDistributionPoints(crl) = &extension.parsed_extension {
visitor.visit_extension_crl_distribution_points(crl);
}
} else if extension.oid == OID_X509_EXT_INHIBITANT_ANY_POLICY {
if let ParsedExtension::InhibitAnyPolicy(policy) = &extension.parsed_extension {
visitor.visit_extension_inhibit_anypolicy(policy);
}
} else if extension.oid == OID_PKIX_AUTHORITY_INFO_ACCESS {
if let ParsedExtension::AuthorityInfoAccess(info) = &extension.parsed_extension {
visitor.visit_extension_authority_information_access(info);
}
} else if extension.oid == OID_CT_LIST_SCT {
if let ParsedExtension::SCT(sct) = &extension.parsed_extension {
visitor.visit_extension_sct(sct);
}
}
}
visitor.post_visit_extensions(self.extensions());
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::FromDer;
static IGCA_DER: &[u8] = include_bytes!("../../assets/IGC_A.der");
#[test]
fn visitor_certificate() {
#[derive(Debug, Default)]
struct SubjectIssuerVisitor {
issuer: String,
subject: String,
is_ca: bool,
}
impl X509CertificateVisitor for SubjectIssuerVisitor {
fn visit_issuer(&mut self, name: &X509Name) {
self.issuer = name.to_string();
}
fn visit_subject(&mut self, name: &X509Name) {
self.subject = name.to_string();
}
fn visit_extension_basic_constraints(&mut self, bc: &BasicConstraints) {
self.is_ca = bc.ca;
}
}
let mut visitor = SubjectIssuerVisitor::default();
let (_, x509) = X509Certificate::from_der(IGCA_DER).unwrap();
x509.walk(&mut visitor);
assert!(!visitor.issuer.is_empty());
assert!(visitor.is_ca);
assert_eq!(&visitor.issuer, &visitor.subject);
}
}