use std::path::Path;
use rustls::pki_types::CertificateDer;
use rustls::pki_types::pem::PemObject;
use super::{FOOT, ORG_UNIT, attributes, client, elements, refusal, subject, tlv};
use crate::channel::material::{CHAIN, Whose};
use crate::test_support::{Scratch, mint};
fn leaf_of(dir: &Path) -> Vec<u8> {
CertificateDer::from_pem_file(dir.join(CHAIN))
.expect("a leaf")
.to_vec()
}
#[test]
fn a_foot_grade_leaf_is_named_as_this_box_s_own_misconfiguration() {
let scratch = Scratch::new();
mint::material(scratch.path());
mint::foot(scratch.path(), true);
let at = scratch.join(CHAIN);
let said = refusal(&leaf_of(scratch.path()), &at).expect("refused");
assert!(said.contains(&at.display().to_string()), "{said}");
assert!(said.contains(mint::SEAT_NAME), "{said}");
assert!(said.contains("foot grade"), "{said}");
assert!(said.contains("operator grade by definition"), "{said}");
assert!(
said.contains(&Whose::Elsewhere.remedy()),
"the remedy is the operator's act: {said}"
);
}
#[test]
fn a_foot_grade_leaf_that_names_no_client_still_names_the_file() {
let scratch = Scratch::new();
mint::material(scratch.path());
mint::foot(scratch.path(), false);
let at = scratch.join(CHAIN);
let said = refusal(&leaf_of(scratch.path()), &at).expect("refused");
assert!(said.contains("the leaf is foot grade"), "{said}");
assert!(said.contains(&at.display().to_string()), "{said}");
}
#[test]
fn an_operator_grade_leaf_says_nothing() {
let scratch = Scratch::new();
mint::material(scratch.path());
let der = leaf_of(scratch.path());
assert_eq!(refusal(&der, &scratch.join(CHAIN)), None);
assert_eq!(
client(&der).as_deref(),
Some(mint::SEAT_NAME),
"and the subject's own name is the last common name in it"
);
}
#[test]
fn nothing_this_walk_cannot_read_is_ever_refused() {
let at = Path::new("client.pem");
for bytes in [
b"".as_slice(),
b"not a certificate at all".as_slice(),
&[0x30, 0x03, 0x02, 0x01, 0x07],
&[0x30, 0x05, 0x30, 0x03, 0x02, 0x01, 0x07],
] {
assert_eq!(refusal(bytes, at), None, "{bytes:?}");
assert_eq!(client(bytes), None, "{bytes:?}");
}
}
#[test]
fn a_body_with_no_serial_number_has_no_subject_to_find() {
let der = [0x30, 0x08, 0x30, 0x06, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00];
assert_eq!(subject(&der), None);
}
#[test]
fn the_length_forms_this_walk_takes_and_the_ones_it_refuses() {
assert_eq!(tlv(&[]), None, "no tag");
assert_eq!(tlv(&[0x30]), None, "no length");
assert_eq!(tlv(&[0x30, 0x80]), None, "the indefinite form DER forbids");
assert_eq!(tlv(&[0x30, 0x85, 1, 1, 1, 1, 1]), None, "wider than served");
assert_eq!(tlv(&[0x30, 0x81]), None, "a truncated long form");
assert_eq!(tlv(&[0x30, 0x02, 0xaa]), None, "a truncated value");
assert_eq!(
tlv(&[0x30, 0x81, 0x01, 0xaa]),
Some((0x30, [0xaa].as_slice(), [].as_slice())),
"the long form for one byte"
);
assert_eq!(
tlv(&[0x02, 0x01, 0x07, 0xff]),
Some((0x02, [0x07].as_slice(), [0xff].as_slice())),
"and what follows a value is handed back whole"
);
}
#[test]
fn a_malformed_tail_yields_the_elements_read_before_it() {
assert_eq!(
elements(&[0x02, 0x01, 0x07, 0x02, 0x09, 0xaa]),
vec![(0x02, [0x07].as_slice())]
);
assert!(elements(&[]).is_empty());
}
#[test]
fn an_attribute_this_walk_cannot_decode_is_skipped_and_never_guessed() {
let rdn = |body: Vec<u8>| {
let mut set = vec![0x31, u8::try_from(body.len()).unwrap_or(0)];
set.extend(body);
set
};
let attribute = |body: Vec<u8>| {
let mut seq = vec![0x30, u8::try_from(body.len()).unwrap_or(0)];
seq.extend(body);
seq
};
let oid = [&[0x06, 0x03][..], &ORG_UNIT[..]].concat();
let wide = attribute([oid.clone(), vec![0x1e, 0x04, 0x00, 0x66, 0x00, 0xf6]].concat());
let untyped = attribute(vec![0x02, 0x01, 0x07, 0x0c, 0x04, 0x66, 0x6f, 0x6f, 0x74]);
let good = attribute([oid, vec![0x0c, 0x04, 0x66, 0x6f, 0x6f, 0x74]].concat());
let name: Vec<u8> = [rdn(wide), rdn(untyped), rdn(good)].concat();
assert_eq!(attributes(&name, ORG_UNIT), vec![FOOT.to_owned()]);
}