1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
|
use der_parser::ber::*;
use der_parser::der::*;
use std::env;
use std::io;
use nom::HexDisplay;
struct BerPrinter {}
impl BerPrinter {
/// try to parse contents, constructed or not
///
/// Do not raise errors if object is not constructed
fn try_print_encapsulated(&mut self, data: &[u8], depth: usize, ber: &BerObject) {
let mut i = data;
let mut first_object = true;
while !i.is_empty() {
match parse_ber_any_r(i, MAX_RECURSION) {
Ok((rem, inner)) => {
if first_object {
println!("{:1$}encapsulates {{", " ", depth * 2);
first_object = false;
}
self.run_at(&inner, depth + 1);
i = rem;
}
Err(e) => {
if ber.is_constructed() {
// object was constructed, so should have been parsed correctly
eprintln!(
"Error while parsing constructed object at depth {}: {}",
depth, e
);
eprintln!("tried to parse\n{}", data.to_hex(16));
} else {
// does not look like encapsulated data
i = &[];
}
break;
}
}
}
if !first_object {
println!("{:1$}}}", " ", depth * 2);
}
if !i.is_empty() {
println!("WARNING: {} remaining bytes at depth {}", i.len(), depth);
}
}
}
impl<'a> Visit<'a> for BerPrinter {
fn visit_ber(&mut self, ber: &'_ BerObject<'a>, depth: usize) {
// create a printer without the recursive flag, recursion is handled by the
// visitor pattern
let pp = PrettyBer::new(ber, vec![PrettyPrinterFlag::ShowHeader], depth * 2, 2);
println!("{:?}", pp);
match ber.content {
BerObjectContent::Unknown(ref any) => {
self.try_print_encapsulated(any.data, depth, ber);
}
// Bitstring and OctetString also can encapsulate objects
BerObjectContent::OctetString(data) => {
self.try_print_encapsulated(data, depth, ber);
}
_ => (),
}
}
}
pub fn main() -> io::Result<()> {
let mut parse_as_ber = false;
for file_name in env::args().skip(1) {
match file_name.as_ref() {
"--ber" => {
parse_as_ber = true;
continue;
}
"--der" => {
parse_as_ber = false;
continue;
}
_ => (),
}
let data = std::fs::read(file_name.clone()).expect("Unable to read file");
let (rem, obj) = if parse_as_ber {
parse_ber(&data).expect("could not parse BER data")
} else {
parse_der(&data).expect("could not parse DER data")
};
let mut printer = BerPrinter {};
printer.run_at(&obj, 1);
if !rem.is_empty() {
println!("WARNING: extra bytes after BER/DER object:\n{:x?}", rem);
}
}
Ok(())
}
|