use asn1_rs::BitString;
use der_parser::num_bigint::BigUint;
use oid_registry::*;
use crate::extensions::*;
use crate::revocation_list::*;
use crate::time::ASN1Time;
use crate::x509::*;
pub trait CertificateRevocationListVisitor {
fn walk(&mut self, crl: &CertificateRevocationList)
where
Self: Sized,
{
crl.walk(self);
}
fn visit_tbs_cert_list(&mut self, _tbs: &TbsCertList) {}
fn visit_signature_algorithm(&mut self, _algorithm: &AlgorithmIdentifier) {}
fn visit_signature_value(&mut self, _signature: &BitString) {}
fn visit_version(&mut self, _version: Option<&X509Version>) {}
fn visit_tbs_signature_algorithm(&mut self, _algorithm: &AlgorithmIdentifier) {}
fn visit_issuer(&mut self, _name: &X509Name) {}
fn visit_this_update(&mut self, _time: &ASN1Time) {}
fn visit_next_update(&mut self, _time: Option<&ASN1Time>) {}
fn visit_revoked_certificates(&mut self, _certificate: &[RevokedCertificate]) {}
fn visit_revoked_certificate(&mut self, _certificate: &RevokedCertificate) {}
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_issuer_alternative_name(&mut self, _ian: &IssuerAlternativeName) {}
fn visit_extension_crl_number(&mut self, _number: &BigUint) {}
fn visit_extension_issuing_distribution_point(&mut self, _dp: &IssuingDistributionPoint) {}
fn visit_extension_authority_information_access(&mut self, _info: &AuthorityInfoAccess) {}
fn visit_extension_reason_code(&mut self, _code: &ReasonCode) {}
fn visit_extension_invalidity_date(&mut self, _time: &ASN1Time) {}
fn visit_extension_sct(&mut self, _sct: &[SignedCertificateTimestamp]) {}
fn visit_extension_unknown(&mut self, _ext: &X509Extension) {}
fn visit_extension_parse_error(
&mut self,
_extension: &X509Extension,
_error: &asn1_rs::Err<asn1_rs::Error>,
) {
}
}
impl CertificateRevocationList<'_> {
pub fn walk<V: CertificateRevocationListVisitor>(&self, visitor: &mut V) {
visitor.visit_tbs_cert_list(&self.tbs_cert_list);
self.tbs_cert_list.walk(visitor);
visitor.visit_signature_algorithm(&self.signature_algorithm);
visitor.visit_signature_value(&self.signature_value);
}
}
impl TbsCertList<'_> {
pub fn walk<V: CertificateRevocationListVisitor>(&self, visitor: &mut V) {
let v = visitor;
v.visit_version(self.version.as_ref());
v.visit_tbs_signature_algorithm(&self.signature);
v.visit_issuer(&self.issuer);
v.visit_this_update(&self.this_update);
v.visit_next_update(self.next_update.as_ref());
v.visit_revoked_certificates(&self.revoked_certificates);
for certificate in &self.revoked_certificates {
v.visit_revoked_certificate(certificate);
}
v.pre_visit_extensions(self.extensions());
for extension in self.extensions() {
v.visit_extension(extension);
match extension.parsed_extension() {
ParsedExtension::AuthorityInfoAccess(info) => {
v.visit_extension_authority_information_access(info)
}
ParsedExtension::AuthorityKeyIdentifier(aki) => v.visit_extension_aki(aki),
ParsedExtension::CRLNumber(number) => v.visit_extension_crl_number(number),
ParsedExtension::InvalidityDate(time) => v.visit_extension_invalidity_date(time),
ParsedExtension::IssuerAlternativeName(ian) => {
v.visit_extension_issuer_alternative_name(ian)
}
ParsedExtension::IssuingDistributionPoint(dp) => {
v.visit_extension_issuing_distribution_point(dp)
}
ParsedExtension::ReasonCode(code) => v.visit_extension_reason_code(code),
ParsedExtension::SCT(sct) => v.visit_extension_sct(sct),
ParsedExtension::ParseError { error } => {
v.visit_extension_parse_error(extension, error)
}
_ => v.visit_extension_unknown(extension),
}
}
v.post_visit_extensions(self.extensions());
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::FromDer;
static CRL: &[u8] = include_bytes!("../../assets/example.crl");
#[test]
fn visitor_crl() {
#[derive(Debug, Default)]
struct RevokedCertsVisitor {
certificates: Vec<BigUint>,
}
impl CertificateRevocationListVisitor for RevokedCertsVisitor {
fn visit_revoked_certificate(&mut self, certificate: &RevokedCertificate) {
self.certificates.push(certificate.user_certificate.clone());
}
}
let mut visitor = RevokedCertsVisitor::default();
let (_, crl) = CertificateRevocationList::from_der(CRL).unwrap();
crl.walk(&mut visitor);
assert_eq!(visitor.certificates.len(), 5);
}
}