print_crl/
print-crl.rs

1use der_parser::oid::Oid;
2use nom::HexDisplay;
3use std::cmp::min;
4use std::env;
5use std::io;
6use x509_parser::prelude::*;
7
8fn print_hex_dump(bytes: &[u8], max_len: usize) {
9    let m = min(bytes.len(), max_len);
10    print!("{}", &bytes[..m].to_hex(16));
11    if bytes.len() > max_len {
12        println!("... <continued>");
13    }
14}
15
16fn format_oid(oid: &Oid) -> String {
17    match oid2sn(oid, oid_registry()) {
18        Ok(s) => s.to_owned(),
19        _ => format!("{}", oid),
20    }
21}
22
23fn print_authority_key_identifier(aki: &AuthorityKeyIdentifier, level: usize) {
24    if let Some(id) = &aki.key_identifier {
25        println!("{:indent$}keyid: {:x}", "", id, indent = level);
26    }
27    if aki.authority_cert_issuer.is_some() {
28        unimplemented!();
29    }
30    if let Some(serial) = aki.authority_cert_serial {
31        let s = format_serial(serial);
32        println!("{:indent$}serial: {}", "", &s, indent = level);
33    }
34}
35
36fn print_x509_extension(oid: &Oid, ext: &X509Extension, level: usize) {
37    match ext.parsed_extension() {
38        ParsedExtension::CRLNumber(num) => {
39            println!("{:indent$}X509v3 CRL Number: {}", "", num, indent = level);
40        }
41        ParsedExtension::ReasonCode(code) => {
42            println!(
43                "{:indent$}X509v3 CRL Reason Code: {}",
44                "",
45                code,
46                indent = level
47            );
48        }
49        ParsedExtension::InvalidityDate(date) => {
50            println!("{:indent$}Invalidity Date: {}", "", date, indent = level);
51        }
52        ParsedExtension::AuthorityKeyIdentifier(aki) => {
53            println!(
54                "{:indent$}X509v3 Authority Key Identifier:",
55                "",
56                indent = level
57            );
58            print_authority_key_identifier(aki, level + 2);
59        }
60        x => {
61            print!("{:indent$}{}:", "", format_oid(oid), indent = level);
62            print!(" Critical={}", ext.critical);
63            print!(" len={}", ext.value.len());
64            println!();
65            println!(" {:indent$}{:?}", "", x, indent = level);
66        }
67    }
68}
69
70fn print_x509_digest_algorithm(alg: &AlgorithmIdentifier, level: usize) {
71    println!(
72        "{:indent$}Oid: {}",
73        "",
74        format_oid(&alg.algorithm),
75        indent = level
76    );
77    if let Some(parameter) = &alg.parameters {
78        println!(
79            "{:indent$}Parameter: <PRESENT> {:?}",
80            "",
81            parameter.tag(),
82            indent = level
83        );
84        let bytes = parameter.as_bytes();
85        print_hex_dump(bytes, 32);
86    } else {
87        println!("{:indent$}Parameter: <ABSENT>", "", indent = level);
88    }
89}
90
91fn print_revoked_certificate(revoked: &RevokedCertificate, level: usize) {
92    println!(
93        "{:indent$}Serial number: {}",
94        "",
95        revoked.raw_serial_as_string(),
96        indent = level
97    );
98    println!(
99        "{:indent$}Revocation Date: {}",
100        "",
101        revoked.revocation_date,
102        indent = level + 2
103    );
104    println!("{:indent$}CRL Extensions:", "", indent = level + 2);
105    for ext in revoked.extensions() {
106        print_x509_extension(&ext.oid, ext, level + 4);
107    }
108}
109
110fn print_crl_info(crl: &CertificateRevocationList) {
111    println!("  Version: {}", crl.version().unwrap_or(X509Version(0)));
112    // println!("  Subject: {}", crl.subject());
113    println!("  Signature Algorithm:");
114    print_x509_digest_algorithm(&crl.signature_algorithm, 4);
115    println!("  Issuer: {}", crl.issuer());
116    // println!("  Serial: {}", crl.tbs_certificate.raw_serial_as_string());
117    println!("  Last Update: {}", crl.last_update());
118    println!(
119        "  Next Update: {}",
120        crl.next_update()
121            .map_or_else(|| "NONE".to_string(), |d| d.to_string())
122    );
123    println!("{:indent$}CRL Extensions:", "", indent = 2);
124    for ext in crl.extensions() {
125        print_x509_extension(&ext.oid, ext, 4);
126    }
127    println!("  Revoked certificates:");
128    for revoked in crl.iter_revoked_certificates() {
129        print_revoked_certificate(revoked, 4);
130    }
131    println!();
132}
133
134pub fn main() -> io::Result<()> {
135    for file_name in env::args().skip(1) {
136        // placeholder to store decoded PEM data, if needed
137        let tmpdata;
138
139        println!("File: {}", file_name);
140        let data = std::fs::read(file_name.clone()).expect("Unable to read file");
141        let der_data: &[u8] = if (data[0], data[1]) == (0x30, 0x82) {
142            // probably DER
143            &data
144        } else {
145            // try as PEM
146            let (_, data) = parse_x509_pem(&data).expect("Could not decode the PEM file");
147            tmpdata = data;
148            &tmpdata.contents
149        };
150        let (_, crl) = parse_x509_crl(der_data).expect("Could not decode DER data");
151        print_crl_info(&crl);
152    }
153    Ok(())
154}