use super::super::*;
const TOPLEVEL_DOCTYPE_FOR_ERROR: &str =
ns_expr!("NetworkStatusVote", "NetworkStatusNs", "NetworkStatusMd",);
pub type Router = ns_type!(
crate::doc::netstatus::VoteRouterStatus,
crate::doc::netstatus::PlainRouterStatus,
crate::doc::netstatus::MdRouterStatus,
);
pub type NddDirectoryFooter = ns_type!(
crate::doc::netstatus::VoteFooter,
crate::doc::netstatus::PlainFooter,
crate::doc::netstatus::MdFooter,
);
pub type NetworkStatusSignatures = ns_type!(
crate::doc::netstatus::vote::NetworkStatusSignatures,
crate::doc::netstatus::plain::NetworkStatusSignatures,
crate::doc::netstatus::md::NetworkStatusSignatures,
);
pub type NetworkStatusVersionItem = ns_type!(
crate::doc::netstatus::vote::NetworkStatusVersionItem,
crate::doc::netstatus::plain::NetworkStatusVersionItem,
crate::doc::netstatus::md::NetworkStatusVersionItem,
);
#[derive(Deftly, Clone, Debug)]
#[derive_deftly(NetdocParseableUnverified)]
#[deftly(netdoc(doctype_for_error = TOPLEVEL_DOCTYPE_FOR_ERROR))]
#[non_exhaustive]
pub struct NetworkStatus {
pub network_status_version: NetworkStatusVersionItem,
pub vote_status: NdiVoteStatus,
pub published: ns_type!((NdaSystemTimeDeprecatedSyntax,), Option<Void>,),
pub valid_after: (NdaSystemTimeDeprecatedSyntax,),
pub valid_until: (NdaSystemTimeDeprecatedSyntax,),
pub voting_delay: NdiVotingDelay,
#[deftly(netdoc(default))]
pub params: NdiParams,
#[deftly(netdoc(subdoc))]
pub authority: NddAuthoritySection,
#[deftly(netdoc(subdoc))]
pub r: Vec<Router>,
#[deftly(netdoc(subdoc))]
pub directory_footer: Option<NddDirectoryFooter>,
}
#[derive(Deftly, Clone, Debug, Hash, Eq, PartialEq)]
#[derive_deftly(ItemValueParseable)]
#[non_exhaustive]
pub struct NdiVoteStatus {
pub status: ns_type!(VoteStatusVote, VoteStatusConsensus, VoteStatusConsensus),
}
#[derive(Deftly, Clone, Debug, Hash, Eq, PartialEq)]
#[derive_deftly(ItemValueParseable)]
#[non_exhaustive]
pub struct NdiVotingDelay {
pub vote_seconds: u32,
pub dist_seconds: u32,
}
#[derive(Deftly, Clone, Debug)]
#[derive_deftly(ItemValueParseable)]
#[non_exhaustive]
pub struct NdiAuthorityDirSource {
pub nickname: types::Nickname,
pub h_p_auth_id_rsa: types::Fingerprint,
}
ns_choose! { (
use VoteAuthoritySection as NddAuthoritySection;
)(
use ConsensusAuthoritySection as NddAuthoritySection;
)}
ns_choose! { (
impl NetworkStatusUnverified {
pub fn verify_selfcert(
self,
now: SystemTime,
) -> Result<(NetworkStatus, SignaturesData<NetworkStatusUnverified>), VF> {
let validity = *self.body.published.0 ..= *self.body.valid_until.0;
check_validity_time(now, validity)?;
let cert = self.body.parse_authcert()?.verify_selfcert(now)?;
netstatus::verify_general_timeless(
&self.sigs.hashes,
slice::from_ref(&self.sigs.sigs.directory_signature),
&[*cert.fingerprint],
&[&cert],
1,
)?;
Ok(self.unwrap_unverified())
}
}
impl NetworkStatus {
fn parse_authcert(&self) -> Result<crate::doc::authcert::AuthCertUnverified, EP> {
let cert_input = ParseInput::new(
self.authority.cert.as_str(),
"<embedded auth cert>",
);
parse_netdoc(&cert_input).map_err(|e| e.problem)
}
pub fn h_kp_auth_id_rsa(&self) -> pk::rsa::RsaIdentity {
*self.parse_authcert()
.expect("was verified already!")
.inspect_unverified()
.0
.fingerprint
}
}
) (
impl NetworkStatusUnverified {
pub fn verify(
self,
now: SystemTime,
authorities: &[pk::rsa::RsaIdentity],
certs: &[&DirAuthKeyCert],
) -> Result<(NetworkStatus, SignaturesData<NetworkStatusUnverified>), VF> {
let threshold = authorities.len() / 2 + 1; let validity_start = self.body.valid_after.0
.checked_sub(Duration::from_secs(self.body.voting_delay.dist_seconds.into()))
.ok_or(VF::Other)?;
check_validity_time(now, validity_start..= *self.body.valid_until.0)?;
netstatus::verify_general_timeless(
&self.sigs.hashes,
&self.sigs.sigs.directory_signature,
authorities,
certs,
threshold,
)?;
Ok(self.unwrap_unverified())
}
}
)}