1use crate::parse::keyword::Keyword;
36use crate::parse::parser::{Section, SectionRules};
37use crate::parse::tokenize::{ItemResult, NetDocReader};
38use crate::types::family::{RelayFamily, RelayFamilyId};
39use crate::types::misc::*;
40use crate::types::policy::*;
41use crate::types::version::TorVersion;
42use crate::util::PeekableIterator;
43use crate::{doc, AllowAnnotations, Error, NetdocErrorKind as EK, Result};
44
45use ll::pk::ed25519::Ed25519Identity;
46use once_cell::sync::Lazy;
47use std::sync::Arc;
48use std::{net, time};
49use tor_cert::CertType;
50use tor_checkable::{signed, timed, Timebound};
51use tor_error::{internal, into_internal};
52use tor_llcrypto as ll;
53use tor_llcrypto::pk::rsa::RsaIdentity;
54
55use digest::Digest;
56
57pub type RdDigest = [u8; 20];
59
60#[allow(dead_code)]
62#[cfg_attr(
63 feature = "dangerous-expose-struct-fields",
64 visible::StructFields(pub),
65 non_exhaustive
66)]
67pub struct AnnotatedRouterDesc {
68 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
70 ann: RouterAnnotation,
71 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
73 router: UncheckedRouterDesc,
74}
75
76#[allow(dead_code)] #[cfg_attr(
79 feature = "dangerous-expose-struct-fields",
80 visible::StructFields(pub),
81 non_exhaustive
82)]
83#[derive(Default)]
84pub struct RouterAnnotation {
85 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
87 source: Option<String>,
88 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
90 downloaded: Option<time::SystemTime>,
91 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
93 purpose: Option<String>,
94}
95
96#[allow(dead_code)] #[cfg_attr(
111 feature = "dangerous-expose-struct-fields",
112 visible::StructFields(pub),
113 non_exhaustive
114)]
115#[derive(Clone, Debug)]
116pub struct RouterDesc {
117 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
121 nickname: Nickname,
122 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
124 ipv4addr: Option<net::Ipv4Addr>,
125 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
127 orport: u16,
128 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
133 ipv6addr: Option<(net::Ipv6Addr, u16)>,
134 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
137 dirport: u16,
138 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
140 uptime: Option<u64>,
141 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
143 published: time::SystemTime,
144 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
147 identity_cert: tor_cert::Ed25519Cert,
148 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
151 rsa_identity_key: ll::pk::rsa::PublicKey,
152 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
155 rsa_identity: ll::pk::rsa::RsaIdentity,
156 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
158 ntor_onion_key: ll::pk::curve25519::PublicKey,
159 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
162 tap_onion_key: Option<ll::pk::rsa::PublicKey>,
163 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
165 proto: Arc<tor_protover::Protocols>,
166 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
168 is_dircache: bool,
169 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
171 is_extrainfo_cache: bool,
172 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
175 family: Arc<RelayFamily>,
176 family_ids: Vec<RelayFamilyId>,
179 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
181 platform: Option<RelayPlatform>,
182 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
187 ipv4_policy: AddrPolicy,
188 #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
191 ipv6_policy: Arc<PortPolicy>,
192}
193
194#[derive(Debug, Clone, PartialEq, Eq)]
196#[non_exhaustive]
197pub enum RelayPlatform {
198 Tor(TorVersion, String),
200 Other(String),
202}
203
204impl std::str::FromStr for RelayPlatform {
205 type Err = Error;
206 fn from_str(args: &str) -> Result<Self> {
207 if args.starts_with("Tor ") {
208 let v: Vec<_> = args.splitn(4, ' ').collect();
209 match &v[..] {
210 ["Tor", ver, "on", p] => Ok(RelayPlatform::Tor(ver.parse()?, (*p).to_string())),
211 ["Tor", ver, ..] => Ok(RelayPlatform::Tor(ver.parse()?, "".to_string())),
212 _ => unreachable!(),
213 }
214 } else {
215 Ok(RelayPlatform::Other(args.to_string()))
216 }
217 }
218}
219
220decl_keyword! {
221 RouterKwd {
224 annotation "@source" => ANN_SOURCE,
225 annotation "@downloaded-at" => ANN_DOWNLOADED_AT,
226 annotation "@purpose" => ANN_PURPOSE,
227 "accept" | "reject" => POLICY,
228 "bandwidth" => BANDWIDTH,
229 "bridge-distribution-request" => BRIDGE_DISTRIBUTION_REQUEST,
230 "caches-extra-info" => CACHES_EXTRA_INFO,
231 "contact" => CONTACT,
232 "extra-info-digest" => EXTRA_INFO_DIGEST,
233 "family" => FAMILY,
234 "family-cert" => FAMILY_CERT,
235 "fingerprint" => FINGERPRINT,
236 "hibernating" => HIBERNATING,
237 "identity-ed25519" => IDENTITY_ED25519,
238 "ipv6-policy" => IPV6_POLICY,
239 "master-key-ed25519" => MASTER_KEY_ED25519,
240 "ntor-onion-key" => NTOR_ONION_KEY,
241 "ntor-onion-key-crosscert" => NTOR_ONION_KEY_CROSSCERT,
242 "onion-key" => ONION_KEY,
243 "onion-key-crosscert" => ONION_KEY_CROSSCERT,
244 "or-address" => OR_ADDRESS,
245 "platform" => PLATFORM,
246 "proto" => PROTO,
247 "published" => PUBLISHED,
248 "router" => ROUTER,
249 "router-sig-ed25519" => ROUTER_SIG_ED25519,
250 "router-signature" => ROUTER_SIGNATURE,
251 "signing-key" => SIGNING_KEY,
252 "tunnelled_dir_server" => TUNNELLED_DIR_SERVER,
253 "uptime" => UPTIME,
254 }
258}
259
260static ROUTER_ANNOTATIONS: Lazy<SectionRules<RouterKwd>> = Lazy::new(|| {
262 use RouterKwd::*;
263
264 let mut rules = SectionRules::builder();
265 rules.add(ANN_SOURCE.rule());
266 rules.add(ANN_DOWNLOADED_AT.rule().args(1..));
267 rules.add(ANN_PURPOSE.rule().args(1..));
268 rules.add(ANN_UNRECOGNIZED.rule().may_repeat().obj_optional());
269 rules.reject_unrecognized();
272 rules.build()
273});
274static ROUTER_HEADER_RULES: Lazy<SectionRules<RouterKwd>> = Lazy::new(|| {
277 use RouterKwd::*;
278
279 let mut rules = SectionRules::builder();
280 rules.add(ROUTER.rule().required().args(5..));
281 rules.add(IDENTITY_ED25519.rule().required().no_args().obj_required());
282 rules.reject_unrecognized();
284 rules.build()
285});
286static ROUTER_BODY_RULES: Lazy<SectionRules<RouterKwd>> = Lazy::new(|| {
289 use RouterKwd::*;
290
291 let mut rules = SectionRules::builder();
292 rules.add(MASTER_KEY_ED25519.rule().required().args(1..));
293 rules.add(PLATFORM.rule());
294 rules.add(PUBLISHED.rule().required());
295 rules.add(FINGERPRINT.rule());
296 rules.add(UPTIME.rule().args(1..));
297 rules.add(ONION_KEY.rule().no_args().obj_required());
298 rules.add(ONION_KEY_CROSSCERT.rule().no_args().obj_required());
299 rules.add(NTOR_ONION_KEY.rule().required().args(1..));
300 rules.add(
301 NTOR_ONION_KEY_CROSSCERT
302 .rule()
303 .required()
304 .args(1..=1)
305 .obj_required(),
306 );
307 rules.add(SIGNING_KEY.rule().no_args().required().obj_required());
308 rules.add(POLICY.rule().may_repeat().args(1..));
309 rules.add(IPV6_POLICY.rule().args(2..));
310 rules.add(FAMILY.rule().args(1..));
311 rules.add(FAMILY_CERT.rule().obj_required().may_repeat());
312 rules.add(CACHES_EXTRA_INFO.rule().no_args());
313 rules.add(OR_ADDRESS.rule().may_repeat().args(1..));
314 rules.add(TUNNELLED_DIR_SERVER.rule());
315 rules.add(PROTO.rule().required().args(1..));
316 rules.add(UNRECOGNIZED.rule().may_repeat().obj_optional());
317 {
319 rules.add(BANDWIDTH.rule().required().args(3..));
320 rules.add(BRIDGE_DISTRIBUTION_REQUEST.rule().args(1..));
321 rules.add(HIBERNATING.rule().args(1..));
322 rules.add(CONTACT.rule());
323 }
324 {
326 rules.add(EXTRA_INFO_DIGEST.rule().args(1..));
327 }
328 rules.build()
329});
330
331static ROUTER_SIG_RULES: Lazy<SectionRules<RouterKwd>> = Lazy::new(|| {
333 use RouterKwd::*;
334
335 let mut rules = SectionRules::builder();
336 rules.add(ROUTER_SIG_ED25519.rule().required().args(1..));
337 rules.add(ROUTER_SIGNATURE.rule().required().no_args().obj_required());
338 rules.reject_unrecognized();
340 rules.build()
341});
342
343impl RouterAnnotation {
344 fn take_from_reader(reader: &mut NetDocReader<'_, RouterKwd>) -> Result<RouterAnnotation> {
346 use RouterKwd::*;
347 let mut items = reader.pause_at(|item| item.is_ok_with_non_annotation());
348
349 let body = ROUTER_ANNOTATIONS.parse(&mut items)?;
350
351 let source = body.maybe(ANN_SOURCE).args_as_str().map(String::from);
352 let purpose = body.maybe(ANN_PURPOSE).args_as_str().map(String::from);
353 let downloaded = body
354 .maybe(ANN_DOWNLOADED_AT)
355 .parse_args_as_str::<Iso8601TimeSp>()?
356 .map(|t| t.into());
357 Ok(RouterAnnotation {
358 source,
359 downloaded,
360 purpose,
361 })
362 }
363}
364
365pub type UncheckedRouterDesc = signed::SignatureGated<timed::TimerangeBound<RouterDesc>>;
368
369const ROUTER_EXPIRY_SECONDS: u64 = 5 * 86400;
372
373const ROUTER_PRE_VALIDITY_SECONDS: u64 = 86400;
379
380impl RouterDesc {
381 pub fn rsa_identity(&self) -> &RsaIdentity {
383 &self.rsa_identity
384 }
385
386 pub fn ed_identity(&self) -> &Ed25519Identity {
388 self.identity_cert
389 .signing_key()
390 .expect("No ed25519 identity key on identity cert")
391 }
392
393 pub fn protocols(&self) -> &tor_protover::Protocols {
396 self.proto.as_ref()
397 }
398
399 pub fn ntor_onion_key(&self) -> &ll::pk::curve25519::PublicKey {
401 &self.ntor_onion_key
402 }
403
404 pub fn published(&self) -> time::SystemTime {
406 self.published
407 }
408
409 pub fn or_ports(&self) -> impl Iterator<Item = net::SocketAddr> + '_ {
412 self.ipv4addr
413 .map(|a| net::SocketAddr::new(a.into(), self.orport))
414 .into_iter()
415 .chain(self.ipv6addr.map(net::SocketAddr::from))
416 }
417
418 pub fn family(&self) -> Arc<RelayFamily> {
420 Arc::clone(&self.family)
421 }
422
423 pub fn family_ids(&self) -> &[RelayFamilyId] {
425 &self.family_ids[..]
426 }
427
428 fn parse_sections<'a>(
430 reader: &mut NetDocReader<'a, RouterKwd>,
431 ) -> Result<(
432 Section<'a, RouterKwd>,
433 Section<'a, RouterKwd>,
434 Section<'a, RouterKwd>,
435 )> {
436 use RouterKwd::*;
437
438 let header = ROUTER_HEADER_RULES.parse(
440 reader.pause_at(|item| item.is_ok_with_kwd_not_in(&[ROUTER, IDENTITY_ED25519])),
441 )?;
442
443 let body =
445 ROUTER_BODY_RULES.parse(reader.pause_at(|item| {
446 item.is_ok_with_kwd_in(&[ROUTER_SIGNATURE, ROUTER_SIG_ED25519])
447 }))?;
448
449 let sig = ROUTER_SIG_RULES.parse(reader.pause_at(|item| {
451 item.is_ok_with_annotation() || item.is_ok_with_kwd(ROUTER) || item.is_empty_line()
452 }))?;
453
454 Ok((header, body, sig))
455 }
456
457 pub fn parse(s: &str) -> Result<UncheckedRouterDesc> {
462 let mut reader = crate::parse::tokenize::NetDocReader::new(s)?;
463 let result = Self::parse_internal(&mut reader).map_err(|e| e.within(s))?;
464 reader
467 .should_be_exhausted_but_for_empty_lines()
468 .map_err(|e| e.within(s))?;
469 Ok(result)
470 }
471
472 fn parse_internal(r: &mut NetDocReader<'_, RouterKwd>) -> Result<UncheckedRouterDesc> {
478 use RouterKwd::*;
481
482 let s = r.str();
483 let (header, body, sig) = RouterDesc::parse_sections(r)?;
484
485 #[allow(clippy::unwrap_used)]
488 let start_offset = header.required(ROUTER)?.offset_in(s).unwrap();
489
490 let (identity_cert, ed25519_signing_key) = {
492 let cert_tok = header.required(IDENTITY_ED25519)?;
493 #[allow(clippy::unwrap_used)]
496 if cert_tok.offset_in(s).unwrap() < start_offset {
497 return Err(EK::MisplacedToken
498 .with_msg("identity-ed25519")
499 .at_pos(cert_tok.pos()));
500 }
501 let cert: tor_cert::UncheckedCert = cert_tok
502 .parse_obj::<UnvalidatedEdCert>("ED25519 CERT")?
503 .check_cert_type(tor_cert::CertType::IDENTITY_V_SIGNING)?
504 .into_unchecked()
505 .should_have_signing_key()
506 .map_err(|err| {
507 EK::BadObjectVal
508 .err()
509 .with_source(err)
510 .at_pos(cert_tok.pos())
511 })?;
512 let sk = *cert.peek_subject_key().as_ed25519().ok_or_else(|| {
513 EK::BadObjectVal
514 .at_pos(cert_tok.pos())
515 .with_msg("wrong type for signing key in cert")
516 })?;
517 let sk: ll::pk::ed25519::PublicKey = sk.try_into().map_err(|_| {
518 EK::BadObjectVal
519 .at_pos(cert_tok.pos())
520 .with_msg("invalid ed25519 signing key")
521 })?;
522 (cert, sk)
523 };
524
525 #[allow(unexpected_cfgs)]
527 {
528 let master_key_tok = body.required(MASTER_KEY_ED25519)?;
529 let ed_id: Ed25519Public = master_key_tok.parse_arg(0)?;
530 let ed_id: ll::pk::ed25519::Ed25519Identity = ed_id.into();
531 if ed_id != *identity_cert.peek_signing_key() {
532 #[cfg(not(fuzzing))] return Err(EK::BadObjectVal
534 .at_pos(master_key_tok.pos())
535 .with_msg("master-key-ed25519 does not match key in identity-ed25519"));
536 }
537 }
538
539 let rsa_identity_key: ll::pk::rsa::PublicKey = body
541 .required(SIGNING_KEY)?
542 .parse_obj::<RsaPublic>("RSA PUBLIC KEY")?
543 .check_len_eq(1024)?
544 .check_exponent(65537)?
545 .into();
546 let rsa_identity = rsa_identity_key.to_rsa_identity();
547
548 let ed_sig = sig.required(ROUTER_SIG_ED25519)?;
549 let rsa_sig = sig.required(ROUTER_SIGNATURE)?;
550 #[allow(clippy::unwrap_used)]
553 let ed_sig_pos = ed_sig.offset_in(s).unwrap();
554 #[allow(clippy::unwrap_used)]
555 let rsa_sig_pos = rsa_sig.offset_in(s).unwrap();
556
557 if ed_sig_pos > rsa_sig_pos {
558 return Err(EK::UnexpectedToken
559 .with_msg(ROUTER_SIG_ED25519.to_str())
560 .at_pos(ed_sig.pos()));
561 }
562
563 let ed_signature: ll::pk::ed25519::ValidatableEd25519Signature = {
565 let mut d = ll::d::Sha256::new();
566 d.update(&b"Tor router descriptor signature v1"[..]);
567 let signed_end = ed_sig_pos + b"router-sig-ed25519 ".len();
568 d.update(&s[start_offset..signed_end]);
569 let d = d.finalize();
570 let sig: [u8; 64] = ed_sig
571 .parse_arg::<B64>(0)?
572 .into_array()
573 .map_err(|_| EK::BadSignature.at_pos(ed_sig.pos()))?;
574 let sig = ll::pk::ed25519::Signature::from(sig);
575 ll::pk::ed25519::ValidatableEd25519Signature::new(ed25519_signing_key, sig, &d)
576 };
577
578 let rsa_signature: ll::pk::rsa::ValidatableRsaSignature = {
580 let mut d = ll::d::Sha1::new();
581 let signed_end = rsa_sig_pos + b"router-signature\n".len();
582 d.update(&s[start_offset..signed_end]);
583 let d = d.finalize();
584 let sig = rsa_sig.obj("SIGNATURE")?;
585 ll::pk::rsa::ValidatableRsaSignature::new(&rsa_identity_key, &sig, &d)
588 };
589
590 let (nickname, ipv4addr, orport, dirport) = {
592 let rtrline = header.required(ROUTER)?;
593 (
594 rtrline.parse_arg::<Nickname>(0)?,
595 Some(rtrline.parse_arg::<net::Ipv4Addr>(1)?),
596 rtrline.parse_arg(2)?,
597 rtrline.parse_arg(4)?,
599 )
600 };
601
602 let uptime = body.maybe(UPTIME).parse_arg(0)?;
604
605 let published = body
607 .required(PUBLISHED)?
608 .args_as_str()
609 .parse::<Iso8601TimeSp>()?
610 .into();
611
612 let ntor_onion_key: Curve25519Public = body.required(NTOR_ONION_KEY)?.parse_arg(0)?;
614 let ntor_onion_key: ll::pk::curve25519::PublicKey = ntor_onion_key.into();
615 let crosscert_cert: tor_cert::UncheckedCert = {
617 let cc = body.required(NTOR_ONION_KEY_CROSSCERT)?;
618 let sign: u8 = cc.parse_arg(0)?;
619 if sign != 0 && sign != 1 {
620 return Err(EK::BadArgument.at_pos(cc.arg_pos(0)).with_msg("not 0 or 1"));
621 }
622 let ntor_as_ed: ll::pk::ed25519::PublicKey =
623 ll::pk::keymanip::convert_curve25519_to_ed25519_public(&ntor_onion_key, sign)
624 .ok_or_else(|| {
625 EK::BadArgument
626 .at_pos(cc.pos())
627 .with_msg("Uncheckable crosscert")
628 })?;
629
630 cc.parse_obj::<UnvalidatedEdCert>("ED25519 CERT")?
631 .check_cert_type(tor_cert::CertType::NTOR_CC_IDENTITY)?
632 .check_subject_key_is(identity_cert.peek_signing_key())?
633 .into_unchecked()
634 .should_be_signed_with(&ntor_as_ed.into())
635 .map_err(|err| EK::BadSignature.err().with_source(err))?
636 };
637
638 let tap_onion_key: Option<ll::pk::rsa::PublicKey> = if let Some(tok) = body.get(ONION_KEY) {
640 Some(
641 tok.parse_obj::<RsaPublic>("RSA PUBLIC KEY")?
642 .check_len_eq(1024)?
643 .check_exponent(65537)?
644 .into(),
645 )
646 } else {
647 None
648 };
649
650 let tap_crosscert_sig = if let Some(cc_tok) = body.get(ONION_KEY_CROSSCERT) {
652 let cc_val = cc_tok.obj("CROSSCERT")?;
653 let mut signed = Vec::new();
654 signed.extend(rsa_identity.as_bytes());
655 signed.extend(identity_cert.peek_signing_key().as_bytes());
656 Some(ll::pk::rsa::ValidatableRsaSignature::new(
657 tap_onion_key.as_ref().ok_or_else(|| {
658 EK::MissingToken.with_msg("onion-key-crosscert without onion-key")
659 })?,
660 &cc_val,
661 &signed,
662 ))
663 } else if tap_onion_key.is_some() {
664 return Err(EK::MissingToken.with_msg("onion-key without onion-key-crosscert"));
665 } else {
666 None
667 };
668
669 let proto = {
671 let proto_tok = body.required(PROTO)?;
672 doc::PROTOVERS_CACHE.intern(
673 proto_tok
674 .args_as_str()
675 .parse::<tor_protover::Protocols>()
676 .map_err(|e| EK::BadArgument.at_pos(proto_tok.pos()).with_source(e))?,
677 )
678 };
679
680 let is_dircache = (dirport != 0) || body.get(TUNNELLED_DIR_SERVER).is_some();
682
683 let is_extrainfo_cache = body.get(CACHES_EXTRA_INFO).is_some();
685
686 if let Some(fp_tok) = body.get(FINGERPRINT) {
688 let fp: RsaIdentity = fp_tok.args_as_str().parse::<SpFingerprint>()?.into();
689 if fp != rsa_identity {
690 return Err(EK::BadArgument
691 .at_pos(fp_tok.pos())
692 .with_msg("fingerprint does not match RSA identity"));
693 }
694 }
695
696 let family = {
698 let mut family = body
699 .maybe(FAMILY)
700 .parse_args_as_str::<RelayFamily>()?
701 .unwrap_or_else(RelayFamily::new);
702 if !family.is_empty() {
703 family.push(rsa_identity);
709 }
710 family.intern()
711 };
712
713 let family_certs: Vec<tor_cert::UncheckedCert> = body
715 .slice(FAMILY_CERT)
716 .iter()
717 .map(|ent| {
718 ent.parse_obj::<UnvalidatedEdCert>("FAMILY CERT")?
719 .check_cert_type(CertType::FAMILY_V_IDENTITY)?
720 .check_subject_key_is(identity_cert.peek_signing_key())?
721 .into_unchecked()
722 .should_have_signing_key()
723 .map_err(|e| {
724 EK::BadObjectVal
725 .with_msg("missing public key")
726 .at_pos(ent.pos())
727 .with_source(e)
728 })
729 })
730 .collect::<Result<_>>()?;
731
732 let mut family_ids: Vec<_> = family_certs
733 .iter()
734 .map(|cert| RelayFamilyId::Ed25519(*cert.peek_signing_key()))
735 .collect();
736 family_ids.sort();
737 family_ids.dedup();
738
739 let mut ipv6addr = None;
743 for tok in body.slice(OR_ADDRESS) {
744 if let Ok(net::SocketAddr::V6(a)) = tok.parse_arg::<net::SocketAddr>(0) {
745 ipv6addr = Some((*a.ip(), a.port()));
746 break;
747 }
748 }
750
751 let platform = body.maybe(PLATFORM).parse_args_as_str::<RelayPlatform>()?;
753
754 let ipv4_policy = {
756 let mut pol = AddrPolicy::new();
757 for ruletok in body.slice(POLICY).iter() {
758 let accept = match ruletok.kwd_str() {
759 "accept" => RuleKind::Accept,
760 "reject" => RuleKind::Reject,
761 _ => {
762 return Err(Error::from(internal!(
763 "tried to parse a strange line as a policy"
764 ))
765 .at_pos(ruletok.pos()))
766 }
767 };
768 let pat: AddrPortPattern = ruletok
769 .args_as_str()
770 .parse()
771 .map_err(|e| EK::BadPolicy.at_pos(ruletok.pos()).with_source(e))?;
772 pol.push(accept, pat);
773 }
774 pol
775 };
776
777 let ipv6_policy = match body.get(IPV6_POLICY) {
779 Some(p) => p
780 .args_as_str()
781 .parse()
782 .map_err(|e| EK::BadPolicy.at_pos(p.pos()).with_source(e))?,
783 #[allow(clippy::unwrap_used)]
785 None => "reject 1-65535".parse::<PortPolicy>().unwrap(),
786 };
787
788 let (identity_cert, identity_sig) = identity_cert.dangerously_split().map_err(|err| {
790 EK::BadObjectVal
791 .with_msg("missing public key")
792 .with_source(err)
793 })?;
794 let (crosscert_cert, cc_sig) = crosscert_cert.dangerously_split().map_err(|err| {
795 EK::BadObjectVal
796 .with_msg("missing public key")
797 .with_source(err)
798 })?;
799 let mut signatures: Vec<Box<dyn ll::pk::ValidatableSignature>> = vec![
800 Box::new(rsa_signature),
801 Box::new(ed_signature),
802 Box::new(identity_sig),
803 Box::new(cc_sig),
804 ];
805 if let Some(s) = tap_crosscert_sig {
806 signatures.push(Box::new(s));
807 }
808
809 let identity_cert = identity_cert.dangerously_assume_timely();
810 let crosscert_cert = crosscert_cert.dangerously_assume_timely();
811 let mut expirations = vec![
812 published + time::Duration::new(ROUTER_EXPIRY_SECONDS, 0),
813 identity_cert.expiry(),
814 crosscert_cert.expiry(),
815 ];
816
817 for cert in family_certs {
818 let (inner, sig) = cert.dangerously_split().map_err(into_internal!(
819 "Missing a public key that was previously there."
820 ))?;
821 signatures.push(Box::new(sig));
822 expirations.push(inner.dangerously_assume_timely().expiry());
823 }
824
825 #[allow(clippy::unwrap_used)]
827 let expiry = *expirations.iter().min().unwrap();
828
829 let start_time = published - time::Duration::new(ROUTER_PRE_VALIDITY_SECONDS, 0);
830
831 let desc = RouterDesc {
832 nickname,
833 ipv4addr,
834 orport,
835 ipv6addr,
836 dirport,
837 uptime,
838 published,
839 identity_cert,
840 rsa_identity_key,
841 rsa_identity,
842 ntor_onion_key,
843 tap_onion_key,
844 proto,
845 is_dircache,
846 is_extrainfo_cache,
847 family,
848 family_ids,
849 platform,
850 ipv4_policy,
851 ipv6_policy: ipv6_policy.intern(),
852 };
853
854 let time_gated = timed::TimerangeBound::new(desc, start_time..expiry);
855 let sig_gated = signed::SignatureGated::new(time_gated, signatures);
856
857 Ok(sig_gated)
858 }
859}
860
861pub struct RouterReader<'a> {
867 annotated: bool,
869 reader: NetDocReader<'a, RouterKwd>,
871}
872
873fn advance_to_next_routerdesc(reader: &mut NetDocReader<'_, RouterKwd>, annotated: bool) {
878 use RouterKwd::*;
879 loop {
880 let item = reader.peek();
881 match item {
882 Some(Ok(t)) => {
883 let kwd = t.kwd();
884 if (annotated && kwd.is_annotation()) || kwd == ROUTER {
885 return;
886 }
887 }
888 Some(Err(_)) => {
889 }
891 None => {
892 return;
893 }
894 }
895 let _ = reader.next();
896 }
897}
898
899impl<'a> RouterReader<'a> {
900 pub fn new(s: &'a str, allow: &AllowAnnotations) -> Result<Self> {
902 let reader = NetDocReader::new(s)?;
903 let annotated = allow == &AllowAnnotations::AnnotationsAllowed;
904 Ok(RouterReader { annotated, reader })
905 }
906
907 fn take_annotation(&mut self) -> Result<RouterAnnotation> {
909 if self.annotated {
910 RouterAnnotation::take_from_reader(&mut self.reader)
911 } else {
912 Ok(RouterAnnotation::default())
913 }
914 }
915
916 fn take_annotated_routerdesc_raw(&mut self) -> Result<AnnotatedRouterDesc> {
920 let ann = self.take_annotation()?;
921 let router = RouterDesc::parse_internal(&mut self.reader)?;
922 Ok(AnnotatedRouterDesc { ann, router })
923 }
924
925 fn take_annotated_routerdesc(&mut self) -> Result<AnnotatedRouterDesc> {
929 let pos_orig = self.reader.pos();
930 let result = self.take_annotated_routerdesc_raw();
931 if result.is_err() {
932 if self.reader.pos() == pos_orig {
933 let _ = self.reader.next();
941 }
942 advance_to_next_routerdesc(&mut self.reader, self.annotated);
943 }
944 result
945 }
946}
947
948impl<'a> Iterator for RouterReader<'a> {
949 type Item = Result<AnnotatedRouterDesc>;
950 fn next(&mut self) -> Option<Self::Item> {
951 self.reader.peek()?;
953
954 Some(
955 self.take_annotated_routerdesc()
956 .map_err(|e| e.within(self.reader.str())),
957 )
958 }
959}
960
961#[cfg(test)]
962mod test {
963 #![allow(clippy::bool_assert_comparison)]
965 #![allow(clippy::clone_on_copy)]
966 #![allow(clippy::dbg_macro)]
967 #![allow(clippy::mixed_attributes_style)]
968 #![allow(clippy::print_stderr)]
969 #![allow(clippy::print_stdout)]
970 #![allow(clippy::single_char_pattern)]
971 #![allow(clippy::unwrap_used)]
972 #![allow(clippy::unchecked_duration_subtraction)]
973 #![allow(clippy::useless_vec)]
974 #![allow(clippy::needless_pass_by_value)]
975 use super::*;
977 const TESTDATA: &str = include_str!("../../testdata/routerdesc1.txt");
978 const TESTDATA2: &str = include_str!("../../testdata/routerdesc2.txt");
979 const TESTDATA3: &str = include_str!("../../testdata/routerdesc3.txt");
981
982 fn read_bad(fname: &str) -> String {
983 use std::fs;
984 use std::path::PathBuf;
985 let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
986 path.push("testdata");
987 path.push("bad-routerdesc");
988 path.push(fname);
989
990 fs::read_to_string(path).unwrap()
991 }
992
993 #[test]
994 fn parse_arbitrary() -> Result<()> {
995 use std::str::FromStr;
996 use tor_checkable::{SelfSigned, Timebound};
997 let rd = RouterDesc::parse(TESTDATA)?
998 .check_signature()?
999 .dangerously_assume_timely();
1000
1001 assert_eq!(rd.nickname.as_str(), "Akka");
1002 assert_eq!(rd.orport, 443);
1003 assert_eq!(rd.dirport, 0);
1004 assert_eq!(rd.uptime, Some(1036923));
1005 assert_eq!(
1006 rd.family.as_ref(),
1007 &RelayFamily::from_str(
1008 "$303509ab910ef207b7438c27435c4a2fd579f1b1 \
1009 $56927e61b51e6f363fb55498150a6ddfcf7077f2"
1010 )
1011 .unwrap()
1012 );
1013
1014 assert_eq!(
1015 rd.rsa_identity().to_string(),
1016 "$56927e61b51e6f363fb55498150a6ddfcf7077f2"
1017 );
1018 assert_eq!(
1019 rd.ed_identity().to_string(),
1020 "CVTjf1oeaL616hH+1+UvYZ8OgkwF3z7UMITvJzm5r7A"
1021 );
1022 assert_eq!(
1023 rd.protocols().to_string(),
1024 "Cons=1-2 Desc=1-2 DirCache=2 FlowCtrl=1-2 HSDir=2 \
1025 HSIntro=4-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 \
1026 Padding=2 Relay=1-4"
1027 );
1028
1029 assert_eq!(
1030 hex::encode(rd.ntor_onion_key().to_bytes()),
1031 "329b3b52991613392e35d1a821dd6753e1210458ecc3337f7b7d39bfcf5da273"
1032 );
1033 assert_eq!(
1034 rd.published(),
1035 humantime::parse_rfc3339("2022-11-14T19:58:52Z").unwrap()
1036 );
1037 assert_eq!(
1038 rd.or_ports().collect::<Vec<_>>(),
1039 vec![
1040 "95.216.33.58:443".parse().unwrap(),
1041 "[2a01:4f9:2a:2145::2]:443".parse().unwrap(),
1042 ]
1043 );
1044 assert!(rd.tap_onion_key.is_some());
1045
1046 Ok(())
1047 }
1048
1049 #[test]
1050 fn parse_no_tap_key() -> Result<()> {
1051 use tor_checkable::{SelfSigned, Timebound};
1052 let rd = RouterDesc::parse(TESTDATA2)?
1053 .check_signature()?
1054 .dangerously_assume_timely();
1055 assert!(rd.tap_onion_key.is_none());
1056
1057 Ok(())
1058 }
1059
1060 #[test]
1061 fn test_bad() {
1062 use crate::types::policy::PolicyError;
1063 use crate::Pos;
1064 fn check(fname: &str, e: &Error) {
1065 let text = read_bad(fname);
1066 let rd = RouterDesc::parse(&text);
1067 assert!(rd.is_err());
1068 assert_eq!(&rd.err().unwrap(), e);
1069 }
1070
1071 check(
1072 "bad-sig-order",
1073 &EK::UnexpectedToken
1074 .with_msg("router-sig-ed25519")
1075 .at_pos(Pos::from_line(50, 1)),
1076 );
1077 check(
1078 "bad-start1",
1079 &EK::MisplacedToken
1080 .with_msg("identity-ed25519")
1081 .at_pos(Pos::from_line(1, 1)),
1082 );
1083 check("bad-start2", &EK::MissingToken.with_msg("identity-ed25519"));
1084 check(
1085 "mismatched-fp",
1086 &EK::BadArgument
1087 .at_pos(Pos::from_line(12, 1))
1088 .with_msg("fingerprint does not match RSA identity"),
1089 );
1090 check("no-ed-sk", &EK::MissingToken.with_msg("identity-ed25519"));
1091
1092 check(
1093 "bad-cc-sign",
1094 &EK::BadArgument
1095 .at_pos(Pos::from_line(34, 26))
1096 .with_msg("not 0 or 1"),
1097 );
1098 check(
1099 "bad-ipv6policy",
1100 &EK::BadPolicy
1101 .at_pos(Pos::from_line(43, 1))
1102 .with_source(PolicyError::InvalidPolicy),
1103 );
1104 check(
1105 "no-ed-id-key-in-cert",
1106 &EK::BadObjectVal
1107 .at_pos(Pos::from_line(2, 1))
1108 .with_source(tor_cert::CertError::MissingPubKey),
1109 );
1110 check(
1111 "non-ed-sk-in-cert",
1112 &EK::BadObjectVal
1113 .at_pos(Pos::from_line(2, 1))
1114 .with_msg("wrong type for signing key in cert"),
1115 );
1116 check(
1117 "bad-ed-sk-in-cert",
1118 &EK::BadObjectVal
1119 .at_pos(Pos::from_line(2, 1))
1120 .with_msg("invalid ed25519 signing key"),
1121 );
1122 check(
1123 "mismatched-ed-sk-in-cert",
1124 &EK::BadObjectVal
1125 .at_pos(Pos::from_line(8, 1))
1126 .with_msg("master-key-ed25519 does not match key in identity-ed25519"),
1127 );
1128 }
1129
1130 #[test]
1131 fn parse_multiple_annotated() {
1132 use crate::AllowAnnotations;
1133 let mut s = read_bad("bad-cc-sign");
1134 s += "\
1135@uploaded-at 2020-09-26 18:15:41
1136@source \"127.0.0.1\"
1137";
1138 s += TESTDATA;
1139 s += "\
1140@uploaded-at 2020-09-26 18:15:41
1141@source \"127.0.0.1\"
1142";
1143 s += &read_bad("mismatched-fp");
1144
1145 let rd = RouterReader::new(&s, &AllowAnnotations::AnnotationsAllowed).unwrap();
1146 let v: Vec<_> = rd.collect();
1147 assert!(v[0].is_err());
1148 assert!(v[1].is_ok());
1149 assert_eq!(
1150 v[1].as_ref().unwrap().ann.source,
1151 Some("\"127.0.0.1\"".to_string())
1152 );
1153 assert!(v[2].is_err());
1154 }
1155
1156 #[test]
1157 fn test_platform() {
1158 let p = "Tor 0.4.4.4-alpha on a flying bison".parse::<RelayPlatform>();
1159 assert!(p.is_ok());
1160 assert_eq!(
1161 p.unwrap(),
1162 RelayPlatform::Tor(
1163 "0.4.4.4-alpha".parse().unwrap(),
1164 "a flying bison".to_string()
1165 )
1166 );
1167
1168 let p = "Tor 0.4.4.4-alpha on".parse::<RelayPlatform>();
1169 assert!(p.is_ok());
1170
1171 let p = "Tor 0.4.4.4-alpha ".parse::<RelayPlatform>();
1172 assert!(p.is_ok());
1173 let p = "Tor 0.4.4.4-alpha".parse::<RelayPlatform>();
1174 assert!(p.is_ok());
1175
1176 let p = "arti 0.0.0".parse::<RelayPlatform>();
1177 assert!(p.is_ok());
1178 assert_eq!(p.unwrap(), RelayPlatform::Other("arti 0.0.0".to_string()));
1179 }
1180
1181 #[test]
1182 fn test_family_ids() -> Result<()> {
1183 use tor_checkable::{SelfSigned, Timebound};
1184 let rd = RouterDesc::parse(TESTDATA3)?
1185 .check_signature()?
1186 .dangerously_assume_timely();
1187
1188 assert_eq!(
1189 rd.family_ids(),
1190 &[
1191 "ed25519:7sToQRuge1bU2hS0CG0ViMndc4m82JhO4B4kdrQey80"
1192 .parse()
1193 .unwrap(),
1194 "ed25519:szHUS3ItRd9uk85b1UVnOZx1gg4B0266jCpbuIMNjcM"
1195 .parse()
1196 .unwrap(),
1197 ]
1198 );
1199
1200 Ok(())
1201 }
1202}