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