use crate::{status_tracker::StatusTracker, validation_status};
pub(crate) struct X509StatusRemapGuard<'a> {
status_tracker: &'a mut StatusTracker,
first_new_item: usize,
}
impl<'a> X509StatusRemapGuard<'a> {
pub(crate) fn new(status_tracker: &'a mut StatusTracker) -> Self {
let first_new_item = status_tracker.logged_items().len();
Self {
status_tracker,
first_new_item,
}
}
pub(crate) fn status_tracker(&mut self) -> &mut StatusTracker {
self.status_tracker
}
}
impl Drop for X509StatusRemapGuard<'_> {
fn drop(&mut self) {
remap_x509_cose_status_codes(self.status_tracker, self.first_new_item);
}
}
fn remap_x509_cose_status_codes(status_tracker: &mut StatusTracker, first_new_item: usize) {
for item in status_tracker.logged_items_mut()[first_new_item..].iter_mut() {
let Some(old_code) = item.validation_status.as_deref() else {
continue;
};
let new_code = match old_code {
validation_status::ALGORITHM_UNSUPPORTED => {
validation_status::CAWG_X509_ALGORITHM_UNSUPPORTED
}
validation_status::SIGNING_CREDENTIAL_TRUSTED => {
validation_status::CAWG_X509_CREDENTIAL_TRUSTED
}
validation_status::SIGNING_CREDENTIAL_UNTRUSTED => {
validation_status::CAWG_X509_CREDENTIAL_UNTRUSTED
}
validation_status::SIGNING_CREDENTIAL_INVALID => {
validation_status::CAWG_X509_CREDENTIAL_INVALID
}
validation_status::SIGNING_CREDENTIAL_EXPIRED => {
validation_status::CAWG_X509_SIGNATURE_OUTSIDE_VALIDITY
}
validation_status::CLAIM_SIGNATURE_MISMATCH => {
validation_status::CAWG_X509_SIGNATURE_MISMATCH
}
_ => continue,
};
item.validation_status = Some(new_code.into());
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used)]
use super::*;
use crate::{log_item, status_tracker::StatusTracker};
fn status_of(tracker: &StatusTracker, index: usize) -> &str {
tracker.logged_items()[index]
.validation_status
.as_ref()
.unwrap()
.as_ref()
}
#[test]
fn remaps_known_c2pa_codes() {
let mut st = StatusTracker::default();
log_item!("l", "d", "f")
.validation_status(validation_status::ALGORITHM_UNSUPPORTED)
.informational(&mut st);
log_item!("l", "d", "f")
.validation_status(validation_status::SIGNING_CREDENTIAL_TRUSTED)
.success(&mut st);
log_item!("l", "d", "f")
.validation_status(validation_status::SIGNING_CREDENTIAL_UNTRUSTED)
.informational(&mut st);
log_item!("l", "d", "f")
.validation_status(validation_status::SIGNING_CREDENTIAL_INVALID)
.informational(&mut st);
log_item!("l", "d", "f")
.validation_status(validation_status::SIGNING_CREDENTIAL_EXPIRED)
.informational(&mut st);
log_item!("l", "d", "f")
.validation_status(validation_status::CLAIM_SIGNATURE_MISMATCH)
.informational(&mut st);
remap_x509_cose_status_codes(&mut st, 0);
assert_eq!(
status_of(&st, 0),
validation_status::CAWG_X509_ALGORITHM_UNSUPPORTED
);
assert_eq!(
status_of(&st, 1),
validation_status::CAWG_X509_CREDENTIAL_TRUSTED
);
assert_eq!(
status_of(&st, 2),
validation_status::CAWG_X509_CREDENTIAL_UNTRUSTED
);
assert_eq!(
status_of(&st, 3),
validation_status::CAWG_X509_CREDENTIAL_INVALID
);
assert_eq!(
status_of(&st, 4),
validation_status::CAWG_X509_SIGNATURE_OUTSIDE_VALIDITY
);
assert_eq!(
status_of(&st, 5),
validation_status::CAWG_X509_SIGNATURE_MISMATCH
);
}
#[test]
fn leaves_unrelated_and_missing_codes_untouched() {
let mut st = StatusTracker::default();
log_item!("l", "d", "f")
.validation_status("cawg.identity.pad.invalid")
.informational(&mut st);
log_item!("l", "d", "f").informational(&mut st);
remap_x509_cose_status_codes(&mut st, 0);
assert_eq!(status_of(&st, 0), "cawg.identity.pad.invalid");
assert!(st.logged_items()[1].validation_status.is_none());
}
#[test]
fn remap_guard_only_remaps_items_logged_during_its_scope() {
let mut st = StatusTracker::default();
log_item!("l", "d", "f")
.validation_status(validation_status::SIGNING_CREDENTIAL_UNTRUSTED)
.informational(&mut st);
{
let mut guard = X509StatusRemapGuard::new(&mut st);
log_item!("l", "d", "f")
.validation_status(validation_status::SIGNING_CREDENTIAL_TRUSTED)
.success(guard.status_tracker());
}
assert_eq!(
status_of(&st, 0),
validation_status::SIGNING_CREDENTIAL_UNTRUSTED
);
assert_eq!(
status_of(&st, 1),
validation_status::CAWG_X509_CREDENTIAL_TRUSTED
);
}
}