1use crate::parse::keyword::Keyword;
36use crate::parse::parser::{Section, SectionRules};
37use crate::parse::tokenize::{ItemResult, NetDocReader};
38use crate::parse2::{ArgumentError, ArgumentStream, ItemArgumentParseable};
39use crate::types::family::{RelayFamily, RelayFamilyIds};
40use crate::types::policy::*;
41use crate::types::routerdesc::*;
42use crate::types::version::TorVersion;
43use crate::types::{EmbeddedCert, misc::*};
44use crate::util::PeekableIterator;
45use crate::{AllowAnnotations, Error, KeywordEncodable, NetdocErrorKind as EK, Result};
46
47use derive_deftly::Deftly;
48use ll::pk::ed25519::Ed25519Identity;
49use saturating_time::SaturatingTime;
50use std::sync::Arc;
51use std::sync::LazyLock;
52use std::{iter, net, time};
53use tor_cert::{CertType, KeyUnknownCert};
54use tor_checkable::{Timebound, signed, timed};
55use tor_error::{internal, into_internal};
56use tor_llcrypto as ll;
57use tor_llcrypto::pk::rsa::RsaIdentity;
58
59use digest::Digest;
60
61pub const DOC_DIGEST_LEN: usize = 20;
63
64pub type RdDigest = [u8; DOC_DIGEST_LEN];
66
67pub type ExtraInfoDigest = [u8; DOC_DIGEST_LEN];
69
70#[non_exhaustive]
72pub struct AnnotatedRouterDesc {
73 pub ann: RouterAnnotation,
75 pub router: UncheckedRouterDesc,
77}
78
79#[derive(Default)]
81#[non_exhaustive]
82pub struct RouterAnnotation {
83 pub source: Option<String>,
85 pub downloaded: Option<time::SystemTime>,
87 pub purpose: Option<String>,
89}
90
91#[derive(Clone, Debug)]
109#[non_exhaustive]
110pub struct RouterDesc {
111 pub router: RouterDescIntroItem,
115
116 pub identity_ed25519: EmbeddedCert<Ed25519IdentityCert, KeyUnknownCert>,
120
121 pub master_key_ed25519: Ed25519Public,
127
128 pub bandwidth: Bandwidth,
133
134 pub platform: Option<RelayPlatform>,
139
140 pub published: Iso8601TimeSp,
145
146 pub fingerprint: Option<SpFingerprint>,
151
152 pub uptime: Option<u64>,
157
158 pub onion_key: Option<ll::pk::rsa::PublicKey>,
164
165 pub ntor_onion_key: Curve25519Public,
170
171 pub signing_key: ll::pk::rsa::PublicKey,
175
176 pub ipv4_policy: AddrPolicy,
184
185 pub ipv6_policy: Arc<PortPolicy>,
190
191 pub family: Arc<RelayFamily>,
197
198 pub family_cert: RetainedOrderVec<EmbeddedCert<Ed25519FamilyCert, KeyUnknownCert>>,
203
204 pub caches_extra_info: bool,
210
211 pub or_address: Vec<net::SocketAddr>,
215
216 pub tunnelled_dir_server: bool,
222
223 pub proto: tor_protover::Protocols,
228}
229
230#[derive(Clone, Debug, Deftly)]
234#[derive_deftly(NetdocParseableSignatures)]
235#[deftly(netdoc(signatures(hashes_accu = "RouterHashAccu")))]
236#[non_exhaustive]
237pub struct RouterDescSignatures {
238 pub router_sig_ed25519: RouterSigEd25519,
244
245 pub router_signature: RouterSignature,
250}
251
252#[derive(Debug, Clone, PartialEq, Eq)]
255#[non_exhaustive]
256pub enum RelayPlatform {
257 Tor(TorVersion, String),
259 Other(String),
261}
262
263impl std::str::FromStr for RelayPlatform {
264 type Err = Error;
265 fn from_str(args: &str) -> Result<Self> {
266 if args.starts_with("Tor ") {
267 let v: Vec<_> = args.splitn(4, ' ').collect();
268 match &v[..] {
269 ["Tor", ver, "on", p] => Ok(RelayPlatform::Tor(ver.parse()?, (*p).to_string())),
270 ["Tor", ver, ..] => Ok(RelayPlatform::Tor(ver.parse()?, "".to_string())),
271 _ => unreachable!(),
272 }
273 } else {
274 Ok(RelayPlatform::Other(args.to_string()))
275 }
276 }
277}
278
279impl ItemArgumentParseable for RelayPlatform {
280 fn from_args<'s>(args: &mut ArgumentStream<'s>) -> std::result::Result<Self, ArgumentError> {
281 args.into_remaining()
282 .parse()
283 .map_err(|_| ArgumentError::Invalid)
284 }
285}
286
287decl_keyword! {
288 RouterKwd {
291 annotation "@source" => ANN_SOURCE,
292 annotation "@downloaded-at" => ANN_DOWNLOADED_AT,
293 annotation "@purpose" => ANN_PURPOSE,
294 "accept" | "reject" => POLICY,
295 "bandwidth" => BANDWIDTH,
296 "bridge-distribution-request" => BRIDGE_DISTRIBUTION_REQUEST,
297 "caches-extra-info" => CACHES_EXTRA_INFO,
298 "contact" => CONTACT,
299 "extra-info-digest" => EXTRA_INFO_DIGEST,
300 "family" => FAMILY,
301 "family-cert" => FAMILY_CERT,
302 "fingerprint" => FINGERPRINT,
303 "hibernating" => HIBERNATING,
304 "identity-ed25519" => IDENTITY_ED25519,
305 "ipv6-policy" => IPV6_POLICY,
306 "master-key-ed25519" => MASTER_KEY_ED25519,
307 "ntor-onion-key" => NTOR_ONION_KEY,
308 "ntor-onion-key-crosscert" => NTOR_ONION_KEY_CROSSCERT,
309 "onion-key" => ONION_KEY,
310 "onion-key-crosscert" => ONION_KEY_CROSSCERT,
311 "or-address" => OR_ADDRESS,
312 "platform" => PLATFORM,
313 "proto" => PROTO,
314 "published" => PUBLISHED,
315 "router" => ROUTER,
316 "router-sig-ed25519" => ROUTER_SIG_ED25519,
317 "router-signature" => ROUTER_SIGNATURE,
318 "signing-key" => SIGNING_KEY,
319 "tunnelled_dir_server" => TUNNELLED_DIR_SERVER,
320 "uptime" => UPTIME,
321 }
325}
326
327static ROUTER_ANNOTATIONS: LazyLock<SectionRules<RouterKwd>> = LazyLock::new(|| {
329 use RouterKwd::*;
330
331 let mut rules = SectionRules::builder();
332 rules.add(ANN_SOURCE.rule());
333 rules.add(ANN_DOWNLOADED_AT.rule().args(1..));
334 rules.add(ANN_PURPOSE.rule().args(1..));
335 rules.add(ANN_UNRECOGNIZED.rule().may_repeat().obj_optional());
336 rules.reject_unrecognized();
339 rules.build()
340});
341static ROUTER_HEADER_RULES: LazyLock<SectionRules<RouterKwd>> = LazyLock::new(|| {
344 use RouterKwd::*;
345
346 let mut rules = SectionRules::builder();
347 rules.add(ROUTER.rule().required().args(5..));
348 rules.add(IDENTITY_ED25519.rule().required().no_args().obj_required());
349 rules.reject_unrecognized();
351 rules.build()
352});
353static ROUTER_BODY_RULES: LazyLock<SectionRules<RouterKwd>> = LazyLock::new(|| {
356 use RouterKwd::*;
357
358 let mut rules = SectionRules::builder();
359 rules.add(MASTER_KEY_ED25519.rule().required().args(1..));
360 rules.add(PLATFORM.rule());
361 rules.add(PUBLISHED.rule().required());
362 rules.add(FINGERPRINT.rule());
363 rules.add(UPTIME.rule().args(1..));
364 rules.add(ONION_KEY.rule().no_args().obj_required());
365 rules.add(ONION_KEY_CROSSCERT.rule().no_args().obj_required());
366 rules.add(NTOR_ONION_KEY.rule().required().args(1..));
367 rules.add(
368 NTOR_ONION_KEY_CROSSCERT
369 .rule()
370 .required()
371 .args(1..=1)
372 .obj_required(),
373 );
374 rules.add(SIGNING_KEY.rule().no_args().required().obj_required());
375 rules.add(POLICY.rule().may_repeat().args(1..));
376 rules.add(IPV6_POLICY.rule().args(2..));
377 rules.add(FAMILY.rule().args(1..));
378 rules.add(FAMILY_CERT.rule().obj_required().may_repeat());
379 rules.add(CACHES_EXTRA_INFO.rule().no_args());
380 rules.add(OR_ADDRESS.rule().may_repeat().args(1..));
381 rules.add(TUNNELLED_DIR_SERVER.rule());
382 rules.add(PROTO.rule().required().args(1..));
383 rules.add(UNRECOGNIZED.rule().may_repeat().obj_optional());
384 {
386 rules.add(BANDWIDTH.rule().required().args(3..));
387 rules.add(BRIDGE_DISTRIBUTION_REQUEST.rule().args(1..));
388 rules.add(HIBERNATING.rule().args(1..));
389 rules.add(CONTACT.rule());
390 }
391 {
393 rules.add(EXTRA_INFO_DIGEST.rule().args(1..));
394 }
395 rules.build()
396});
397
398static ROUTER_SIG_RULES: LazyLock<SectionRules<RouterKwd>> = LazyLock::new(|| {
400 use RouterKwd::*;
401
402 let mut rules = SectionRules::builder();
403 rules.add(ROUTER_SIG_ED25519.rule().required().args(1..));
404 rules.add(ROUTER_SIGNATURE.rule().required().no_args().obj_required());
405 rules.reject_unrecognized();
407 rules.build()
408});
409
410impl RouterAnnotation {
411 fn take_from_reader(reader: &mut NetDocReader<'_, RouterKwd>) -> Result<RouterAnnotation> {
413 use RouterKwd::*;
414 let mut items = reader.pause_at(|item| item.is_ok_with_non_annotation());
415
416 let body = ROUTER_ANNOTATIONS.parse(&mut items)?;
417
418 let source = body.maybe(ANN_SOURCE).args_as_str().map(String::from);
419 let purpose = body.maybe(ANN_PURPOSE).args_as_str().map(String::from);
420 let downloaded = body
421 .maybe(ANN_DOWNLOADED_AT)
422 .parse_args_as_str::<Iso8601TimeSp>()?
423 .map(|t| t.into());
424 Ok(RouterAnnotation {
425 source,
426 downloaded,
427 purpose,
428 })
429 }
430}
431
432pub type UncheckedRouterDesc = signed::SignatureGated<timed::TimerangeBound<RouterDesc>>;
435
436const ROUTER_EXPIRY_SECONDS: u64 = 5 * 86400;
439
440const ROUTER_PRE_VALIDITY_SECONDS: u64 = 86400;
446
447impl RouterDesc {
448 pub fn rsa_identity(&self) -> RsaIdentity {
450 self.signing_key.to_rsa_identity()
451 }
452
453 pub fn ed_identity(&self) -> &Ed25519Identity {
455 &self
456 .identity_ed25519
457 .get()
458 .expect("ed25519 identity cert should be verified")
459 .id_ed25519
460 }
461
462 pub fn protocols(&self) -> &tor_protover::Protocols {
465 &self.proto
466 }
467
468 pub fn ntor_onion_key(&self) -> &ll::pk::curve25519::PublicKey {
470 &self.ntor_onion_key.0
471 }
472
473 pub fn published(&self) -> time::SystemTime {
475 self.published.0
476 }
477
478 pub fn or_ports(&self) -> impl Iterator<Item = net::SocketAddr> + '_ {
481 iter::once(net::SocketAddr::new(
482 self.router.address.into(),
483 self.router.orport,
484 ))
485 .chain(self.or_address.iter().copied())
486 }
487
488 pub fn family(&self) -> Arc<RelayFamily> {
490 Arc::clone(&self.family)
491 }
492
493 pub fn family_ids(&self) -> RelayFamilyIds {
495 RelayFamilyIds::from_iter(
496 self.family_cert
497 .iter()
498 .map(|cert| cert.get().expect("unverified family cert?"))
499 .map(|cert| cert.family_ed25519.into()),
500 )
501 }
502
503 fn parse_sections<'a>(
505 reader: &mut NetDocReader<'a, RouterKwd>,
506 ) -> Result<(
507 Section<'a, RouterKwd>,
508 Section<'a, RouterKwd>,
509 Section<'a, RouterKwd>,
510 )> {
511 use RouterKwd::*;
512
513 let header = ROUTER_HEADER_RULES.parse(
515 reader.pause_at(|item| item.is_ok_with_kwd_not_in(&[ROUTER, IDENTITY_ED25519])),
516 )?;
517
518 let body =
520 ROUTER_BODY_RULES.parse(reader.pause_at(|item| {
521 item.is_ok_with_kwd_in(&[ROUTER_SIGNATURE, ROUTER_SIG_ED25519])
522 }))?;
523
524 let sig = ROUTER_SIG_RULES.parse(reader.pause_at(|item| {
526 item.is_ok_with_annotation() || item.is_ok_with_kwd(ROUTER) || item.is_empty_line()
527 }))?;
528
529 Ok((header, body, sig))
530 }
531
532 pub fn parse(s: &str) -> Result<UncheckedRouterDesc> {
544 let mut reader = crate::parse::tokenize::NetDocReader::new(s)?;
545 let result = Self::parse_internal(&mut reader).map_err(|e| e.within(s))?;
546 reader
549 .should_be_exhausted_but_for_empty_lines()
550 .map_err(|e| e.within(s))?;
551 Ok(result)
552 }
553
554 fn parse_internal(r: &mut NetDocReader<'_, RouterKwd>) -> Result<UncheckedRouterDesc> {
560 use RouterKwd::*;
563
564 let s = r.str();
565 let (header, body, sig) = RouterDesc::parse_sections(r)?;
566
567 #[allow(clippy::unwrap_used)]
570 let start_offset = header.required(ROUTER)?.offset_in(s).unwrap();
571
572 let (ku_identity_cert, identity_cert, ed25519_signing_key) = {
586 let cert_tok = header.required(IDENTITY_ED25519)?;
587 #[allow(clippy::unwrap_used)]
590 if cert_tok.offset_in(s).unwrap() < start_offset {
591 return Err(EK::MisplacedToken
592 .with_msg("identity-ed25519")
593 .at_pos(cert_tok.pos()));
594 }
595 let ku_cert = cert_tok
596 .parse_obj::<UnvalidatedEdCert>("ED25519 CERT")?
597 .check_cert_type(tor_cert::CertType::IDENTITY_V_SIGNING)?
598 .into_unchecked();
599 let cert = ku_cert.clone().should_have_signing_key().map_err(|err| {
600 EK::BadObjectVal
601 .err()
602 .with_source(err)
603 .at_pos(cert_tok.pos())
604 })?;
605 let sk = *cert.peek_subject_key().as_ed25519().ok_or_else(|| {
606 EK::BadObjectVal
607 .at_pos(cert_tok.pos())
608 .with_msg("wrong type for signing key in cert")
609 })?;
610 let sk: ll::pk::ed25519::PublicKey = sk.try_into().map_err(|_| {
611 EK::BadObjectVal
612 .at_pos(cert_tok.pos())
613 .with_msg("invalid ed25519 signing key")
614 })?;
615 (ku_cert, cert, sk)
616 };
617
618 #[allow(unexpected_cfgs)]
620 let ed25519_identity_key = {
621 let master_key_tok = body.required(MASTER_KEY_ED25519)?;
622 let ed_id: Ed25519Public = master_key_tok.parse_arg(0)?;
623 let ed_id: ll::pk::ed25519::Ed25519Identity = ed_id.into();
624 if ed_id != *identity_cert.peek_signing_key() {
625 #[cfg(not(fuzzing))] return Err(EK::BadObjectVal
627 .at_pos(master_key_tok.pos())
628 .with_msg("master-key-ed25519 does not match key in identity-ed25519"));
629 }
630 ed_id
631 };
632
633 let rsa_identity_key: ll::pk::rsa::PublicKey = body
635 .required(SIGNING_KEY)?
636 .parse_obj::<RsaPublicParse1Helper>("RSA PUBLIC KEY")?
637 .check_len_eq(1024)?
638 .check_exponent(65537)?
639 .into();
640 let rsa_identity = rsa_identity_key.to_rsa_identity();
641
642 let ed_sig = sig.required(ROUTER_SIG_ED25519)?;
643 let rsa_sig = sig.required(ROUTER_SIGNATURE)?;
644 #[allow(clippy::unwrap_used)]
647 let ed_sig_pos = ed_sig.offset_in(s).unwrap();
648 #[allow(clippy::unwrap_used)]
649 let rsa_sig_pos = rsa_sig.offset_in(s).unwrap();
650
651 if ed_sig_pos > rsa_sig_pos {
652 return Err(EK::UnexpectedToken
653 .with_msg(ROUTER_SIG_ED25519.to_str())
654 .at_pos(ed_sig.pos()));
655 }
656
657 let ed_signature: ll::pk::ed25519::ValidatableEd25519Signature = {
659 let mut d = ll::d::Sha256::new();
660 d.update(&b"Tor router descriptor signature v1"[..]);
661 let signed_end = ed_sig_pos + b"router-sig-ed25519 ".len();
662 d.update(&s[start_offset..signed_end]);
663 let d = d.finalize();
664 let sig: [u8; 64] = ed_sig
665 .parse_arg::<B64>(0)?
666 .into_array()
667 .map_err(|_| EK::BadSignature.at_pos(ed_sig.pos()))?;
668 let sig = ll::pk::ed25519::Signature::from(sig);
669 ll::pk::ed25519::ValidatableEd25519Signature::new(ed25519_signing_key, sig, &d)
670 };
671
672 let rsa_signature: ll::pk::rsa::ValidatableRsaSignature = {
674 let mut d = ll::d::Sha1::new();
675 let signed_end = rsa_sig_pos + b"router-signature\n".len();
676 d.update(&s[start_offset..signed_end]);
677 let d = d.finalize();
678 let sig = rsa_sig.obj("SIGNATURE")?;
679 ll::pk::rsa::ValidatableRsaSignature::new(&rsa_identity_key, &sig, &d)
682 };
683
684 let (nickname, ipv4addr, orport, dirport) = {
686 let rtrline = header.required(ROUTER)?;
687 (
688 rtrline.required_arg(0)?.parse::<Nickname>().map_err(|e| {
689 EK::BadArgument
690 .with_msg(e.to_string())
691 .at_pos(rtrline.pos())
692 })?,
693 rtrline.parse_arg::<net::Ipv4Addr>(1)?,
694 rtrline.parse_arg(2)?,
695 rtrline.parse_arg(4)?,
697 )
698 };
699
700 let uptime = body.maybe(UPTIME).parse_arg(0)?;
702
703 let published = body
705 .required(PUBLISHED)?
706 .args_as_str()
707 .parse::<Iso8601TimeSp>()?;
708
709 let ntor_onion_key: Curve25519Public = body.required(NTOR_ONION_KEY)?.parse_arg(0)?;
711 let crosscert_cert: tor_cert::UncheckedCert = {
713 let cc = body.required(NTOR_ONION_KEY_CROSSCERT)?;
714 let sign: u8 = cc.parse_arg(0)?;
715 if sign != 0 && sign != 1 {
716 return Err(EK::BadArgument.at_pos(cc.arg_pos(0)).with_msg("not 0 or 1"));
717 }
718 let ntor_as_ed: ll::pk::ed25519::PublicKey =
719 ll::pk::keymanip::convert_curve25519_to_ed25519_public(&ntor_onion_key.0, sign)
720 .ok_or_else(|| {
721 EK::BadArgument
722 .at_pos(cc.pos())
723 .with_msg("Uncheckable crosscert")
724 })?;
725
726 cc.parse_obj::<UnvalidatedEdCert>("ED25519 CERT")?
727 .check_cert_type(tor_cert::CertType::NTOR_CC_IDENTITY)?
728 .check_subject_key_is(identity_cert.peek_signing_key())?
729 .into_unchecked()
730 .should_be_signed_with(&ntor_as_ed.into())
731 .map_err(|err| EK::BadSignature.err().with_source(err))?
732 };
733
734 let tap_onion_key: Option<ll::pk::rsa::PublicKey> = if let Some(tok) = body.get(ONION_KEY) {
736 Some(
737 tok.parse_obj::<RsaPublicParse1Helper>("RSA PUBLIC KEY")?
738 .check_len_eq(1024)?
739 .check_exponent(65537)?
740 .into(),
741 )
742 } else {
743 None
744 };
745
746 let tap_crosscert_sig = if let Some(cc_tok) = body.get(ONION_KEY_CROSSCERT) {
748 let cc_val = cc_tok.obj("CROSSCERT")?;
749 let mut signed = Vec::new();
750 signed.extend(rsa_identity.as_bytes());
751 signed.extend(identity_cert.peek_signing_key().as_bytes());
752 Some(ll::pk::rsa::ValidatableRsaSignature::new(
753 tap_onion_key.as_ref().ok_or_else(|| {
754 EK::MissingToken.with_msg("onion-key-crosscert without onion-key")
755 })?,
756 &cc_val,
757 &signed,
758 ))
759 } else if tap_onion_key.is_some() {
760 return Err(EK::MissingToken.with_msg("onion-key without onion-key-crosscert"));
761 } else {
762 None
763 };
764
765 let proto = {
767 let proto_tok = body.required(PROTO)?;
768 proto_tok
769 .args_as_str()
770 .parse::<tor_protover::Protocols>()
771 .map_err(|e| EK::BadArgument.at_pos(proto_tok.pos()).with_source(e))?
772 };
773
774 let is_dircache = (dirport != 0) || body.get(TUNNELLED_DIR_SERVER).is_some();
776
777 let is_extrainfo_cache = body.get(CACHES_EXTRA_INFO).is_some();
779
780 if let Some(fp_tok) = body.get(FINGERPRINT) {
782 let fp: RsaIdentity = fp_tok.args_as_str().parse::<SpFingerprint>()?.into();
783 if fp != rsa_identity {
784 return Err(EK::BadArgument
785 .at_pos(fp_tok.pos())
786 .with_msg("fingerprint does not match RSA identity"));
787 }
788 }
789
790 let family = {
792 let mut family = body
793 .maybe(FAMILY)
794 .parse_args_as_str::<RelayFamily>()?
795 .unwrap_or_else(RelayFamily::new);
796 if !family.is_empty() {
797 family.push(rsa_identity);
803 }
804 family.intern()
805 };
806
807 let family_certs = body
815 .slice(FAMILY_CERT)
816 .iter()
817 .map(|ent| {
818 let ku = ent
819 .parse_obj::<UnvalidatedEdCert>("FAMILY CERT")?
820 .check_cert_type(CertType::FAMILY_V_IDENTITY)?
821 .check_subject_key_is(identity_cert.peek_signing_key())?
822 .into_unchecked();
823 let unchecked = ku.clone().should_have_signing_key().map_err(|e| {
824 EK::BadObjectVal
825 .with_msg("missing public key")
826 .at_pos(ent.pos())
827 .with_source(e)
828 })?;
829 Ok((ku, unchecked))
830 })
831 .collect::<Result<Vec<_>>>()?;
832
833 let mut ipv6addr = Vec::with_capacity(1);
837 for tok in body.slice(OR_ADDRESS) {
838 if let Ok(net::SocketAddr::V6(a)) = tok.parse_arg::<net::SocketAddr>(0) {
839 ipv6addr.push(a.into());
840 break;
841 }
842 }
844
845 let platform = body.maybe(PLATFORM).parse_args_as_str::<RelayPlatform>()?;
847
848 let ipv4_policy = {
850 let mut pol = AddrPolicy::new();
851 for ruletok in body.slice(POLICY).iter() {
852 let accept = match ruletok.kwd_str() {
853 "accept" => RuleKind::Accept,
854 "reject" => RuleKind::Reject,
855 _ => {
856 return Err(Error::from(internal!(
857 "tried to parse a strange line as a policy"
858 ))
859 .at_pos(ruletok.pos()));
860 }
861 };
862 let pat: AddrPortPattern = ruletok
863 .args_as_str()
864 .parse()
865 .map_err(|e| EK::BadPolicy.at_pos(ruletok.pos()).with_source(e))?;
866 pol.push(accept, pat);
867 }
868 pol
869 };
870
871 let ipv6_policy = match body.get(IPV6_POLICY) {
873 Some(p) => p
874 .args_as_str()
875 .parse()
876 .map_err(|e| EK::BadPolicy.at_pos(p.pos()).with_source(e))?,
877 #[allow(clippy::unwrap_used)]
879 None => "reject 1-65535".parse::<PortPolicy>().unwrap(),
880 };
881
882 let (identity_cert, identity_sig) = identity_cert.dangerously_split().map_err(|err| {
884 EK::BadObjectVal
885 .with_msg("missing public key")
886 .with_source(err)
887 })?;
888 let (crosscert_cert, cc_sig) = crosscert_cert.dangerously_split().map_err(|err| {
889 EK::BadObjectVal
890 .with_msg("missing public key")
891 .with_source(err)
892 })?;
893 let mut signatures: Vec<Box<dyn ll::pk::ValidatableSignature>> = vec![
894 Box::new(rsa_signature),
895 Box::new(ed_signature),
896 Box::new(identity_sig),
897 Box::new(cc_sig),
898 ];
899 if let Some(s) = tap_crosscert_sig {
900 signatures.push(Box::new(s));
901 }
902
903 let identity_cert = identity_cert.dangerously_assume_timely();
904 let crosscert_cert = crosscert_cert.dangerously_assume_timely();
905 let mut expirations = vec![
906 published
907 .0
908 .saturating_add(time::Duration::new(ROUTER_EXPIRY_SECONDS, 0)),
909 identity_cert.expiry(),
910 crosscert_cert.expiry(),
911 ];
912
913 let mut embedded_family_certs = Vec::with_capacity(family_certs.len());
919 for (ku_cert, cert) in family_certs {
920 let family_ed25519 = *cert.peek_signing_key();
921 let (inner, sig) = cert.dangerously_split().map_err(into_internal!(
922 "Missing a public key that was previously there."
923 ))?;
924 let embedded_cert = EmbeddedCert::new(Ed25519FamilyCert { family_ed25519 }, ku_cert);
925 signatures.push(Box::new(sig));
926 expirations.push(inner.dangerously_assume_timely().expiry());
927 embedded_family_certs.push(embedded_cert);
928 }
929
930 #[allow(clippy::unwrap_used)]
932 let expiry = *expirations.iter().min().unwrap();
933
934 let start_time = published
935 .0
936 .saturating_sub(time::Duration::new(ROUTER_PRE_VALIDITY_SECONDS, 0));
937
938 let desc = RouterDesc {
939 router: RouterDescIntroItem {
940 nickname,
941 address: ipv4addr,
942 orport,
943 socksport: 0,
944 dirport,
945 },
946 identity_ed25519: EmbeddedCert::new(
947 Ed25519IdentityCert {
948 id_ed25519: ed25519_identity_key,
949 sign_ed25519: ed25519_signing_key.into(),
950 },
951 ku_identity_cert,
952 ),
953 master_key_ed25519: ed25519_identity_key.into(),
954 bandwidth: Default::default(),
955 platform,
956 published,
957 fingerprint: Some(rsa_identity.into()),
958 uptime,
959 onion_key: tap_onion_key,
960 ntor_onion_key,
961 signing_key: rsa_identity_key,
962 ipv4_policy,
963 ipv6_policy: ipv6_policy.intern(),
964 family,
965 family_cert: embedded_family_certs.into(),
966 caches_extra_info: is_extrainfo_cache,
967 or_address: ipv6addr,
968 tunnelled_dir_server: is_dircache,
969 proto,
970 };
971
972 let time_gated = timed::TimerangeBound::new(desc, start_time..expiry);
973 let sig_gated = signed::SignatureGated::new(time_gated, signatures);
974
975 Ok(sig_gated)
976 }
977}
978
979pub struct RouterReader<'a> {
985 annotated: bool,
987 reader: NetDocReader<'a, RouterKwd>,
989}
990
991fn advance_to_next_routerdesc(reader: &mut NetDocReader<'_, RouterKwd>, annotated: bool) {
996 use RouterKwd::*;
997 loop {
998 let item = reader.peek();
999 match item {
1000 Some(Ok(t)) => {
1001 let kwd = t.kwd();
1002 if (annotated && kwd.is_annotation()) || kwd == ROUTER {
1003 return;
1004 }
1005 }
1006 Some(Err(_)) => {
1007 }
1009 None => {
1010 return;
1011 }
1012 }
1013 let _ = reader.next();
1014 }
1015}
1016
1017impl<'a> RouterReader<'a> {
1018 pub fn new(s: &'a str, allow: &AllowAnnotations) -> Result<Self> {
1020 let reader = NetDocReader::new(s)?;
1021 let annotated = allow == &AllowAnnotations::AnnotationsAllowed;
1022 Ok(RouterReader { annotated, reader })
1023 }
1024
1025 fn take_annotation(&mut self) -> Result<RouterAnnotation> {
1027 if self.annotated {
1028 RouterAnnotation::take_from_reader(&mut self.reader)
1029 } else {
1030 Ok(RouterAnnotation::default())
1031 }
1032 }
1033
1034 fn take_annotated_routerdesc_raw(&mut self) -> Result<AnnotatedRouterDesc> {
1038 let ann = self.take_annotation()?;
1039 let router = RouterDesc::parse_internal(&mut self.reader)?;
1040 Ok(AnnotatedRouterDesc { ann, router })
1041 }
1042
1043 fn take_annotated_routerdesc(&mut self) -> Result<AnnotatedRouterDesc> {
1047 let pos_orig = self.reader.pos();
1048 let result = self.take_annotated_routerdesc_raw();
1049 if result.is_err() {
1050 if self.reader.pos() == pos_orig {
1051 let _ = self.reader.next();
1059 }
1060 advance_to_next_routerdesc(&mut self.reader, self.annotated);
1061 }
1062 result
1063 }
1064}
1065
1066impl<'a> Iterator for RouterReader<'a> {
1067 type Item = Result<AnnotatedRouterDesc>;
1068 fn next(&mut self) -> Option<Self::Item> {
1069 self.reader.peek()?;
1071
1072 Some(
1073 self.take_annotated_routerdesc()
1074 .map_err(|e| e.within(self.reader.str())),
1075 )
1076 }
1077}
1078
1079#[cfg(test)]
1080mod test {
1081 #![allow(clippy::bool_assert_comparison)]
1083 #![allow(clippy::clone_on_copy)]
1084 #![allow(clippy::dbg_macro)]
1085 #![allow(clippy::mixed_attributes_style)]
1086 #![allow(clippy::print_stderr)]
1087 #![allow(clippy::print_stdout)]
1088 #![allow(clippy::single_char_pattern)]
1089 #![allow(clippy::unwrap_used)]
1090 #![allow(clippy::unchecked_time_subtraction)]
1091 #![allow(clippy::useless_vec)]
1092 #![allow(clippy::needless_pass_by_value)]
1093 use super::*;
1095 const TESTDATA: &str = include_str!("../../testdata/routerdesc1.txt");
1096 const TESTDATA2: &str = include_str!("../../testdata/routerdesc2.txt");
1097 const TESTDATA3: &str = include_str!("../../testdata/routerdesc3.txt");
1099
1100 fn read_bad(fname: &str) -> String {
1101 use std::fs;
1102 use std::path::PathBuf;
1103 let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
1104 path.push("testdata");
1105 path.push("bad-routerdesc");
1106 path.push(fname);
1107
1108 fs::read_to_string(path).unwrap()
1109 }
1110
1111 #[test]
1112 fn parse_arbitrary() -> Result<()> {
1113 use std::str::FromStr;
1114 use tor_checkable::{SelfSigned, Timebound};
1115 let rd = RouterDesc::parse(TESTDATA)?
1116 .check_signature()?
1117 .dangerously_assume_timely();
1118
1119 assert_eq!(rd.router.nickname.as_str(), "Akka");
1120 assert_eq!(rd.router.orport, 443);
1121 assert_eq!(rd.router.dirport, 0);
1122 assert_eq!(rd.uptime, Some(1036923));
1123 assert_eq!(
1124 rd.family.as_ref(),
1125 &RelayFamily::from_str(
1126 "$303509ab910ef207b7438c27435c4a2fd579f1b1 \
1127 $56927e61b51e6f363fb55498150a6ddfcf7077f2"
1128 )
1129 .unwrap()
1130 );
1131
1132 assert_eq!(
1133 rd.rsa_identity().to_string(),
1134 "$56927e61b51e6f363fb55498150a6ddfcf7077f2"
1135 );
1136 assert_eq!(
1137 rd.ed_identity().to_string(),
1138 "CVTjf1oeaL616hH+1+UvYZ8OgkwF3z7UMITvJzm5r7A"
1139 );
1140 assert_eq!(
1141 rd.protocols().to_string(),
1142 "Cons=1-2 Desc=1-2 DirCache=2 FlowCtrl=1-2 HSDir=2 \
1143 HSIntro=4-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 \
1144 Padding=2 Relay=1-4"
1145 );
1146
1147 assert_eq!(
1148 hex::encode(rd.ntor_onion_key().to_bytes()),
1149 "329b3b52991613392e35d1a821dd6753e1210458ecc3337f7b7d39bfcf5da273"
1150 );
1151 assert_eq!(
1152 rd.published(),
1153 humantime::parse_rfc3339("2022-11-14T19:58:52Z").unwrap()
1154 );
1155 assert_eq!(
1156 rd.or_ports().collect::<Vec<_>>(),
1157 vec![
1158 "95.216.33.58:443".parse().unwrap(),
1159 "[2a01:4f9:2a:2145::2]:443".parse().unwrap(),
1160 ]
1161 );
1162 assert!(rd.onion_key.is_some());
1163
1164 Ok(())
1165 }
1166
1167 #[test]
1168 fn parse_no_tap_key() -> Result<()> {
1169 use tor_checkable::{SelfSigned, Timebound};
1170 let rd = RouterDesc::parse(TESTDATA2)?
1171 .check_signature()?
1172 .dangerously_assume_timely();
1173 assert!(rd.onion_key.is_none());
1174
1175 Ok(())
1176 }
1177
1178 #[test]
1179 fn test_bad() {
1180 use crate::Pos;
1181 use crate::types::policy::PolicyError;
1182 fn check(fname: &str, e: &Error) {
1183 let text = read_bad(fname);
1184 let rd = RouterDesc::parse(&text);
1185 assert!(rd.is_err());
1186 assert_eq!(&rd.err().unwrap(), e);
1187 }
1188
1189 check(
1190 "bad-sig-order",
1191 &EK::UnexpectedToken
1192 .with_msg("router-sig-ed25519")
1193 .at_pos(Pos::from_line(50, 1)),
1194 );
1195 check(
1196 "bad-start1",
1197 &EK::MisplacedToken
1198 .with_msg("identity-ed25519")
1199 .at_pos(Pos::from_line(1, 1)),
1200 );
1201 check("bad-start2", &EK::MissingToken.with_msg("identity-ed25519"));
1202 check(
1203 "mismatched-fp",
1204 &EK::BadArgument
1205 .at_pos(Pos::from_line(12, 1))
1206 .with_msg("fingerprint does not match RSA identity"),
1207 );
1208 check("no-ed-sk", &EK::MissingToken.with_msg("identity-ed25519"));
1209
1210 check(
1211 "bad-cc-sign",
1212 &EK::BadArgument
1213 .at_pos(Pos::from_line(34, 26))
1214 .with_msg("not 0 or 1"),
1215 );
1216 check(
1217 "bad-ipv6policy",
1218 &EK::BadPolicy
1219 .at_pos(Pos::from_line(43, 1))
1220 .with_source(PolicyError::InvalidPolicy),
1221 );
1222 check(
1223 "no-ed-id-key-in-cert",
1224 &EK::BadObjectVal
1225 .at_pos(Pos::from_line(2, 1))
1226 .with_source(tor_cert::CertError::MissingPubKey),
1227 );
1228 check(
1229 "non-ed-sk-in-cert",
1230 &EK::BadObjectVal
1231 .at_pos(Pos::from_line(2, 1))
1232 .with_msg("wrong type for signing key in cert"),
1233 );
1234 check(
1235 "bad-ed-sk-in-cert",
1236 &EK::BadObjectVal
1237 .at_pos(Pos::from_line(2, 1))
1238 .with_msg("invalid ed25519 signing key"),
1239 );
1240 check(
1241 "mismatched-ed-sk-in-cert",
1242 &EK::BadObjectVal
1243 .at_pos(Pos::from_line(8, 1))
1244 .with_msg("master-key-ed25519 does not match key in identity-ed25519"),
1245 );
1246 }
1247
1248 #[test]
1249 fn parse_multiple_annotated() {
1250 use crate::AllowAnnotations;
1251 let mut s = read_bad("bad-cc-sign");
1252 s += "\
1253@uploaded-at 2020-09-26 18:15:41
1254@source \"127.0.0.1\"
1255";
1256 s += TESTDATA;
1257 s += "\
1258@uploaded-at 2020-09-26 18:15:41
1259@source \"127.0.0.1\"
1260";
1261 s += &read_bad("mismatched-fp");
1262
1263 let rd = RouterReader::new(&s, &AllowAnnotations::AnnotationsAllowed).unwrap();
1264 let v: Vec<_> = rd.collect();
1265 assert!(v[0].is_err());
1266 assert!(v[1].is_ok());
1267 assert_eq!(
1268 v[1].as_ref().unwrap().ann.source,
1269 Some("\"127.0.0.1\"".to_string())
1270 );
1271 assert!(v[2].is_err());
1272 }
1273
1274 #[test]
1275 fn test_platform() {
1276 let p = "Tor 0.4.4.4-alpha on a flying bison".parse::<RelayPlatform>();
1277 assert!(p.is_ok());
1278 assert_eq!(
1279 p.unwrap(),
1280 RelayPlatform::Tor(
1281 "0.4.4.4-alpha".parse().unwrap(),
1282 "a flying bison".to_string()
1283 )
1284 );
1285
1286 let p = "Tor 0.4.4.4-alpha on".parse::<RelayPlatform>();
1287 assert!(p.is_ok());
1288
1289 let p = "Tor 0.4.4.4-alpha ".parse::<RelayPlatform>();
1290 assert!(p.is_ok());
1291 let p = "Tor 0.4.4.4-alpha".parse::<RelayPlatform>();
1292 assert!(p.is_ok());
1293
1294 let p = "arti 0.0.0".parse::<RelayPlatform>();
1295 assert!(p.is_ok());
1296 assert_eq!(p.unwrap(), RelayPlatform::Other("arti 0.0.0".to_string()));
1297 }
1298
1299 #[test]
1300 fn test_family_ids() -> Result<()> {
1301 use tor_checkable::{SelfSigned, Timebound};
1302 let rd = RouterDesc::parse(TESTDATA3)?
1303 .check_signature()?
1304 .dangerously_assume_timely();
1305
1306 assert_eq!(
1307 rd.family_ids().as_ref(),
1308 &[
1309 "ed25519:7sToQRuge1bU2hS0CG0ViMndc4m82JhO4B4kdrQey80"
1310 .parse()
1311 .unwrap(),
1312 "ed25519:szHUS3ItRd9uk85b1UVnOZx1gg4B0266jCpbuIMNjcM"
1313 .parse()
1314 .unwrap(),
1315 ]
1316 );
1317
1318 Ok(())
1319 }
1320}