use crate::error::ErrorCode;
use crate::fixtures::{extension, extension_error, ia5, int, oid as oid_of, seq, with_extension};
use crate::oid;
use structured_asn1::Oid;
const ISSUER_POLICY: Oid<'static> = Oid::from_bytes(&[0x2a, 0x86, 0x24, 0x01, 0x02]);
const OTHER_POLICY: Oid<'static> = Oid::from_bytes(&[0x2a, 0x86, 0x24, 0x01, 0x03]);
#[test]
fn lazy_policy_qualifier_keeps_its_document_depth() {
let value = seq(&[seq(&[
oid_of(ISSUER_POLICY),
seq(&[seq(&[
oid_of(oid::CPS_QUALIFIER),
ia5("https://example.ua/cps"),
])]),
])]);
with_extension(extension(oid::CERTIFICATE_POLICIES, true, &value), |list| {
let policies = list.certificate_policies(list.memory()).unwrap().unwrap();
let qualifier = policies.policies()[0].qualifiers()[0];
let limited = structured_asn1::Parser::new(
structured_asn1::Encoding::Der,
structured_asn1::Limits {
max_depth: 0,
..structured_asn1::Limits::default()
},
crate::fixtures::memory(),
);
let error = super::qualifier_understood(&limited, qualifier, limited.memory()).unwrap_err();
assert_eq!(
error.code(),
ErrorCode::Encoding(structured_asn1::ErrorCode::LimitExceeded(
structured_asn1::Limit::Depth
))
);
assert_eq!(error.offset(), qualifier.at);
});
}
#[test]
fn a_policy_is_read_with_whatever_was_written_beside_it() {
let statement = ia5("https://example.ua/cps");
let value = seq(&[seq(&[
oid_of(ISSUER_POLICY),
seq(&[seq(&[oid_of(oid::CPS_QUALIFIER), statement.clone()])]),
])]);
with_extension(
extension(oid::CERTIFICATE_POLICIES, false, &value),
|list| {
let policies = list.certificate_policies(list.memory()).unwrap().unwrap();
assert!(policies.has(ISSUER_POLICY, list.memory()).unwrap());
assert!(!policies.has(OTHER_POLICY, list.memory()).unwrap());
let qualifiers = policies.policies()[0].qualifiers();
assert_eq!(qualifiers.len(), 1);
assert_eq!(qualifiers[0].kind(), oid::CPS_QUALIFIER);
assert_eq!(qualifiers[0].value(), &statement[..]);
},
);
}
#[test]
fn a_policy_without_qualifiers_is_the_usual_shape() {
let value = seq(&[seq(&[oid_of(ISSUER_POLICY)])]);
with_extension(
extension(oid::CERTIFICATE_POLICIES, false, &value),
|list| {
let policies = list.certificate_policies(list.memory()).unwrap().unwrap();
assert_eq!(policies.policies().len(), 1);
assert!(policies.policies()[0].qualifiers().is_empty());
},
);
}
#[test]
fn the_identifier_standing_for_any_policy_is_not_treated_as_all_of_them() {
let value = seq(&[seq(&[oid_of(oid::ANY_POLICY)])]);
with_extension(
extension(oid::CERTIFICATE_POLICIES, false, &value),
|list| {
let policies = list.certificate_policies(list.memory()).unwrap().unwrap();
assert!(policies.has(oid::ANY_POLICY, list.memory()).unwrap());
assert!(!policies.has(ISSUER_POLICY, list.memory()).unwrap());
},
);
}
#[test]
fn one_policy_written_twice_is_refused() {
let value = seq(&[seq(&[oid_of(ISSUER_POLICY)]), seq(&[oid_of(ISSUER_POLICY)])]);
let error = extension_error!(
extension(oid::CERTIFICATE_POLICIES, false, &value),
certificate_policies
);
assert_eq!(error.code(), ErrorCode::MalformedValue);
assert_eq!(error.field(), "extensions.certificatePolicies");
}
#[test]
fn a_qualifier_that_is_not_der_is_refused_before_it_is_preserved() {
use crate::fixtures::tlv;
for qualifier in [
seq(&[tlv(0x02, &[0x00, 0x01])]),
seq(&[seq(&[tlv(0x02, &[0x00, 0x01])])]),
seq(&[tlv(0x2c, b"\x0c\x01x")]),
tlv(0x31, &[int(2), int(1)].concat()),
] {
let value = seq(&[seq(&[
oid_of(ISSUER_POLICY),
seq(&[seq(&[oid_of(oid::CPS_QUALIFIER), qualifier.clone()])]),
])]);
extension_error!(
extension(oid::CERTIFICATE_POLICIES, false, &value),
certificate_policies
);
}
let qualifier = seq(&[int(1)]);
let value = seq(&[seq(&[
oid_of(ISSUER_POLICY),
seq(&[seq(&[oid_of(oid::CPS_QUALIFIER), qualifier.clone()])]),
])]);
with_extension(
extension(oid::CERTIFICATE_POLICIES, false, &value),
|list| {
let policies = list.certificate_policies(list.memory()).unwrap().unwrap();
assert_eq!(
policies.policies()[0].qualifiers()[0].value(),
&qualifier[..]
);
},
);
}
#[test]
fn a_list_of_no_policies_or_of_no_qualifiers_is_refused() {
let error = extension_error!(
extension(oid::CERTIFICATE_POLICIES, false, &seq(&[])),
certificate_policies
);
assert_eq!(error.code(), ErrorCode::EmptySequence);
let value = seq(&[seq(&[oid_of(ISSUER_POLICY), seq(&[])])]);
let error = extension_error!(
extension(oid::CERTIFICATE_POLICIES, false, &value),
certificate_policies
);
assert_eq!(error.code(), ErrorCode::EmptySequence);
}
#[test]
fn a_mapping_is_read_as_the_pair_it_is() {
let value = seq(&[seq(&[oid_of(ISSUER_POLICY), oid_of(OTHER_POLICY)])]);
with_extension(extension(oid::POLICY_MAPPINGS, false, &value), |list| {
let mappings = list.policy_mappings(list.memory()).unwrap().unwrap();
assert_eq!(mappings.mappings().len(), 1);
assert_eq!(mappings.mappings()[0].issuer_domain(), ISSUER_POLICY);
assert_eq!(mappings.mappings()[0].subject_domain(), OTHER_POLICY);
});
}
#[test]
fn mapping_the_identifier_that_stands_for_any_policy_is_refused() {
for pair in [
seq(&[oid_of(oid::ANY_POLICY), oid_of(OTHER_POLICY)]),
seq(&[oid_of(ISSUER_POLICY), oid_of(oid::ANY_POLICY)]),
] {
let error = extension_error!(
extension(oid::POLICY_MAPPINGS, false, &seq(&[pair])),
policy_mappings
);
assert_eq!(error.code(), ErrorCode::MalformedValue);
}
}
#[test]
fn a_mapping_missing_half_of_the_pair_is_refused() {
let value = seq(&[seq(&[oid_of(ISSUER_POLICY)])]);
let error = extension_error!(
extension(oid::POLICY_MAPPINGS, false, &value),
policy_mappings
);
assert_eq!(
error.code(),
ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedEnd)
);
}
#[test]
fn a_policy_that_is_not_shaped_like_one_is_refused() {
let error = extension_error!(
extension(oid::CERTIFICATE_POLICIES, false, &int(1)),
certificate_policies
);
assert_eq!(
error.code(),
ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag)
);
}
#[test]
fn one_issuer_policy_mapped_to_two_subject_policies_is_read() {
const THIRD_POLICY: Oid<'static> = Oid::from_bytes(&[0x2a, 0x86, 0x24, 0x01, 0x04]);
let value = seq(&[
seq(&[oid_of(ISSUER_POLICY), oid_of(OTHER_POLICY)]),
seq(&[oid_of(ISSUER_POLICY), oid_of(THIRD_POLICY)]),
]);
with_extension(extension(oid::POLICY_MAPPINGS, false, &value), |list| {
let mappings = list.policy_mappings(list.memory()).unwrap().unwrap();
assert_eq!(mappings.mappings().len(), 2);
assert_eq!(mappings.mappings()[0].subject_domain(), OTHER_POLICY);
assert_eq!(mappings.mappings()[1].subject_domain(), THIRD_POLICY);
});
}
#[test]
fn an_identical_mapping_written_twice_reads_once() {
let value = seq(&[
seq(&[oid_of(ISSUER_POLICY), oid_of(OTHER_POLICY)]),
seq(&[oid_of(ISSUER_POLICY), oid_of(OTHER_POLICY)]),
]);
with_extension(extension(oid::POLICY_MAPPINGS, false, &value), |list| {
let mappings = list.policy_mappings(list.memory()).unwrap().unwrap();
assert_eq!(mappings.mappings().len(), 1);
assert_eq!(mappings.mappings()[0].subject_domain(), OTHER_POLICY);
});
}