rpki/tests/test_manifest_rfc9286_section6_1.rs
2026-02-11 10:07:24 +08:00

78 lines
3.0 KiB
Rust

use std::path::Path;
use rpki::data_model::manifest::ManifestObject;
use rpki::policy::{CaFailedFetchPolicy, Policy};
use rpki::storage::{FetchCachePpKey, RocksStore};
use rpki::validation::manifest::process_manifest_publication_point;
fn issuer_ca_fixture() -> Vec<u8> {
std::fs::read(
"tests/fixtures/repository/rpki.apnic.net/repository/B527EF581D6611E2BB468F7C72FD1FF2/BfycW4hQb3wNP4YsiJW-1n6fjro.cer",
)
.expect("read issuer ca fixture")
}
fn issuer_ca_rsync_uri() -> &'static str {
"rsync://rpki.apnic.net/repository/B527EF581D6611E2BB468F7C72FD1FF2/BfycW4hQb3wNP4YsiJW-1n6fjro.cer"
}
#[test]
fn manifest_outside_publication_point_is_failed_fetch_rfc9286_section6_1() {
let fixture_manifest_path = Path::new(
"tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft",
);
let fixture_dir = fixture_manifest_path.parent().expect("fixture dir");
let manifest_bytes = std::fs::read(fixture_manifest_path).expect("read manifest fixture");
let manifest = ManifestObject::decode_der(&manifest_bytes).expect("decode manifest fixture");
let validation_time = manifest.manifest.this_update + time::Duration::seconds(1);
// Intentionally mismatch: manifest is NOT under the publication point URI.
let manifest_rsync_uri = "rsync://example.test/a/manifest.mft";
let publication_point_rsync_uri = "rsync://example.test/b/";
let temp = tempfile::tempdir().expect("tempdir");
let store = RocksStore::open(temp.path()).expect("open rocksdb");
// Store the manifest at its rsync URI.
store
.put_raw(manifest_rsync_uri, &manifest_bytes)
.expect("store manifest raw");
// Store all referenced files under the (different) publication point so that §6.4/§6.5
// would otherwise succeed if §6.1 was not enforced.
for entry in &manifest.manifest.files {
let file_path = fixture_dir.join(&entry.file_name);
let bytes = std::fs::read(&file_path)
.unwrap_or_else(|_| panic!("read fixture file referenced by manifest: {file_path:?}"));
let rsync_uri = format!("{publication_point_rsync_uri}{}", entry.file_name);
store.put_raw(&rsync_uri, &bytes).expect("store file raw");
}
let mut policy = Policy::default();
policy.ca_failed_fetch_policy = CaFailedFetchPolicy::StopAllOutput;
let issuer_ca_der = issuer_ca_fixture();
let err = process_manifest_publication_point(
&store,
&policy,
manifest_rsync_uri,
publication_point_rsync_uri,
&issuer_ca_der,
Some(issuer_ca_rsync_uri()),
validation_time,
)
.expect_err("§6.1 mismatch must be treated as failed fetch");
let msg = err.to_string();
assert!(msg.contains("RFC 9286 §6.1"), "{msg}");
let key = FetchCachePpKey::from_manifest_rsync_uri(manifest_rsync_uri);
assert!(
store
.get_fetch_cache_pp(&key)
.expect("get fetch_cache_pp")
.is_none(),
"must not write fetch_cache_pp on failed fetch"
);
}