1use crate::encode::{ItemEncoder, ItemValueEncodable};
36use crate::parse::keyword::Keyword;
37use crate::parse::parser::{Section, SectionRules};
38use crate::parse::tokenize::{ItemResult, NetDocReader};
39use crate::parse2::{ArgumentError, ErrorProblem, ItemValueParseable, UnparsedItem};
40use crate::types::family::{RelayFamily, RelayFamilyIds};
41use crate::types::policy::*;
42use crate::types::routerdesc::*;
43use crate::types::version::TorVersion;
44use crate::types::{EmbeddedCert, misc::*};
45use crate::util::PeekableIterator;
46use crate::{AllowAnnotations, Error, KeywordEncodable, NetdocErrorKind as EK, Result};
47
48use derive_deftly::Deftly;
49use ll::pk::ed25519::Ed25519Identity;
50use saturating_time::SaturatingTime;
51use std::fmt::Display;
52use std::sync::LazyLock;
53use std::{iter, net, time};
54use tor_basic_utils::intern::Intern;
55use tor_cert::{CertType, KeyUnknownCert};
56use tor_checkable::{Timebound, signed, timed};
57use tor_error::{internal, into_internal};
58use tor_llcrypto as ll;
59use tor_llcrypto::pk::rsa::RsaIdentity;
60
61use digest::Digest;
62
63pub const DOC_DIGEST_LEN: usize = 20;
65
66pub type RdDigest = [u8; DOC_DIGEST_LEN];
68
69pub type ExtraInfoDigest = [u8; DOC_DIGEST_LEN];
71
72#[non_exhaustive]
74pub struct AnnotatedRouterDesc {
75 pub ann: RouterAnnotation,
77 pub router: UncheckedRouterDesc,
79}
80
81#[derive(Default)]
83#[non_exhaustive]
84pub struct RouterAnnotation {
85 pub source: Option<String>,
87 pub downloaded: Option<time::SystemTime>,
89 pub purpose: Option<String>,
91}
92
93#[derive(Clone, Debug, Deftly, PartialEq, Eq)]
111#[derive_deftly(NetdocParseableUnverified)]
112#[non_exhaustive]
113pub struct RouterDesc {
114 pub router: RouterDescIntroItem,
118
119 pub identity_ed25519: EmbeddedCert<Ed25519IdentityCert, KeyUnknownCert>,
123
124 #[deftly(netdoc(single_arg))]
130 pub master_key_ed25519: Ed25519Public,
131
132 pub bandwidth: Bandwidth,
137
138 pub platform: Option<RelayPlatform>,
143
144 #[deftly(netdoc(single_arg))]
149 pub published: Iso8601TimeSp,
150
151 #[deftly(netdoc(single_arg))]
156 pub fingerprint: Option<SpFingerprint>,
157
158 #[deftly(netdoc(single_arg, default))]
163 pub hibernating: NumericBoolean,
164
165 #[deftly(netdoc(single_arg))]
170 pub uptime: Option<u64>,
171
172 pub onion_key: Option<ll::pk::rsa::PublicKey>,
178
179 #[deftly(netdoc(single_arg))]
184 pub ntor_onion_key: Curve25519Public,
185
186 pub ntor_onion_key_crosscert: NtorOnionKeyCrossCert,
190
191 pub signing_key: ll::pk::rsa::PublicKey,
195
196 #[deftly(netdoc(flatten))]
204 pub ipv4_policy: AddrPolicy,
205
206 #[deftly(netdoc(default))]
211 pub ipv6_policy: Intern<PortPolicy>,
212
213 pub overload_general: Option<OverloadGeneral>,
219
220 pub contact: Option<ContactInfo>,
224
225 #[deftly(netdoc(default))]
231 pub family: Intern<RelayFamily>,
232
233 pub family_cert: RetainedOrderVec<EmbeddedCert<Ed25519FamilyCert, KeyUnknownCert>>,
238
239 pub caches_extra_info: Option<ItemPresent<CachesExtraInfoToken>>,
245
246 pub extra_info_digest: Option<ExtraInfoDigests>,
250
251 pub hidden_service_dir: Option<ItemPresent<HiddenServiceDirToken>>,
255
256 #[deftly(netdoc(single_arg))]
260 pub or_address: Vec<net::SocketAddr>,
261
262 pub tunnelled_dir_server: Option<ItemPresent<TunnelledDirServerToken>>,
268
269 pub proto: tor_protover::Protocols,
274}
275
276#[derive(Clone, Debug, PartialEq, Eq, Deftly)]
280#[derive_deftly(NetdocParseableSignatures)]
281#[deftly(netdoc(signatures(hashes_accu = "RouterHashAccu")))]
282#[non_exhaustive]
283pub struct RouterDescSignatures {
284 pub router_sig_ed25519: RouterSigEd25519,
290
291 pub router_signature: RouterSignature,
296}
297
298impl RouterDescUnverified {}
300
301#[derive(Debug, Clone, PartialEq, Eq)]
307#[non_exhaustive]
308pub enum RelayPlatform {
309 Tor(TorVersion, Option<String>),
311 Other(String),
313}
314
315#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
317#[non_exhaustive]
318pub struct CachesExtraInfoToken;
319
320#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
322#[non_exhaustive]
323pub struct HiddenServiceDirToken;
324
325#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
327#[non_exhaustive]
328pub struct TunnelledDirServerToken;
329
330impl std::str::FromStr for RelayPlatform {
331 type Err = Error;
332 fn from_str(args: &str) -> Result<Self> {
333 if args.starts_with("Tor ") {
334 let v: Vec<_> = args.splitn(4, ' ').collect();
335 match &v[..] {
336 ["Tor", ver, "on", p] => {
337 Ok(RelayPlatform::Tor(ver.parse()?, Some((*p).to_string())))
338 }
339 ["Tor", ver, ..] => Ok(RelayPlatform::Tor(ver.parse()?, None)),
340 _ => unreachable!(),
341 }
342 } else {
343 Ok(RelayPlatform::Other(args.to_string()))
344 }
345 }
346}
347
348impl Display for RelayPlatform {
349 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
350 match &self {
351 Self::Tor(v, Some(p)) => write!(f, "Tor {v} on {p}"),
352 Self::Tor(v, None) => write!(f, "Tor {v}"),
353 Self::Other(s) => write!(f, "{s}"),
354 }
355 }
356}
357
358impl ItemValueParseable for RelayPlatform {
359 fn from_unparsed(item: UnparsedItem<'_>) -> std::result::Result<Self, ErrorProblem> {
360 let mut args = item.args_copy();
361 item.check_no_object()?;
362 args.into_remaining()
363 .parse()
364 .map_err(|_| args.handle_error("platform", ArgumentError::Invalid))
365 }
366}
367
368impl ItemValueEncodable for RelayPlatform {
369 fn write_item_value_onto(
370 &self,
371 mut out: ItemEncoder,
372 ) -> std::result::Result<(), tor_error::Bug> {
373 out.args_raw_string(&self);
376 Ok(())
377 }
378}
379
380decl_keyword! {
381 RouterKwd {
384 annotation "@source" => ANN_SOURCE,
385 annotation "@downloaded-at" => ANN_DOWNLOADED_AT,
386 annotation "@purpose" => ANN_PURPOSE,
387 "accept" | "reject" => POLICY,
388 "bandwidth" => BANDWIDTH,
389 "bridge-distribution-request" => BRIDGE_DISTRIBUTION_REQUEST,
390 "caches-extra-info" => CACHES_EXTRA_INFO,
391 "contact" => CONTACT,
392 "extra-info-digest" => EXTRA_INFO_DIGEST,
393 "family" => FAMILY,
394 "family-cert" => FAMILY_CERT,
395 "fingerprint" => FINGERPRINT,
396 "hibernating" => HIBERNATING,
397 "identity-ed25519" => IDENTITY_ED25519,
398 "ipv6-policy" => IPV6_POLICY,
399 "master-key-ed25519" => MASTER_KEY_ED25519,
400 "ntor-onion-key" => NTOR_ONION_KEY,
401 "ntor-onion-key-crosscert" => NTOR_ONION_KEY_CROSSCERT,
402 "onion-key" => ONION_KEY,
403 "onion-key-crosscert" => ONION_KEY_CROSSCERT,
404 "or-address" => OR_ADDRESS,
405 "platform" => PLATFORM,
406 "proto" => PROTO,
407 "published" => PUBLISHED,
408 "router" => ROUTER,
409 "router-sig-ed25519" => ROUTER_SIG_ED25519,
410 "router-signature" => ROUTER_SIGNATURE,
411 "signing-key" => SIGNING_KEY,
412 "tunnelled_dir_server" => TUNNELLED_DIR_SERVER,
413 "uptime" => UPTIME,
414 }
418}
419
420static ROUTER_ANNOTATIONS: LazyLock<SectionRules<RouterKwd>> = LazyLock::new(|| {
422 use RouterKwd::*;
423
424 let mut rules = SectionRules::builder();
425 rules.add(ANN_SOURCE.rule());
426 rules.add(ANN_DOWNLOADED_AT.rule().args(1..));
427 rules.add(ANN_PURPOSE.rule().args(1..));
428 rules.add(ANN_UNRECOGNIZED.rule().may_repeat().obj_optional());
429 rules.reject_unrecognized();
432 rules.build()
433});
434static ROUTER_HEADER_RULES: LazyLock<SectionRules<RouterKwd>> = LazyLock::new(|| {
437 use RouterKwd::*;
438
439 let mut rules = SectionRules::builder();
440 rules.add(ROUTER.rule().required().args(5..));
441 rules.add(IDENTITY_ED25519.rule().required().no_args().obj_required());
442 rules.reject_unrecognized();
444 rules.build()
445});
446static ROUTER_BODY_RULES: LazyLock<SectionRules<RouterKwd>> = LazyLock::new(|| {
449 use RouterKwd::*;
450
451 let mut rules = SectionRules::builder();
452 rules.add(MASTER_KEY_ED25519.rule().required().args(1..));
453 rules.add(PLATFORM.rule());
454 rules.add(PUBLISHED.rule().required());
455 rules.add(FINGERPRINT.rule());
456 rules.add(UPTIME.rule().args(1..));
457 rules.add(ONION_KEY.rule().no_args().obj_required());
458 rules.add(ONION_KEY_CROSSCERT.rule().no_args().obj_required());
459 rules.add(NTOR_ONION_KEY.rule().required().args(1..));
460 rules.add(
461 NTOR_ONION_KEY_CROSSCERT
462 .rule()
463 .required()
464 .args(1..=1)
465 .obj_required(),
466 );
467 rules.add(SIGNING_KEY.rule().no_args().required().obj_required());
468 rules.add(POLICY.rule().may_repeat().args(1..));
469 rules.add(IPV6_POLICY.rule().args(2..));
470 rules.add(FAMILY.rule().args(1..));
471 rules.add(FAMILY_CERT.rule().obj_required().may_repeat());
472 rules.add(CACHES_EXTRA_INFO.rule().no_args());
473 rules.add(OR_ADDRESS.rule().may_repeat().args(1..));
474 rules.add(TUNNELLED_DIR_SERVER.rule());
475 rules.add(PROTO.rule().required().args(1..));
476 rules.add(UNRECOGNIZED.rule().may_repeat().obj_optional());
477 {
479 rules.add(BANDWIDTH.rule().required().args(3..));
480 rules.add(BRIDGE_DISTRIBUTION_REQUEST.rule().args(1..));
481 rules.add(HIBERNATING.rule().args(1..));
482 rules.add(CONTACT.rule());
483 }
484 {
486 rules.add(EXTRA_INFO_DIGEST.rule().args(1..));
487 }
488 rules.build()
489});
490
491static ROUTER_SIG_RULES: LazyLock<SectionRules<RouterKwd>> = LazyLock::new(|| {
493 use RouterKwd::*;
494
495 let mut rules = SectionRules::builder();
496 rules.add(ROUTER_SIG_ED25519.rule().required().args(1..));
497 rules.add(ROUTER_SIGNATURE.rule().required().no_args().obj_required());
498 rules.reject_unrecognized();
500 rules.build()
501});
502
503impl RouterAnnotation {
504 fn take_from_reader(reader: &mut NetDocReader<'_, RouterKwd>) -> Result<RouterAnnotation> {
506 use RouterKwd::*;
507 let mut items = reader.pause_at(|item| item.is_ok_with_non_annotation());
508
509 let body = ROUTER_ANNOTATIONS.parse(&mut items)?;
510
511 let source = body.maybe(ANN_SOURCE).args_as_str().map(String::from);
512 let purpose = body.maybe(ANN_PURPOSE).args_as_str().map(String::from);
513 let downloaded = body
514 .maybe(ANN_DOWNLOADED_AT)
515 .parse_args_as_str::<Iso8601TimeSp>()?
516 .map(|t| t.into());
517 Ok(RouterAnnotation {
518 source,
519 downloaded,
520 purpose,
521 })
522 }
523}
524
525pub type UncheckedRouterDesc = signed::SignatureGated<timed::TimerangeBound<RouterDesc>>;
528
529const ROUTER_EXPIRY_SECONDS: u64 = 5 * 86400;
532
533const ROUTER_PRE_VALIDITY_SECONDS: u64 = 86400;
539
540impl RouterDesc {
541 pub fn rsa_identity(&self) -> RsaIdentity {
543 self.signing_key.to_rsa_identity()
544 }
545
546 pub fn ed_identity(&self) -> &Ed25519Identity {
548 &self
549 .identity_ed25519
550 .get()
551 .expect("ed25519 identity cert should be verified")
552 .id_ed25519
553 }
554
555 pub fn protocols(&self) -> &tor_protover::Protocols {
558 &self.proto
559 }
560
561 pub fn ntor_onion_key(&self) -> &ll::pk::curve25519::PublicKey {
563 &self.ntor_onion_key.0
564 }
565
566 pub fn published(&self) -> time::SystemTime {
568 self.published.0
569 }
570
571 pub fn or_ports(&self) -> impl Iterator<Item = net::SocketAddr> + '_ {
574 iter::once(net::SocketAddr::new(
575 self.router.address.into(),
576 self.router.orport,
577 ))
578 .chain(self.or_address.iter().copied())
579 }
580
581 pub fn family(&self) -> Intern<RelayFamily> {
583 Intern::clone(&self.family)
584 }
585
586 pub fn family_ids(&self) -> RelayFamilyIds {
588 RelayFamilyIds::from_iter(
589 self.family_cert
590 .iter()
591 .map(|cert| cert.get().expect("unverified family cert?"))
592 .map(|cert| cert.family_ed25519.into()),
593 )
594 }
595
596 fn parse_sections<'a>(
598 reader: &mut NetDocReader<'a, RouterKwd>,
599 ) -> Result<(
600 Section<'a, RouterKwd>,
601 Section<'a, RouterKwd>,
602 Section<'a, RouterKwd>,
603 )> {
604 use RouterKwd::*;
605
606 let header = ROUTER_HEADER_RULES.parse(
608 reader.pause_at(|item| item.is_ok_with_kwd_not_in(&[ROUTER, IDENTITY_ED25519])),
609 )?;
610
611 let body =
613 ROUTER_BODY_RULES.parse(reader.pause_at(|item| {
614 item.is_ok_with_kwd_in(&[ROUTER_SIGNATURE, ROUTER_SIG_ED25519])
615 }))?;
616
617 let sig = ROUTER_SIG_RULES.parse(reader.pause_at(|item| {
619 item.is_ok_with_annotation() || item.is_ok_with_kwd(ROUTER) || item.is_empty_line()
620 }))?;
621
622 Ok((header, body, sig))
623 }
624
625 pub fn parse(s: &str) -> Result<UncheckedRouterDesc> {
642 let mut reader = crate::parse::tokenize::NetDocReader::new(s)?;
643 let result = Self::parse_internal(&mut reader).map_err(|e| e.within(s))?;
644 reader
647 .should_be_exhausted_but_for_empty_lines()
648 .map_err(|e| e.within(s))?;
649 Ok(result)
650 }
651
652 fn parse_internal(r: &mut NetDocReader<'_, RouterKwd>) -> Result<UncheckedRouterDesc> {
658 use RouterKwd::*;
661
662 let s = r.str();
663 let (header, body, sig) = RouterDesc::parse_sections(r)?;
664
665 #[allow(clippy::unwrap_used)]
668 let start_offset = header.required(ROUTER)?.offset_in(s).unwrap();
669
670 let (ku_identity_cert, identity_cert, ed25519_signing_key) = {
684 let cert_tok = header.required(IDENTITY_ED25519)?;
685 #[allow(clippy::unwrap_used)]
688 if cert_tok.offset_in(s).unwrap() < start_offset {
689 return Err(EK::MisplacedToken
690 .with_msg("identity-ed25519")
691 .at_pos(cert_tok.pos()));
692 }
693 let ku_cert = cert_tok
694 .parse_obj::<UnvalidatedEdCert>("ED25519 CERT")?
695 .check_cert_type(tor_cert::CertType::IDENTITY_V_SIGNING)?
696 .into_unchecked();
697 let cert = ku_cert.clone().should_have_signing_key().map_err(|err| {
698 EK::BadObjectVal
699 .err()
700 .with_source(err)
701 .at_pos(cert_tok.pos())
702 })?;
703 let sk = *cert.peek_subject_key().as_ed25519().ok_or_else(|| {
704 EK::BadObjectVal
705 .at_pos(cert_tok.pos())
706 .with_msg("wrong type for signing key in cert")
707 })?;
708 let sk: ll::pk::ed25519::PublicKey = sk.try_into().map_err(|_| {
709 EK::BadObjectVal
710 .at_pos(cert_tok.pos())
711 .with_msg("invalid ed25519 signing key")
712 })?;
713 (ku_cert, cert, sk)
714 };
715
716 #[allow(unexpected_cfgs)]
718 let ed25519_identity_key = {
719 let master_key_tok = body.required(MASTER_KEY_ED25519)?;
720 let ed_id: Ed25519Public = master_key_tok.parse_arg(0)?;
721 let ed_id: ll::pk::ed25519::Ed25519Identity = ed_id.into();
722 if ed_id != *identity_cert.peek_signing_key() {
723 #[cfg(not(fuzzing))] return Err(EK::BadObjectVal
725 .at_pos(master_key_tok.pos())
726 .with_msg("master-key-ed25519 does not match key in identity-ed25519"));
727 }
728 ed_id
729 };
730
731 let rsa_identity_key: ll::pk::rsa::PublicKey = body
733 .required(SIGNING_KEY)?
734 .parse_obj::<RsaPublicParse1Helper>("RSA PUBLIC KEY")?
735 .check_len_eq(1024)?
736 .check_exponent(65537)?
737 .into();
738 let rsa_identity = rsa_identity_key.to_rsa_identity();
739
740 let ed_sig = sig.required(ROUTER_SIG_ED25519)?;
741 let rsa_sig = sig.required(ROUTER_SIGNATURE)?;
742 #[allow(clippy::unwrap_used)]
745 let ed_sig_pos = ed_sig.offset_in(s).unwrap();
746 #[allow(clippy::unwrap_used)]
747 let rsa_sig_pos = rsa_sig.offset_in(s).unwrap();
748
749 if ed_sig_pos > rsa_sig_pos {
750 return Err(EK::UnexpectedToken
751 .with_msg(ROUTER_SIG_ED25519.to_str())
752 .at_pos(ed_sig.pos()));
753 }
754
755 let ed_signature: ll::pk::ed25519::ValidatableEd25519Signature = {
757 let mut d = ll::d::Sha256::new();
758 d.update(&b"Tor router descriptor signature v1"[..]);
759 let signed_end = ed_sig_pos + b"router-sig-ed25519 ".len();
760 d.update(
761 s.get(start_offset..signed_end)
762 .ok_or(internal!("chopped utf8"))?,
763 );
764 let d = d.finalize();
765 let sig: [u8; 64] = ed_sig
766 .parse_arg::<B64>(0)?
767 .into_array()
768 .map_err(|_| EK::BadSignature.at_pos(ed_sig.pos()))?;
769 let sig = ll::pk::ed25519::Signature::from(sig);
770 ll::pk::ed25519::ValidatableEd25519Signature::new(ed25519_signing_key, sig, &d)
771 };
772
773 let rsa_signature: ll::pk::rsa::ValidatableRsaSignature = {
775 let mut d = ll::d::Sha1::new();
776 let signed_end = rsa_sig_pos + b"router-signature\n".len();
777 d.update(
778 s.get(start_offset..signed_end)
779 .ok_or(internal!("chopped utf8"))?,
780 );
781 let d = d.finalize();
782 let sig = rsa_sig.obj("SIGNATURE")?;
783 ll::pk::rsa::ValidatableRsaSignature::new(&rsa_identity_key, &sig, &d)
786 };
787
788 let (nickname, ipv4addr, orport, dirport) = {
790 let rtrline = header.required(ROUTER)?;
791 (
792 rtrline.required_arg(0)?.parse::<Nickname>().map_err(|e| {
793 EK::BadArgument
794 .with_msg(e.to_string())
795 .at_pos(rtrline.pos())
796 })?,
797 rtrline.parse_arg::<net::Ipv4Addr>(1)?,
798 rtrline.parse_arg(2)?,
799 rtrline.parse_arg(4)?,
801 )
802 };
803
804 let uptime = body.maybe(UPTIME).parse_arg(0)?;
806
807 let published = body
809 .required(PUBLISHED)?
810 .args_as_str()
811 .parse::<Iso8601TimeSp>()?;
812
813 let ntor_onion_key: Curve25519Public = body.required(NTOR_ONION_KEY)?.parse_arg(0)?;
815 let (cc_sig, cc_expiry, cc_cert) = {
817 let cc = body.required(NTOR_ONION_KEY_CROSSCERT)?;
818 let sign: u8 = cc.parse_arg(0)?;
819 if sign != 0 && sign != 1 {
820 return Err(EK::BadArgument.at_pos(cc.arg_pos(0)).with_msg("not 0 or 1"));
821 }
822 let ntor_as_ed: ll::pk::ed25519::PublicKey =
823 ll::pk::keymanip::convert_curve25519_to_ed25519_public(&ntor_onion_key.0, sign)
824 .ok_or_else(|| {
825 EK::BadArgument
826 .at_pos(cc.pos())
827 .with_msg("Uncheckable crosscert")
828 })?;
829
830 let cert = cc
831 .parse_obj::<UnvalidatedEdCert>("ED25519 CERT")?
832 .into_unchecked();
833 let (_, sig, expiry) = Ed25519NtorCrossCert::verify_inner(
834 ntor_as_ed.into(),
835 ed25519_identity_key,
836 cert.clone(),
837 )
838 .map_err(|_| EK::BadSignature.err())?;
839
840 let cert = NtorOnionKeyCrossCert {
841 bit: NumericBoolean(sign != 0),
842 cert: EmbeddedCert::new(Ed25519NtorCrossCert::dangerous_new_unverified(), cert),
844 };
845
846 (sig, expiry, cert)
847 };
848
849 let tap_onion_key: Option<ll::pk::rsa::PublicKey> = if let Some(tok) = body.get(ONION_KEY) {
851 Some(
852 tok.parse_obj::<RsaPublicParse1Helper>("RSA PUBLIC KEY")?
853 .check_len_eq(1024)?
854 .check_exponent(65537)?
855 .into(),
856 )
857 } else {
858 None
859 };
860
861 let tap_crosscert_sig = if let Some(cc_tok) = body.get(ONION_KEY_CROSSCERT) {
863 let cc_val = cc_tok.obj("CROSSCERT")?;
864 let mut signed = Vec::new();
865 signed.extend(rsa_identity.as_bytes());
866 signed.extend(identity_cert.peek_signing_key().as_bytes());
867 Some(ll::pk::rsa::ValidatableRsaSignature::new(
868 tap_onion_key.as_ref().ok_or_else(|| {
869 EK::MissingToken.with_msg("onion-key-crosscert without onion-key")
870 })?,
871 &cc_val,
872 &signed,
873 ))
874 } else if tap_onion_key.is_some() {
875 return Err(EK::MissingToken.with_msg("onion-key without onion-key-crosscert"));
876 } else {
877 None
878 };
879
880 let proto = {
882 let proto_tok = body.required(PROTO)?;
883 proto_tok
884 .args_as_str()
885 .parse::<tor_protover::Protocols>()
886 .map_err(|e| EK::BadArgument.at_pos(proto_tok.pos()).with_source(e))?
887 };
888
889 let is_dircache = ((dirport != 0) || body.get(TUNNELLED_DIR_SERVER).is_some())
891 .then_some(ItemPresent::default());
892
893 let is_extrainfo_cache = body.get(CACHES_EXTRA_INFO).map(|_| ItemPresent::default());
895
896 if let Some(fp_tok) = body.get(FINGERPRINT) {
898 let fp: RsaIdentity = fp_tok.args_as_str().parse::<SpFingerprint>()?.into();
899 if fp != rsa_identity {
900 return Err(EK::BadArgument
901 .at_pos(fp_tok.pos())
902 .with_msg("fingerprint does not match RSA identity"));
903 }
904 }
905
906 let family = {
908 let mut family = body
909 .maybe(FAMILY)
910 .parse_args_as_str::<RelayFamily>()?
911 .unwrap_or_else(RelayFamily::new);
912 if !family.is_empty() {
913 family.push(rsa_identity);
919 }
920 family.intern()
921 };
922
923 let family_certs = body
931 .slice(FAMILY_CERT)
932 .iter()
933 .map(|ent| {
934 let ku = ent
935 .parse_obj::<UnvalidatedEdCert>("FAMILY CERT")?
936 .check_cert_type(CertType::FAMILY_V_IDENTITY)?
937 .check_subject_key_is(identity_cert.peek_signing_key())?
938 .into_unchecked();
939 let unchecked = ku.clone().should_have_signing_key().map_err(|e| {
940 EK::BadObjectVal
941 .with_msg("missing public key")
942 .at_pos(ent.pos())
943 .with_source(e)
944 })?;
945 Ok((ku, unchecked))
946 })
947 .collect::<Result<Vec<_>>>()?;
948
949 let mut ipv6addr = Vec::with_capacity(1);
953 for tok in body.slice(OR_ADDRESS) {
954 if let Ok(net::SocketAddr::V6(a)) = tok.parse_arg::<net::SocketAddr>(0) {
955 ipv6addr.push(a.into());
956 break;
957 }
958 }
960
961 let platform = body.maybe(PLATFORM).parse_args_as_str::<RelayPlatform>()?;
963
964 let ipv4_policy = {
966 let mut pol = AddrPolicy::new();
967 for ruletok in body.slice(POLICY).iter() {
968 let accept = match ruletok.kwd_str() {
969 "accept" => RuleKind::Accept,
970 "reject" => RuleKind::Reject,
971 _ => {
972 return Err(Error::from(internal!(
973 "tried to parse a strange line as a policy"
974 ))
975 .at_pos(ruletok.pos()));
976 }
977 };
978 let pat: AddrPortPattern = ruletok
979 .args_as_str()
980 .parse()
981 .map_err(|e| EK::BadPolicy.at_pos(ruletok.pos()).with_source(e))?;
982 pol.push(accept, pat);
983 }
984 pol
985 };
986
987 let ipv6_policy = match body.get(IPV6_POLICY) {
989 Some(p) => p
990 .args_as_str()
991 .parse()
992 .map_err(|e| EK::BadPolicy.at_pos(p.pos()).with_source(e))?,
993 #[allow(clippy::unwrap_used)]
995 None => "reject 1-65535".parse::<PortPolicy>().unwrap(),
996 };
997
998 let (identity_cert, identity_sig) = identity_cert.dangerously_split().map_err(|err| {
1000 EK::BadObjectVal
1001 .with_msg("missing public key")
1002 .with_source(err)
1003 })?;
1004 let mut signatures: Vec<Box<dyn ll::pk::ValidatableSignature>> = vec![
1005 Box::new(rsa_signature),
1006 Box::new(ed_signature),
1007 Box::new(identity_sig),
1008 Box::new(cc_sig),
1009 ];
1010 if let Some(s) = tap_crosscert_sig {
1011 signatures.push(Box::new(s));
1012 }
1013
1014 let identity_cert = identity_cert.dangerously_assume_timely();
1015 let mut expirations = vec![
1016 published
1017 .0
1018 .saturating_add(time::Duration::new(ROUTER_EXPIRY_SECONDS, 0)),
1019 identity_cert.expiry(),
1020 cc_expiry,
1021 ];
1022
1023 let mut embedded_family_certs = Vec::with_capacity(family_certs.len());
1029 for (ku_cert, cert) in family_certs {
1030 let family_ed25519 = *cert.peek_signing_key();
1031 let (inner, sig) = cert.dangerously_split().map_err(into_internal!(
1032 "Missing a public key that was previously there."
1033 ))?;
1034 let embedded_cert = EmbeddedCert::new(Ed25519FamilyCert { family_ed25519 }, ku_cert);
1035 signatures.push(Box::new(sig));
1036 expirations.push(inner.dangerously_assume_timely().expiry());
1037 embedded_family_certs.push(embedded_cert);
1038 }
1039
1040 #[allow(clippy::unwrap_used)]
1042 let expiry = *expirations.iter().min().unwrap();
1043
1044 let start_time = published
1045 .0
1046 .saturating_sub(time::Duration::new(ROUTER_PRE_VALIDITY_SECONDS, 0));
1047
1048 let desc = RouterDesc {
1049 router: RouterDescIntroItem {
1050 nickname,
1051 address: ipv4addr,
1052 orport,
1053 socksport: 0,
1054 dirport,
1055 },
1056 identity_ed25519: EmbeddedCert::new(
1057 Ed25519IdentityCert {
1058 id_ed25519: ed25519_identity_key,
1059 sign_ed25519: ed25519_signing_key.into(),
1060 },
1061 ku_identity_cert,
1062 ),
1063 master_key_ed25519: ed25519_identity_key.into(),
1064 bandwidth: Default::default(),
1065 platform,
1066 published,
1067 fingerprint: Some(rsa_identity.into()),
1068 hibernating: Default::default(),
1069 uptime,
1070 onion_key: tap_onion_key,
1071 ntor_onion_key,
1072 ntor_onion_key_crosscert: cc_cert,
1073 signing_key: rsa_identity_key,
1074 ipv4_policy,
1075 ipv6_policy: ipv6_policy.intern(),
1076 overload_general: Default::default(),
1077 contact: Default::default(),
1078 family,
1079 family_cert: embedded_family_certs.into(),
1080 caches_extra_info: is_extrainfo_cache,
1081 extra_info_digest: Default::default(),
1082 hidden_service_dir: Default::default(),
1083 or_address: ipv6addr,
1084 tunnelled_dir_server: is_dircache,
1085 proto,
1086 };
1087
1088 let time_gated = timed::TimerangeBound::new(desc, start_time..expiry);
1089 let sig_gated = signed::SignatureGated::new(time_gated, signatures);
1090
1091 Ok(sig_gated)
1092 }
1093}
1094
1095pub struct RouterReader<'a> {
1101 annotated: bool,
1103 reader: NetDocReader<'a, RouterKwd>,
1105}
1106
1107fn advance_to_next_routerdesc(reader: &mut NetDocReader<'_, RouterKwd>, annotated: bool) {
1112 use RouterKwd::*;
1113 loop {
1114 let item = reader.peek();
1115 match item {
1116 Some(Ok(t)) => {
1117 let kwd = t.kwd();
1118 if (annotated && kwd.is_annotation()) || kwd == ROUTER {
1119 return;
1120 }
1121 }
1122 Some(Err(_)) => {
1123 }
1125 None => {
1126 return;
1127 }
1128 }
1129 let _ = reader.next();
1130 }
1131}
1132
1133impl<'a> RouterReader<'a> {
1134 pub fn new(s: &'a str, allow: &AllowAnnotations) -> Result<Self> {
1136 let reader = NetDocReader::new(s)?;
1137 let annotated = allow == &AllowAnnotations::AnnotationsAllowed;
1138 Ok(RouterReader { annotated, reader })
1139 }
1140
1141 fn take_annotation(&mut self) -> Result<RouterAnnotation> {
1143 if self.annotated {
1144 RouterAnnotation::take_from_reader(&mut self.reader)
1145 } else {
1146 Ok(RouterAnnotation::default())
1147 }
1148 }
1149
1150 fn take_annotated_routerdesc_raw(&mut self) -> Result<AnnotatedRouterDesc> {
1154 let ann = self.take_annotation()?;
1155 let router = RouterDesc::parse_internal(&mut self.reader)?;
1156 Ok(AnnotatedRouterDesc { ann, router })
1157 }
1158
1159 fn take_annotated_routerdesc(&mut self) -> Result<AnnotatedRouterDesc> {
1163 let pos_orig = self.reader.pos();
1164 let result = self.take_annotated_routerdesc_raw();
1165 if result.is_err() {
1166 if self.reader.pos() == pos_orig {
1167 let _ = self.reader.next();
1175 }
1176 advance_to_next_routerdesc(&mut self.reader, self.annotated);
1177 }
1178 result
1179 }
1180}
1181
1182impl<'a> Iterator for RouterReader<'a> {
1183 type Item = Result<AnnotatedRouterDesc>;
1184 fn next(&mut self) -> Option<Self::Item> {
1185 self.reader.peek()?;
1187
1188 Some(
1189 self.take_annotated_routerdesc()
1190 .map_err(|e| e.within(self.reader.str())),
1191 )
1192 }
1193}
1194
1195#[cfg(test)]
1196mod test {
1197 #![allow(clippy::bool_assert_comparison)]
1199 #![allow(clippy::clone_on_copy)]
1200 #![allow(clippy::dbg_macro)]
1201 #![allow(clippy::mixed_attributes_style)]
1202 #![allow(clippy::print_stderr)]
1203 #![allow(clippy::print_stdout)]
1204 #![allow(clippy::single_char_pattern)]
1205 #![allow(clippy::unwrap_used)]
1206 #![allow(clippy::unchecked_time_subtraction)]
1207 #![allow(clippy::useless_vec)]
1208 #![allow(clippy::needless_pass_by_value)]
1209 #![allow(clippy::string_slice)] use crate::parse2::{self, NetdocParseableUnverified, ParseInput};
1212
1213 use super::*;
1214 const TESTDATA: &str = include_str!("../../testdata/routerdesc1.txt");
1215 const TESTDATA2: &str = include_str!("../../testdata/routerdesc2.txt");
1216 const TESTDATA3: &str = include_str!("../../testdata/routerdesc3.txt");
1218
1219 fn read_bad(fname: &str) -> String {
1220 use std::fs;
1221 use std::path::PathBuf;
1222 let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
1223 path.push("testdata");
1224 path.push("bad-routerdesc");
1225 path.push(fname);
1226
1227 fs::read_to_string(path).unwrap()
1228 }
1229
1230 #[test]
1231 fn parse_arbitrary() -> Result<()> {
1232 use std::str::FromStr;
1233 use tor_checkable::{SelfSigned, Timebound};
1234 let rd = RouterDesc::parse(TESTDATA)?
1235 .check_signature()?
1236 .dangerously_assume_timely();
1237
1238 assert_eq!(rd.router.nickname.as_str(), "Akka");
1239 assert_eq!(rd.router.orport, 443);
1240 assert_eq!(rd.router.dirport, 0);
1241 assert_eq!(rd.uptime, Some(1036923));
1242 assert_eq!(
1243 rd.family.as_ref(),
1244 &RelayFamily::from_str(
1245 "$303509ab910ef207b7438c27435c4a2fd579f1b1 \
1246 $56927e61b51e6f363fb55498150a6ddfcf7077f2"
1247 )
1248 .unwrap()
1249 );
1250
1251 assert_eq!(
1252 rd.rsa_identity().to_string(),
1253 "$56927e61b51e6f363fb55498150a6ddfcf7077f2"
1254 );
1255 assert_eq!(
1256 rd.ed_identity().to_string(),
1257 "CVTjf1oeaL616hH+1+UvYZ8OgkwF3z7UMITvJzm5r7A"
1258 );
1259 assert_eq!(
1260 rd.protocols().to_string(),
1261 "Cons=1-2 Desc=1-2 DirCache=2 FlowCtrl=1-2 HSDir=2 \
1262 HSIntro=4-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 \
1263 Padding=2 Relay=1-4"
1264 );
1265
1266 assert_eq!(
1267 hex::encode(rd.ntor_onion_key().to_bytes()),
1268 "329b3b52991613392e35d1a821dd6753e1210458ecc3337f7b7d39bfcf5da273"
1269 );
1270 assert_eq!(
1271 rd.published(),
1272 humantime::parse_rfc3339("2022-11-14T19:58:52Z").unwrap()
1273 );
1274 assert_eq!(
1275 rd.or_ports().collect::<Vec<_>>(),
1276 vec![
1277 "95.216.33.58:443".parse().unwrap(),
1278 "[2a01:4f9:2a:2145::2]:443".parse().unwrap(),
1279 ]
1280 );
1281 assert!(rd.onion_key.is_some());
1282
1283 Ok(())
1284 }
1285
1286 #[test]
1287 fn parse_no_tap_key() -> Result<()> {
1288 use tor_checkable::{SelfSigned, Timebound};
1289 let rd = RouterDesc::parse(TESTDATA2)?
1290 .check_signature()?
1291 .dangerously_assume_timely();
1292 assert!(rd.onion_key.is_none());
1293
1294 Ok(())
1295 }
1296
1297 #[test]
1298 fn test_bad() {
1299 use crate::Pos;
1300 use crate::types::policy::PolicyError;
1301 fn check(fname: &str, e: &Error) {
1302 let text = read_bad(fname);
1303 let rd = RouterDesc::parse(&text);
1304 assert!(rd.is_err());
1305 assert_eq!(&rd.err().unwrap(), e);
1306 }
1307
1308 check(
1309 "bad-sig-order",
1310 &EK::UnexpectedToken
1311 .with_msg("router-sig-ed25519")
1312 .at_pos(Pos::from_line(50, 1)),
1313 );
1314 check(
1315 "bad-start1",
1316 &EK::MisplacedToken
1317 .with_msg("identity-ed25519")
1318 .at_pos(Pos::from_line(1, 1)),
1319 );
1320 check("bad-start2", &EK::MissingToken.with_msg("identity-ed25519"));
1321 check(
1322 "mismatched-fp",
1323 &EK::BadArgument
1324 .at_pos(Pos::from_line(12, 1))
1325 .with_msg("fingerprint does not match RSA identity"),
1326 );
1327 check("no-ed-sk", &EK::MissingToken.with_msg("identity-ed25519"));
1328
1329 check(
1330 "bad-cc-sign",
1331 &EK::BadArgument
1332 .at_pos(Pos::from_line(34, 26))
1333 .with_msg("not 0 or 1"),
1334 );
1335 check(
1336 "bad-ipv6policy",
1337 &EK::BadPolicy
1338 .at_pos(Pos::from_line(43, 1))
1339 .with_source(PolicyError::InvalidPolicy),
1340 );
1341 check(
1342 "no-ed-id-key-in-cert",
1343 &EK::BadObjectVal
1344 .at_pos(Pos::from_line(2, 1))
1345 .with_source(tor_cert::CertError::MissingPubKey),
1346 );
1347 check(
1348 "non-ed-sk-in-cert",
1349 &EK::BadObjectVal
1350 .at_pos(Pos::from_line(2, 1))
1351 .with_msg("wrong type for signing key in cert"),
1352 );
1353 check(
1354 "bad-ed-sk-in-cert",
1355 &EK::BadObjectVal
1356 .at_pos(Pos::from_line(2, 1))
1357 .with_msg("invalid ed25519 signing key"),
1358 );
1359 check(
1360 "mismatched-ed-sk-in-cert",
1361 &EK::BadObjectVal
1362 .at_pos(Pos::from_line(8, 1))
1363 .with_msg("master-key-ed25519 does not match key in identity-ed25519"),
1364 );
1365 }
1366
1367 #[test]
1368 fn parse_multiple_annotated() {
1369 use crate::AllowAnnotations;
1370 let mut s = read_bad("bad-cc-sign");
1371 s += "\
1372@uploaded-at 2020-09-26 18:15:41
1373@source \"127.0.0.1\"
1374";
1375 s += TESTDATA;
1376 s += "\
1377@uploaded-at 2020-09-26 18:15:41
1378@source \"127.0.0.1\"
1379";
1380 s += &read_bad("mismatched-fp");
1381
1382 let rd = RouterReader::new(&s, &AllowAnnotations::AnnotationsAllowed).unwrap();
1383 let v: Vec<_> = rd.collect();
1384 assert!(v[0].is_err());
1385 assert!(v[1].is_ok());
1386 assert_eq!(
1387 v[1].as_ref().unwrap().ann.source,
1388 Some("\"127.0.0.1\"".to_string())
1389 );
1390 assert!(v[2].is_err());
1391 }
1392
1393 #[test]
1394 fn test_platform() {
1395 let tests = [
1396 (
1398 "Tor 0.4.4.4-alpha on a flying bison",
1399 RelayPlatform::Tor(
1400 "0.4.4.4-alpha".parse().unwrap(),
1401 Some("a flying bison".to_string()),
1402 ),
1403 ),
1404 (
1406 "Tor 0.4.4.4-alpha on",
1407 RelayPlatform::Tor("0.4.4.4-alpha".parse().unwrap(), None),
1408 ),
1409 (
1410 "Tor 0.4.4.4-alpha ",
1411 RelayPlatform::Tor("0.4.4.4-alpha".parse().unwrap(), None),
1412 ),
1413 (
1414 "Tor 0.4.4.4-alpha",
1415 RelayPlatform::Tor("0.4.4.4-alpha".parse().unwrap(), None),
1416 ),
1417 ("arti 0.0.0", RelayPlatform::Other("arti 0.0.0".to_string())),
1419 ];
1420 for (input, output) in tests {
1421 assert_eq!(input.parse::<RelayPlatform>().unwrap(), output);
1422
1423 let input = input.strip_suffix(" on").unwrap_or(input);
1427 let input = input.trim();
1428 assert_eq!(output.to_string(), input);
1429 }
1430 }
1431
1432 #[test]
1433 fn test_family_ids() -> Result<()> {
1434 use tor_checkable::{SelfSigned, Timebound};
1435 let rd = RouterDesc::parse(TESTDATA3)?
1436 .check_signature()?
1437 .dangerously_assume_timely();
1438
1439 assert_eq!(
1440 rd.family_ids().as_ref(),
1441 &[
1442 "ed25519:7sToQRuge1bU2hS0CG0ViMndc4m82JhO4B4kdrQey80"
1443 .parse()
1444 .unwrap(),
1445 "ed25519:szHUS3ItRd9uk85b1UVnOZx1gg4B0266jCpbuIMNjcM"
1446 .parse()
1447 .unwrap(),
1448 ]
1449 );
1450
1451 Ok(())
1452 }
1453
1454 #[test]
1458 fn test_parse2() {
1459 let input = ParseInput::new(
1460 include_str!("../../testdata2/cached-descriptors.new"),
1461 "cached-descriptors.new",
1462 );
1463 let rd = parse2::parse_netdoc_multiple::<RouterDescUnverified>(&input)
1464 .unwrap()
1465 .into_iter()
1466 .map(|rd| rd.unwrap_unverified().0)
1467 .collect::<Vec<RouterDesc>>();
1468 assert_eq!(rd.len(), 20);
1469 assert_eq!(
1470 rd[0].router,
1471 RouterDescIntroItem {
1472 nickname: "test002a".parse().unwrap(),
1473 address: net::Ipv4Addr::LOCALHOST,
1474 orport: 5102,
1475 socksport: 0,
1476 dirport: 7102
1477 }
1478 );
1479 assert_eq!(
1480 rd[0].fingerprint.unwrap(),
1481 "257D 06F0 360B B224 6388 724F 109E C089 5A1D 41FB"
1482 .parse()
1483 .unwrap()
1484 );
1485 }
1486}