串行验证通过
This commit is contained in:
146
src/validation/from_tal.rs
Normal file
146
src/validation/from_tal.rs
Normal file
@@ -0,0 +1,146 @@
|
||||
use url::Url;
|
||||
|
||||
use crate::data_model::ta::{TrustAnchor, TrustAnchorError};
|
||||
use crate::data_model::tal::{Tal, TalDecodeError};
|
||||
use crate::sync::rrdp::Fetcher;
|
||||
use crate::validation::ca_instance::{CaInstanceUris, CaInstanceUrisError, ca_instance_uris_from_ca_certificate};
|
||||
use crate::validation::objects::IssuerCaCertificateResolver;
|
||||
use crate::validation::run::{RunError, RunOutput, run_publication_point_once};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct DiscoveredRootCaInstance {
|
||||
pub tal_url: Option<String>,
|
||||
pub trust_anchor: TrustAnchor,
|
||||
pub ca_instance: CaInstanceUris,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct RunFromTalOutput {
|
||||
pub discovery: DiscoveredRootCaInstance,
|
||||
pub run: RunOutput,
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum FromTalError {
|
||||
#[error("TAL fetch failed: {0} (RFC 8630 §2.2)")]
|
||||
TalFetch(String),
|
||||
|
||||
#[error("TAL decode failed: {0} (RFC 8630 §2.2)")]
|
||||
TalDecode(#[from] TalDecodeError),
|
||||
|
||||
#[error("failed to fetch TA certificate from TAL: {0} (RFC 8630 §2.3)")]
|
||||
TaFetch(String),
|
||||
|
||||
#[error("failed to bind TAL and TA certificate: {0} (RFC 8630 §2.3)")]
|
||||
Bind(#[from] TrustAnchorError),
|
||||
|
||||
#[error("failed to discover CA instance URIs from TA certificate: {0}")]
|
||||
CaInstanceUris(#[from] CaInstanceUrisError),
|
||||
|
||||
#[error("run failed: {0}")]
|
||||
Run(#[from] RunError),
|
||||
|
||||
#[error("TAL contains no TA URIs (RFC 8630 §2.2)")]
|
||||
NoTaUris,
|
||||
}
|
||||
|
||||
pub fn discover_root_ca_instance_from_tal_url(
|
||||
http_fetcher: &dyn Fetcher,
|
||||
tal_url: &str,
|
||||
) -> Result<DiscoveredRootCaInstance, FromTalError> {
|
||||
let tal_bytes = http_fetcher
|
||||
.fetch(tal_url)
|
||||
.map_err(FromTalError::TalFetch)?;
|
||||
let tal = Tal::decode_bytes(&tal_bytes)?;
|
||||
discover_root_ca_instance_from_tal(http_fetcher, tal, Some(tal_url.to_string()))
|
||||
}
|
||||
|
||||
pub fn discover_root_ca_instance_from_tal(
|
||||
http_fetcher: &dyn Fetcher,
|
||||
tal: Tal,
|
||||
tal_url: Option<String>,
|
||||
) -> Result<DiscoveredRootCaInstance, FromTalError> {
|
||||
if tal.ta_uris.is_empty() {
|
||||
return Err(FromTalError::NoTaUris);
|
||||
}
|
||||
|
||||
let mut last_err: Option<String> = None;
|
||||
for ta_uri in tal.ta_uris.iter() {
|
||||
let ta_der = match http_fetcher.fetch(ta_uri.as_str()) {
|
||||
Ok(b) => b,
|
||||
Err(e) => {
|
||||
last_err = Some(format!("fetch {ta_uri} failed: {e}"));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let trust_anchor = match TrustAnchor::bind_der(tal.clone(), &ta_der, Some(ta_uri)) {
|
||||
Ok(ta) => ta,
|
||||
Err(e) => {
|
||||
last_err = Some(format!("bind {ta_uri} failed: {e}"));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let ca_instance = match ca_instance_uris_from_ca_certificate(&trust_anchor.ta_certificate.rc_ca)
|
||||
{
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
last_err = Some(format!("CA instance discovery failed: {e}"));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
return Ok(DiscoveredRootCaInstance {
|
||||
tal_url,
|
||||
trust_anchor,
|
||||
ca_instance,
|
||||
});
|
||||
}
|
||||
|
||||
Err(FromTalError::TaFetch(
|
||||
last_err.unwrap_or_else(|| "unknown TA candidate error".to_string()),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn discover_root_ca_instance_from_tal_and_ta_der(
|
||||
tal_bytes: &[u8],
|
||||
ta_der: &[u8],
|
||||
resolved_ta_uri: Option<&Url>,
|
||||
) -> Result<DiscoveredRootCaInstance, FromTalError> {
|
||||
let tal = Tal::decode_bytes(tal_bytes)?;
|
||||
let trust_anchor = TrustAnchor::bind_der(tal, ta_der, resolved_ta_uri)?;
|
||||
let ca_instance = ca_instance_uris_from_ca_certificate(&trust_anchor.ta_certificate.rc_ca)?;
|
||||
Ok(DiscoveredRootCaInstance {
|
||||
tal_url: None,
|
||||
trust_anchor,
|
||||
ca_instance,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn run_root_from_tal_url_once(
|
||||
store: &crate::storage::RocksStore,
|
||||
policy: &crate::policy::Policy,
|
||||
tal_url: &str,
|
||||
http_fetcher: &dyn Fetcher,
|
||||
rsync_fetcher: &dyn crate::fetch::rsync::RsyncFetcher,
|
||||
issuer_resolver: &dyn IssuerCaCertificateResolver,
|
||||
validation_time: time::OffsetDateTime,
|
||||
) -> Result<RunFromTalOutput, FromTalError> {
|
||||
let discovery = discover_root_ca_instance_from_tal_url(http_fetcher, tal_url)?;
|
||||
|
||||
let run = run_publication_point_once(
|
||||
store,
|
||||
policy,
|
||||
discovery.ca_instance.rrdp_notification_uri.as_deref(),
|
||||
&discovery.ca_instance.rsync_base_uri,
|
||||
&discovery.ca_instance.manifest_rsync_uri,
|
||||
&discovery.ca_instance.publication_point_rsync_uri,
|
||||
http_fetcher,
|
||||
rsync_fetcher,
|
||||
issuer_resolver,
|
||||
validation_time,
|
||||
)?;
|
||||
|
||||
Ok(RunFromTalOutput { discovery, run })
|
||||
}
|
||||
Reference in New Issue
Block a user