use rpki::data_model::oid::{OID_AD_CA_REPOSITORY, OID_AD_RPKI_MANIFEST, OID_AD_RPKI_NOTIFY}; use rpki::data_model::rc::{ AccessDescription, ResourceCertKind, ResourceCertificate, SubjectInfoAccess, SubjectInfoAccessCa, }; use rpki::validation::ca_instance::{CaInstanceUrisError, ca_instance_uris_from_ca_certificate}; fn apnic_child_ca_fixture_der() -> Vec { std::fs::read( "tests/fixtures/repository/rpki.apnic.net/repository/B527EF581D6611E2BB468F7C72FD1FF2/BfycW4hQb3wNP4YsiJW-1n6fjro.cer", ) .expect("read apnic fixture ca") } fn set_sia_ca(cert: &mut ResourceCertificate, ads: Vec) { cert.tbs.extensions.subject_info_access = Some(SubjectInfoAccess::Ca(SubjectInfoAccessCa { access_descriptions: ads })); } #[test] fn ca_instance_uris_success_and_error_branches() { let mut cert = ResourceCertificate::decode_der(&apnic_child_ca_fixture_der()) .expect("decode apnic fixture ca"); // Success path. let uris = ca_instance_uris_from_ca_certificate(&cert).expect("uris"); assert!(uris.rsync_base_uri.starts_with("rsync://")); assert!(uris.rsync_base_uri.ends_with('/')); assert!(uris.manifest_rsync_uri.starts_with("rsync://")); assert!(uris.manifest_rsync_uri.ends_with(".mft")); // NotCa. cert.kind = ResourceCertKind::Ee; let err = ca_instance_uris_from_ca_certificate(&cert).unwrap_err(); assert!(matches!(err, CaInstanceUrisError::NotCa)); cert.kind = ResourceCertKind::Ca; // MissingSia. cert.tbs.extensions.subject_info_access = None; let err = ca_instance_uris_from_ca_certificate(&cert).unwrap_err(); assert!(matches!(err, CaInstanceUrisError::MissingSia)); // MissingCaRepository / MissingRpkiManifest. set_sia_ca( &mut cert, vec![AccessDescription { access_method_oid: OID_AD_RPKI_MANIFEST.to_string(), access_location: "rsync://example.test/repo/x.mft".to_string(), }], ); let err = ca_instance_uris_from_ca_certificate(&cert).unwrap_err(); assert!(matches!(err, CaInstanceUrisError::MissingCaRepository), "{err}"); set_sia_ca( &mut cert, vec![AccessDescription { access_method_oid: OID_AD_CA_REPOSITORY.to_string(), access_location: "rsync://example.test/repo/".to_string(), }], ); let err = ca_instance_uris_from_ca_certificate(&cert).unwrap_err(); assert!(matches!(err, CaInstanceUrisError::MissingRpkiManifest), "{err}"); // Scheme validation branches. set_sia_ca( &mut cert, vec![AccessDescription { access_method_oid: OID_AD_CA_REPOSITORY.to_string(), access_location: "http://example.test/repo/".to_string(), }], ); let err = ca_instance_uris_from_ca_certificate(&cert).unwrap_err(); assert!(matches!(err, CaInstanceUrisError::CaRepositoryNotRsync(_)), "{err}"); set_sia_ca( &mut cert, vec![AccessDescription { access_method_oid: OID_AD_CA_REPOSITORY.to_string(), access_location: "rsync://example.test/repo/".to_string(), }, AccessDescription { access_method_oid: OID_AD_RPKI_MANIFEST.to_string(), access_location: "http://example.test/repo/x.mft".to_string(), }], ); let err = ca_instance_uris_from_ca_certificate(&cert).unwrap_err(); assert!(matches!(err, CaInstanceUrisError::RpkiManifestNotRsync(_)), "{err}"); set_sia_ca( &mut cert, vec![ AccessDescription { access_method_oid: OID_AD_CA_REPOSITORY.to_string(), access_location: "rsync://example.test/repo/".to_string(), }, AccessDescription { access_method_oid: OID_AD_RPKI_MANIFEST.to_string(), access_location: "rsync://example.test/repo/x.mft".to_string(), }, AccessDescription { access_method_oid: OID_AD_RPKI_NOTIFY.to_string(), access_location: "rsync://example.test/repo/notification.xml".to_string(), }, ], ); let err = ca_instance_uris_from_ca_certificate(&cert).unwrap_err(); assert!(matches!(err, CaInstanceUrisError::RpkiNotifyNotHttps(_)), "{err}"); // ManifestNotUnderPublicationPoint. set_sia_ca( &mut cert, vec![ AccessDescription { access_method_oid: OID_AD_CA_REPOSITORY.to_string(), access_location: "rsync://example.test/repo/".to_string(), }, AccessDescription { access_method_oid: OID_AD_RPKI_MANIFEST.to_string(), access_location: "rsync://other.test/repo/x.mft".to_string(), }, ], ); let err = ca_instance_uris_from_ca_certificate(&cert).unwrap_err(); assert!(matches!(err, CaInstanceUrisError::ManifestNotUnderPublicationPoint { .. }), "{err}"); }