tor_netdoc/parse2/poc/netstatus/
flavoured.rs1use super::super::*;
15
16const TOPLEVEL_DOCTYPE_FOR_ERROR: &str =
18 ns_expr!("NetworkStatusVote", "NetworkStatusNs", "NetworkStatusMd",);
19
20pub type Router = ns_type!(
22 crate::doc::netstatus::VoteRouterStatus,
23 crate::doc::netstatus::PlainRouterStatus,
24 crate::doc::netstatus::MdRouterStatus,
25);
26
27pub type NddDirectoryFooter = ns_type!(
29 crate::doc::netstatus::VoteFooter,
30 crate::doc::netstatus::PlainFooter,
31 crate::doc::netstatus::MdFooter,
32);
33
34pub type NetworkStatusSignatures = ns_type!(
36 crate::doc::netstatus::vote::NetworkStatusSignatures,
37 crate::doc::netstatus::plain::NetworkStatusSignatures,
38 crate::doc::netstatus::md::NetworkStatusSignatures,
39);
40
41pub type NetworkStatusVersionItem = ns_type!(
43 crate::doc::netstatus::vote::NetworkStatusVersionItem,
44 crate::doc::netstatus::plain::NetworkStatusVersionItem,
45 crate::doc::netstatus::md::NetworkStatusVersionItem,
46);
47
48#[derive(Deftly, Clone, Debug)]
53#[derive_deftly(NetdocParseableUnverified)]
54#[deftly(netdoc(doctype_for_error = TOPLEVEL_DOCTYPE_FOR_ERROR))]
55#[non_exhaustive]
56pub struct NetworkStatus {
57 pub network_status_version: NetworkStatusVersionItem,
59
60 pub vote_status: NdiVoteStatus,
62
63 pub published: ns_type!((NdaSystemTimeDeprecatedSyntax,), Option<Void>,),
65
66 pub valid_after: (NdaSystemTimeDeprecatedSyntax,),
68
69 pub valid_until: (NdaSystemTimeDeprecatedSyntax,),
71
72 pub voting_delay: NdiVotingDelay,
74
75 #[deftly(netdoc(default))]
77 pub params: NdiParams,
78
79 #[deftly(netdoc(subdoc))]
81 pub authority: NddAuthoritySection,
82
83 #[deftly(netdoc(subdoc))]
85 pub r: Vec<Router>,
86
87 #[deftly(netdoc(subdoc))]
89 pub directory_footer: Option<NddDirectoryFooter>,
90}
91
92#[derive(Deftly, Clone, Debug, Hash, Eq, PartialEq)]
98#[derive_deftly(ItemValueParseable)]
99#[non_exhaustive]
100pub struct NdiVoteStatus {
101 pub status: ns_type!(VoteStatusVote, VoteStatusConsensus, VoteStatusConsensus),
103}
104
105#[derive(Deftly, Clone, Debug, Hash, Eq, PartialEq)]
107#[derive_deftly(ItemValueParseable)]
108#[non_exhaustive]
109pub struct NdiVotingDelay {
110 pub vote_seconds: u32,
112 pub dist_seconds: u32,
114}
115
116#[derive(Deftly, Clone, Debug)]
118#[derive_deftly(ItemValueParseable)]
119#[non_exhaustive]
120pub struct NdiAuthorityDirSource {
121 pub nickname: types::Nickname,
123 pub h_p_auth_id_rsa: types::Fingerprint,
125}
126
127ns_choose! { (
128 use VoteAuthoritySection as NddAuthoritySection;
129)(
130 use ConsensusAuthoritySection as NddAuthoritySection;
131)}
132
133ns_choose! { (
134 impl NetworkStatusUnverified {
135 pub fn verify_selfcert(
142 self,
143 now: SystemTime,
144 ) -> Result<(NetworkStatus, SignaturesData<NetworkStatusUnverified>), VF> {
145 let validity = *self.body.published.0 ..= *self.body.valid_until.0;
146 check_validity_time(now, validity)?;
147
148 let cert = self.body.parse_authcert()?.verify_selfcert(now)?;
149
150 netstatus::verify_general_timeless(
151 &self.sigs.hashes,
152 slice::from_ref(&self.sigs.sigs.directory_signature),
153 &[*cert.fingerprint],
154 &[&cert],
155 1,
156 )?;
157
158 Ok(self.unwrap_unverified())
159 }
160 }
161
162 impl NetworkStatus {
163 fn parse_authcert(&self) -> Result<crate::doc::authcert::AuthCertUnverified, EP> {
165 let cert_input = ParseInput::new(
166 self.authority.cert.as_str(),
167 "<embedded auth cert>",
168 );
169 parse_netdoc(&cert_input).map_err(|e| e.problem)
170 }
171
172 pub fn h_kp_auth_id_rsa(&self) -> pk::rsa::RsaIdentity {
182 *self.parse_authcert()
183 .expect("was verified already!")
187 .inspect_unverified()
188 .0
189 .fingerprint
190 }
191 }
192) (
193 impl NetworkStatusUnverified {
194 pub fn verify(
210 self,
211 now: SystemTime,
212 authorities: &[pk::rsa::RsaIdentity],
213 certs: &[&DirAuthKeyCert],
214 ) -> Result<(NetworkStatus, SignaturesData<NetworkStatusUnverified>), VF> {
215 let threshold = authorities.len() / 2 + 1; let validity_start = self.body.valid_after.0
217 .checked_sub(Duration::from_secs(self.body.voting_delay.dist_seconds.into()))
218 .ok_or(VF::Other)?;
219 check_validity_time(now, validity_start..= *self.body.valid_until.0)?;
220
221 netstatus::verify_general_timeless(
222 &self.sigs.hashes,
223 &self.sigs.sigs.directory_signature,
224 authorities,
225 certs,
226 threshold,
227 )?;
228
229 Ok(self.unwrap_unverified())
230 }
231 }
232)}