tor_netdoc/doc/
routerdesc.rs

1//!
2//! A "router descriptor" is a signed statement that a relay makes
3//! about itself, explaining its keys, its capabilities, its location,
4//! and its status.
5//!
6//! Relays upload their router descriptors to authorities, which use
7//! them to build consensus documents.  Old clients and relays used to
8//! fetch and use router descriptors for all the relays, but nowadays they use
9//! microdescriptors instead.
10//!
11//! Clients still use router descriptors when communicating with
12//! bridges: since bridges are not passed through an authority,
13//! clients accept their descriptors directly.
14//!
15//! For full information about the router descriptor format, see
16//! [dir-spec.txt](https://spec.torproject.org/dir-spec).
17//!
18//! # Limitations
19//!
20//! TODO: This needs to get tested much more!
21//!
22//! TODO: This implementation can be memory-inefficient.  In practice,
23//! it gets really expensive storing policy entries, family
24//! descriptions, parsed keys, and things like that.  We will probably want to
25//! de-duplicate those.
26//!
27//! TODO: There should be accessor functions for some or all of the
28//! fields in RouterDesc.  I'm deferring those until I know what they
29//! should be.
30//!
31//! # Availability
32//!
33//! Most of this module is only available when this crate is built with the
34//! `routerdesc` feature enabled.
35use 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::{AllowAnnotations, Error, NetdocErrorKind as EK, Result, doc};
44
45use ll::pk::ed25519::Ed25519Identity;
46use std::sync::Arc;
47use std::sync::LazyLock;
48use std::{net, time};
49use tor_cert::CertType;
50use tor_checkable::{Timebound, signed, timed};
51use tor_error::{internal, into_internal};
52use tor_llcrypto as ll;
53use tor_llcrypto::pk::rsa::RsaIdentity;
54
55use digest::Digest;
56
57/// Length of a router descriptor digest
58pub const DOC_DIGEST_LEN: usize = 20;
59
60/// The digest of a RouterDesc document, as reported in a NS consensus.
61pub type RdDigest = [u8; DOC_DIGEST_LEN];
62
63/// A router descriptor, with possible annotations.
64#[non_exhaustive]
65pub struct AnnotatedRouterDesc {
66    /// Annotation for this router descriptor; possibly empty.
67    pub ann: RouterAnnotation,
68    /// Underlying router descriptor; signatures not checked yet.
69    pub router: UncheckedRouterDesc,
70}
71
72/// Annotations about a router descriptor, as stored on disc.
73#[derive(Default)]
74#[non_exhaustive]
75pub struct RouterAnnotation {
76    /// Description of where we got this router descriptor
77    pub source: Option<String>,
78    /// When this descriptor was first downloaded.
79    pub downloaded: Option<time::SystemTime>,
80    /// Description of what we're willing to use this descriptor for.
81    pub purpose: Option<String>,
82}
83
84/// Information about a relay, parsed from a router descriptor.
85///
86/// This type does not hold all the information in the router descriptor
87///
88/// # Limitations
89///
90/// See module documentation.
91///
92/// Additionally, some fields that from router descriptors are not yet
93/// parsed: see the comments in ROUTER_BODY_RULES for information about those.
94///
95/// Before using this type to connect to a relay, you MUST check that
96/// it is valid, using is_expired_at().
97#[derive(Clone, Debug)]
98#[non_exhaustive]
99pub struct RouterDesc {
100    /// Human-readable nickname for this relay.
101    ///
102    /// This is not secure, and not guaranteed to be unique.
103    pub nickname: Nickname,
104    /// IPv4 address for this relay.
105    pub ipv4addr: Option<net::Ipv4Addr>,
106    /// IPv4 ORPort for this relay.
107    pub orport: u16,
108    /// IPv6 address and port for this relay.
109    // TODO: we don't use a socketaddrv6 because we don't care about
110    // the flow and scope fields.  We should decide whether that's a
111    // good idea.
112    pub ipv6addr: Option<(net::Ipv6Addr, u16)>,
113    /// Directory port for contacting this relay for direct HTTP
114    /// directory downloads.
115    pub dirport: u16,
116    /// Declared uptime for this relay, in seconds.
117    pub uptime: Option<u64>,
118    /// Time when this router descriptor was published.
119    pub published: time::SystemTime,
120    /// Ed25519 identity certificate (identity key authenticating a
121    /// signing key)
122    pub identity_cert: tor_cert::Ed25519Cert,
123    /// RSA identity key for this relay. (Deprecated; never use this without
124    /// the ed25519 identity as well).
125    pub rsa_identity_key: ll::pk::rsa::PublicKey,
126    /// RSA identity key for this relay. (Deprecated; never use this without
127    /// the ed25519 identity as well).
128    pub rsa_identity: ll::pk::rsa::RsaIdentity,
129    /// Key for extending a circuit to this relay using the ntor protocol.
130    pub ntor_onion_key: ll::pk::curve25519::PublicKey,
131    /// Key for extending a circuit to this relay using the
132    /// (deprecated) TAP protocol.
133    pub tap_onion_key: Option<ll::pk::rsa::PublicKey>,
134    /// List of subprotocol versions supported by this relay.
135    pub proto: Arc<tor_protover::Protocols>,
136    /// True if this relay says it's a directory cache.
137    pub is_dircache: bool,
138    /// True if this relay says that it caches extrainfo documents.
139    pub is_extrainfo_cache: bool,
140    /// Declared family members for this relay.  If two relays are in the
141    /// same family, they shouldn't be used in the same circuit.
142    pub family: Arc<RelayFamily>,
143    /// Declared (and proven) family IDs for this relay. If two relays
144    /// share a family ID, they shouldn't be used in the same circuit.
145    family_ids: Vec<RelayFamilyId>,
146    /// Software and version that this relay says it's running.
147    pub platform: Option<RelayPlatform>,
148    /// A complete address-level policy for which IPv4 addresses this relay
149    /// says it supports.
150    // TODO: these polices can get bulky too. Perhaps we should
151    // de-duplicate them too.
152    pub ipv4_policy: AddrPolicy,
153    /// A summary of which ports this relay is willing to connect to
154    /// on IPv6.
155    pub ipv6_policy: Arc<PortPolicy>,
156}
157
158/// Description of the software a relay is running.
159#[derive(Debug, Clone, PartialEq, Eq)]
160#[non_exhaustive]
161pub enum RelayPlatform {
162    /// Software advertised to be some version of Tor, on some platform.
163    Tor(TorVersion, String),
164    /// Software not advertised to be Tor.
165    Other(String),
166}
167
168impl std::str::FromStr for RelayPlatform {
169    type Err = Error;
170    fn from_str(args: &str) -> Result<Self> {
171        if args.starts_with("Tor ") {
172            let v: Vec<_> = args.splitn(4, ' ').collect();
173            match &v[..] {
174                ["Tor", ver, "on", p] => Ok(RelayPlatform::Tor(ver.parse()?, (*p).to_string())),
175                ["Tor", ver, ..] => Ok(RelayPlatform::Tor(ver.parse()?, "".to_string())),
176                _ => unreachable!(),
177            }
178        } else {
179            Ok(RelayPlatform::Other(args.to_string()))
180        }
181    }
182}
183
184decl_keyword! {
185    /// RouterKwd is an instance of Keyword, used to denote the different
186    /// Items that are recognized as appearing in a router descriptor.
187    RouterKwd {
188        annotation "@source" => ANN_SOURCE,
189        annotation "@downloaded-at" => ANN_DOWNLOADED_AT,
190        annotation "@purpose" => ANN_PURPOSE,
191        "accept" | "reject" => POLICY,
192        "bandwidth" => BANDWIDTH,
193        "bridge-distribution-request" => BRIDGE_DISTRIBUTION_REQUEST,
194        "caches-extra-info" => CACHES_EXTRA_INFO,
195        "contact" => CONTACT,
196        "extra-info-digest" => EXTRA_INFO_DIGEST,
197        "family" => FAMILY,
198        "family-cert" => FAMILY_CERT,
199        "fingerprint" => FINGERPRINT,
200        "hibernating" => HIBERNATING,
201        "identity-ed25519" => IDENTITY_ED25519,
202        "ipv6-policy" => IPV6_POLICY,
203        "master-key-ed25519" => MASTER_KEY_ED25519,
204        "ntor-onion-key" => NTOR_ONION_KEY,
205        "ntor-onion-key-crosscert" => NTOR_ONION_KEY_CROSSCERT,
206        "onion-key" => ONION_KEY,
207        "onion-key-crosscert" => ONION_KEY_CROSSCERT,
208        "or-address" => OR_ADDRESS,
209        "platform" => PLATFORM,
210        "proto" => PROTO,
211        "published" => PUBLISHED,
212        "router" => ROUTER,
213        "router-sig-ed25519" => ROUTER_SIG_ED25519,
214        "router-signature" => ROUTER_SIGNATURE,
215        "signing-key" => SIGNING_KEY,
216        "tunnelled_dir_server" => TUNNELLED_DIR_SERVER,
217        "uptime" => UPTIME,
218        // "protocols" once existed, but is obsolete
219        // "eventdns" once existed, but is obsolete
220        // "allow-single-hop-exits" is also obsolete.
221    }
222}
223
224/// Rules for parsing a set of router descriptor annotations.
225static ROUTER_ANNOTATIONS: LazyLock<SectionRules<RouterKwd>> = LazyLock::new(|| {
226    use RouterKwd::*;
227
228    let mut rules = SectionRules::builder();
229    rules.add(ANN_SOURCE.rule());
230    rules.add(ANN_DOWNLOADED_AT.rule().args(1..));
231    rules.add(ANN_PURPOSE.rule().args(1..));
232    rules.add(ANN_UNRECOGNIZED.rule().may_repeat().obj_optional());
233    // Unrecognized annotations are fine; anything else is an error in this
234    // context.
235    rules.reject_unrecognized();
236    rules.build()
237});
238/// Rules for tokens that are allowed in the first part of a
239/// router descriptor.
240static ROUTER_HEADER_RULES: LazyLock<SectionRules<RouterKwd>> = LazyLock::new(|| {
241    use RouterKwd::*;
242
243    let mut rules = SectionRules::builder();
244    rules.add(ROUTER.rule().required().args(5..));
245    rules.add(IDENTITY_ED25519.rule().required().no_args().obj_required());
246    // No other intervening tokens are permitted in the header.
247    rules.reject_unrecognized();
248    rules.build()
249});
250/// Rules for  tokens that are allowed in the first part of a
251/// router descriptor.
252static ROUTER_BODY_RULES: LazyLock<SectionRules<RouterKwd>> = LazyLock::new(|| {
253    use RouterKwd::*;
254
255    let mut rules = SectionRules::builder();
256    rules.add(MASTER_KEY_ED25519.rule().required().args(1..));
257    rules.add(PLATFORM.rule());
258    rules.add(PUBLISHED.rule().required());
259    rules.add(FINGERPRINT.rule());
260    rules.add(UPTIME.rule().args(1..));
261    rules.add(ONION_KEY.rule().no_args().obj_required());
262    rules.add(ONION_KEY_CROSSCERT.rule().no_args().obj_required());
263    rules.add(NTOR_ONION_KEY.rule().required().args(1..));
264    rules.add(
265        NTOR_ONION_KEY_CROSSCERT
266            .rule()
267            .required()
268            .args(1..=1)
269            .obj_required(),
270    );
271    rules.add(SIGNING_KEY.rule().no_args().required().obj_required());
272    rules.add(POLICY.rule().may_repeat().args(1..));
273    rules.add(IPV6_POLICY.rule().args(2..));
274    rules.add(FAMILY.rule().args(1..));
275    rules.add(FAMILY_CERT.rule().obj_required().may_repeat());
276    rules.add(CACHES_EXTRA_INFO.rule().no_args());
277    rules.add(OR_ADDRESS.rule().may_repeat().args(1..));
278    rules.add(TUNNELLED_DIR_SERVER.rule());
279    rules.add(PROTO.rule().required().args(1..));
280    rules.add(UNRECOGNIZED.rule().may_repeat().obj_optional());
281    // TODO: these aren't parsed yet.  Only authorities use them.
282    {
283        rules.add(BANDWIDTH.rule().required().args(3..));
284        rules.add(BRIDGE_DISTRIBUTION_REQUEST.rule().args(1..));
285        rules.add(HIBERNATING.rule().args(1..));
286        rules.add(CONTACT.rule());
287    }
288    // TODO: this is ignored for now.
289    {
290        rules.add(EXTRA_INFO_DIGEST.rule().args(1..));
291    }
292    rules.build()
293});
294
295/// Rules for items that appear at the end of a router descriptor.
296static ROUTER_SIG_RULES: LazyLock<SectionRules<RouterKwd>> = LazyLock::new(|| {
297    use RouterKwd::*;
298
299    let mut rules = SectionRules::builder();
300    rules.add(ROUTER_SIG_ED25519.rule().required().args(1..));
301    rules.add(ROUTER_SIGNATURE.rule().required().no_args().obj_required());
302    // No intervening tokens are allowed in the footer.
303    rules.reject_unrecognized();
304    rules.build()
305});
306
307impl RouterAnnotation {
308    /// Extract a single RouterAnnotation (possibly empty) from a reader.
309    fn take_from_reader(reader: &mut NetDocReader<'_, RouterKwd>) -> Result<RouterAnnotation> {
310        use RouterKwd::*;
311        let mut items = reader.pause_at(|item| item.is_ok_with_non_annotation());
312
313        let body = ROUTER_ANNOTATIONS.parse(&mut items)?;
314
315        let source = body.maybe(ANN_SOURCE).args_as_str().map(String::from);
316        let purpose = body.maybe(ANN_PURPOSE).args_as_str().map(String::from);
317        let downloaded = body
318            .maybe(ANN_DOWNLOADED_AT)
319            .parse_args_as_str::<Iso8601TimeSp>()?
320            .map(|t| t.into());
321        Ok(RouterAnnotation {
322            source,
323            downloaded,
324            purpose,
325        })
326    }
327}
328
329/// A parsed router descriptor whose signatures and/or validity times
330/// may or may not be invalid.
331pub type UncheckedRouterDesc = signed::SignatureGated<timed::TimerangeBound<RouterDesc>>;
332
333/// How long after its published time is a router descriptor officially
334/// supposed to be usable?
335const ROUTER_EXPIRY_SECONDS: u64 = 5 * 86400;
336
337/// How long before its published time is a router descriptor usable?
338// TODO(nickm): This valid doesn't match C tor, which only enforces this rule
339// ("routers should not some from the future") at directory authorities, and
340// there only enforces a 12-hour limit (`ROUTER_ALLOW_SKEW`).  Eventually we
341// should probably harmonize these cutoffs.
342const ROUTER_PRE_VALIDITY_SECONDS: u64 = 86400;
343
344impl RouterDesc {
345    /// Return a reference to this relay's RSA identity.
346    pub fn rsa_identity(&self) -> &RsaIdentity {
347        &self.rsa_identity
348    }
349
350    /// Return a reference to this relay's Ed25519 identity.
351    pub fn ed_identity(&self) -> &Ed25519Identity {
352        self.identity_cert
353            .signing_key()
354            .expect("No ed25519 identity key on identity cert")
355    }
356
357    /// Return a reference to the list of subprotocol versions supported by this
358    /// relay.
359    pub fn protocols(&self) -> &tor_protover::Protocols {
360        self.proto.as_ref()
361    }
362
363    /// Return a reference to this relay's Ntor onion key.
364    pub fn ntor_onion_key(&self) -> &ll::pk::curve25519::PublicKey {
365        &self.ntor_onion_key
366    }
367
368    /// Return the publication
369    pub fn published(&self) -> time::SystemTime {
370        self.published
371    }
372
373    /// Return an iterator of every `SocketAddr` at which this descriptor says
374    /// its relay can be reached.
375    pub fn or_ports(&self) -> impl Iterator<Item = net::SocketAddr> + '_ {
376        self.ipv4addr
377            .map(|a| net::SocketAddr::new(a.into(), self.orport))
378            .into_iter()
379            .chain(self.ipv6addr.map(net::SocketAddr::from))
380    }
381
382    /// Return the declared family of this descriptor.
383    pub fn family(&self) -> Arc<RelayFamily> {
384        Arc::clone(&self.family)
385    }
386
387    /// Return the authenticated family IDs of this descriptor.
388    pub fn family_ids(&self) -> &[RelayFamilyId] {
389        &self.family_ids[..]
390    }
391
392    /// Helper: tokenize `s`, and divide it into three validated sections.
393    fn parse_sections<'a>(
394        reader: &mut NetDocReader<'a, RouterKwd>,
395    ) -> Result<(
396        Section<'a, RouterKwd>,
397        Section<'a, RouterKwd>,
398        Section<'a, RouterKwd>,
399    )> {
400        use RouterKwd::*;
401
402        // Parse everything up through the header.
403        let header = ROUTER_HEADER_RULES.parse(
404            reader.pause_at(|item| item.is_ok_with_kwd_not_in(&[ROUTER, IDENTITY_ED25519])),
405        )?;
406
407        // Parse everything up to but not including the signature.
408        let body =
409            ROUTER_BODY_RULES.parse(reader.pause_at(|item| {
410                item.is_ok_with_kwd_in(&[ROUTER_SIGNATURE, ROUTER_SIG_ED25519])
411            }))?;
412
413        // Parse the signature.
414        let sig = ROUTER_SIG_RULES.parse(reader.pause_at(|item| {
415            item.is_ok_with_annotation() || item.is_ok_with_kwd(ROUTER) || item.is_empty_line()
416        }))?;
417
418        Ok((header, body, sig))
419    }
420
421    /// Try to parse `s` as a router descriptor.
422    ///
423    /// Does not actually check liveness or signatures; you need to do that
424    /// yourself before you can do the output.
425    pub fn parse(s: &str) -> Result<UncheckedRouterDesc> {
426        let mut reader = crate::parse::tokenize::NetDocReader::new(s)?;
427        let result = Self::parse_internal(&mut reader).map_err(|e| e.within(s))?;
428        // We permit empty lines at the end of router descriptors, since there's
429        // a known issue in Tor relays that causes them to return them this way.
430        reader
431            .should_be_exhausted_but_for_empty_lines()
432            .map_err(|e| e.within(s))?;
433        Ok(result)
434    }
435
436    /// Helper: parse a router descriptor from `s`.
437    ///
438    /// This function does the same as parse(), but returns errors based on
439    /// byte-wise positions.  The parse() function converts such errors
440    /// into line-and-byte positions.
441    fn parse_internal(r: &mut NetDocReader<'_, RouterKwd>) -> Result<UncheckedRouterDesc> {
442        // TODO: This function is too long!  The little "paragraphs" here
443        // that parse one item at a time should be made into sub-functions.
444        use RouterKwd::*;
445
446        let s = r.str();
447        let (header, body, sig) = RouterDesc::parse_sections(r)?;
448
449        // Unwrap should be safe because inline `required` call should return
450        // `Error::MissingToken` if `ROUTER` is not `Ok`
451        #[allow(clippy::unwrap_used)]
452        let start_offset = header.required(ROUTER)?.offset_in(s).unwrap();
453
454        // ed25519 identity and signing key.
455        let (identity_cert, ed25519_signing_key) = {
456            let cert_tok = header.required(IDENTITY_ED25519)?;
457            // Unwrap should be safe because above `required` call should
458            // return `Error::MissingToken` if `IDENTITY_ED25519` is not `Ok`
459            #[allow(clippy::unwrap_used)]
460            if cert_tok.offset_in(s).unwrap() < start_offset {
461                return Err(EK::MisplacedToken
462                    .with_msg("identity-ed25519")
463                    .at_pos(cert_tok.pos()));
464            }
465            let cert: tor_cert::UncheckedCert = cert_tok
466                .parse_obj::<UnvalidatedEdCert>("ED25519 CERT")?
467                .check_cert_type(tor_cert::CertType::IDENTITY_V_SIGNING)?
468                .into_unchecked()
469                .should_have_signing_key()
470                .map_err(|err| {
471                    EK::BadObjectVal
472                        .err()
473                        .with_source(err)
474                        .at_pos(cert_tok.pos())
475                })?;
476            let sk = *cert.peek_subject_key().as_ed25519().ok_or_else(|| {
477                EK::BadObjectVal
478                    .at_pos(cert_tok.pos())
479                    .with_msg("wrong type for signing key in cert")
480            })?;
481            let sk: ll::pk::ed25519::PublicKey = sk.try_into().map_err(|_| {
482                EK::BadObjectVal
483                    .at_pos(cert_tok.pos())
484                    .with_msg("invalid ed25519 signing key")
485            })?;
486            (cert, sk)
487        };
488
489        // master-key-ed25519: required, and should match certificate.
490        #[allow(unexpected_cfgs)]
491        {
492            let master_key_tok = body.required(MASTER_KEY_ED25519)?;
493            let ed_id: Ed25519Public = master_key_tok.parse_arg(0)?;
494            let ed_id: ll::pk::ed25519::Ed25519Identity = ed_id.into();
495            if ed_id != *identity_cert.peek_signing_key() {
496                #[cfg(not(fuzzing))] // No feature here; never omit in production.
497                return Err(EK::BadObjectVal
498                    .at_pos(master_key_tok.pos())
499                    .with_msg("master-key-ed25519 does not match key in identity-ed25519"));
500            }
501        }
502
503        // Legacy RSA identity
504        let rsa_identity_key: ll::pk::rsa::PublicKey = body
505            .required(SIGNING_KEY)?
506            .parse_obj::<RsaPublic>("RSA PUBLIC KEY")?
507            .check_len_eq(1024)?
508            .check_exponent(65537)?
509            .into();
510        let rsa_identity = rsa_identity_key.to_rsa_identity();
511
512        let ed_sig = sig.required(ROUTER_SIG_ED25519)?;
513        let rsa_sig = sig.required(ROUTER_SIGNATURE)?;
514        // Unwrap should be safe because above `required` calls should return
515        // an `Error::MissingToken` if `ROUTER_...` is not `Ok`
516        #[allow(clippy::unwrap_used)]
517        let ed_sig_pos = ed_sig.offset_in(s).unwrap();
518        #[allow(clippy::unwrap_used)]
519        let rsa_sig_pos = rsa_sig.offset_in(s).unwrap();
520
521        if ed_sig_pos > rsa_sig_pos {
522            return Err(EK::UnexpectedToken
523                .with_msg(ROUTER_SIG_ED25519.to_str())
524                .at_pos(ed_sig.pos()));
525        }
526
527        // Extract ed25519 signature.
528        let ed_signature: ll::pk::ed25519::ValidatableEd25519Signature = {
529            let mut d = ll::d::Sha256::new();
530            d.update(&b"Tor router descriptor signature v1"[..]);
531            let signed_end = ed_sig_pos + b"router-sig-ed25519 ".len();
532            d.update(&s[start_offset..signed_end]);
533            let d = d.finalize();
534            let sig: [u8; 64] = ed_sig
535                .parse_arg::<B64>(0)?
536                .into_array()
537                .map_err(|_| EK::BadSignature.at_pos(ed_sig.pos()))?;
538            let sig = ll::pk::ed25519::Signature::from(sig);
539            ll::pk::ed25519::ValidatableEd25519Signature::new(ed25519_signing_key, sig, &d)
540        };
541
542        // Extract legacy RSA signature.
543        let rsa_signature: ll::pk::rsa::ValidatableRsaSignature = {
544            let mut d = ll::d::Sha1::new();
545            let signed_end = rsa_sig_pos + b"router-signature\n".len();
546            d.update(&s[start_offset..signed_end]);
547            let d = d.finalize();
548            let sig = rsa_sig.obj("SIGNATURE")?;
549            // TODO: we need to accept prefixes here. COMPAT BLOCKER.
550
551            ll::pk::rsa::ValidatableRsaSignature::new(&rsa_identity_key, &sig, &d)
552        };
553
554        // router nickname ipv4addr orport socksport dirport
555        let (nickname, ipv4addr, orport, dirport) = {
556            let rtrline = header.required(ROUTER)?;
557            (
558                rtrline.parse_arg::<Nickname>(0)?,
559                Some(rtrline.parse_arg::<net::Ipv4Addr>(1)?),
560                rtrline.parse_arg(2)?,
561                // Skipping socksport.
562                rtrline.parse_arg(4)?,
563            )
564        };
565
566        // uptime
567        let uptime = body.maybe(UPTIME).parse_arg(0)?;
568
569        // published time.
570        let published = body
571            .required(PUBLISHED)?
572            .args_as_str()
573            .parse::<Iso8601TimeSp>()?
574            .into();
575
576        // ntor key
577        let ntor_onion_key: Curve25519Public = body.required(NTOR_ONION_KEY)?.parse_arg(0)?;
578        let ntor_onion_key: ll::pk::curve25519::PublicKey = ntor_onion_key.into();
579        // ntor crosscert
580        let crosscert_cert: tor_cert::UncheckedCert = {
581            let cc = body.required(NTOR_ONION_KEY_CROSSCERT)?;
582            let sign: u8 = cc.parse_arg(0)?;
583            if sign != 0 && sign != 1 {
584                return Err(EK::BadArgument.at_pos(cc.arg_pos(0)).with_msg("not 0 or 1"));
585            }
586            let ntor_as_ed: ll::pk::ed25519::PublicKey =
587                ll::pk::keymanip::convert_curve25519_to_ed25519_public(&ntor_onion_key, sign)
588                    .ok_or_else(|| {
589                        EK::BadArgument
590                            .at_pos(cc.pos())
591                            .with_msg("Uncheckable crosscert")
592                    })?;
593
594            cc.parse_obj::<UnvalidatedEdCert>("ED25519 CERT")?
595                .check_cert_type(tor_cert::CertType::NTOR_CC_IDENTITY)?
596                .check_subject_key_is(identity_cert.peek_signing_key())?
597                .into_unchecked()
598                .should_be_signed_with(&ntor_as_ed.into())
599                .map_err(|err| EK::BadSignature.err().with_source(err))?
600        };
601
602        // TAP key
603        let tap_onion_key: Option<ll::pk::rsa::PublicKey> = if let Some(tok) = body.get(ONION_KEY) {
604            Some(
605                tok.parse_obj::<RsaPublic>("RSA PUBLIC KEY")?
606                    .check_len_eq(1024)?
607                    .check_exponent(65537)?
608                    .into(),
609            )
610        } else {
611            None
612        };
613
614        // TAP crosscert
615        let tap_crosscert_sig = if let Some(cc_tok) = body.get(ONION_KEY_CROSSCERT) {
616            let cc_val = cc_tok.obj("CROSSCERT")?;
617            let mut signed = Vec::new();
618            signed.extend(rsa_identity.as_bytes());
619            signed.extend(identity_cert.peek_signing_key().as_bytes());
620            Some(ll::pk::rsa::ValidatableRsaSignature::new(
621                tap_onion_key.as_ref().ok_or_else(|| {
622                    EK::MissingToken.with_msg("onion-key-crosscert without onion-key")
623                })?,
624                &cc_val,
625                &signed,
626            ))
627        } else if tap_onion_key.is_some() {
628            return Err(EK::MissingToken.with_msg("onion-key without onion-key-crosscert"));
629        } else {
630            None
631        };
632
633        // List of subprotocol versions
634        let proto = {
635            let proto_tok = body.required(PROTO)?;
636            doc::PROTOVERS_CACHE.intern(
637                proto_tok
638                    .args_as_str()
639                    .parse::<tor_protover::Protocols>()
640                    .map_err(|e| EK::BadArgument.at_pos(proto_tok.pos()).with_source(e))?,
641            )
642        };
643
644        // tunneled-dir-server
645        let is_dircache = (dirport != 0) || body.get(TUNNELLED_DIR_SERVER).is_some();
646
647        // caches-extra-info
648        let is_extrainfo_cache = body.get(CACHES_EXTRA_INFO).is_some();
649
650        // fingerprint: check for consistency with RSA identity.
651        if let Some(fp_tok) = body.get(FINGERPRINT) {
652            let fp: RsaIdentity = fp_tok.args_as_str().parse::<SpFingerprint>()?.into();
653            if fp != rsa_identity {
654                return Err(EK::BadArgument
655                    .at_pos(fp_tok.pos())
656                    .with_msg("fingerprint does not match RSA identity"));
657            }
658        }
659
660        // Family
661        let family = {
662            let mut family = body
663                .maybe(FAMILY)
664                .parse_args_as_str::<RelayFamily>()?
665                .unwrap_or_else(RelayFamily::new);
666            if !family.is_empty() {
667                // If this family is nonempty, we add our own RSA id to it, on
668                // the theory that doing so will improve the odds of having a
669                // canonical family shared by all of the members of this family.
670                // If the family is empty, there's no point in adding our own ID
671                // to it, and doing so would only waste memory.
672                family.push(rsa_identity);
673            }
674            family.intern()
675        };
676
677        // Family ids (for "happy families")
678        let family_certs: Vec<tor_cert::UncheckedCert> = body
679            .slice(FAMILY_CERT)
680            .iter()
681            .map(|ent| {
682                ent.parse_obj::<UnvalidatedEdCert>("FAMILY CERT")?
683                    .check_cert_type(CertType::FAMILY_V_IDENTITY)?
684                    .check_subject_key_is(identity_cert.peek_signing_key())?
685                    .into_unchecked()
686                    .should_have_signing_key()
687                    .map_err(|e| {
688                        EK::BadObjectVal
689                            .with_msg("missing public key")
690                            .at_pos(ent.pos())
691                            .with_source(e)
692                    })
693            })
694            .collect::<Result<_>>()?;
695
696        let mut family_ids: Vec<_> = family_certs
697            .iter()
698            .map(|cert| RelayFamilyId::Ed25519(*cert.peek_signing_key()))
699            .collect();
700        family_ids.sort();
701        family_ids.dedup();
702
703        // or-address
704        // Extract at most one ipv6 address from the list.  It's not great,
705        // but it's what Tor does.
706        let mut ipv6addr = None;
707        for tok in body.slice(OR_ADDRESS) {
708            if let Ok(net::SocketAddr::V6(a)) = tok.parse_arg::<net::SocketAddr>(0) {
709                ipv6addr = Some((*a.ip(), a.port()));
710                break;
711            }
712            // We skip over unparsable addresses. Is that right?
713        }
714
715        // platform
716        let platform = body.maybe(PLATFORM).parse_args_as_str::<RelayPlatform>()?;
717
718        // ipv4_policy
719        let ipv4_policy = {
720            let mut pol = AddrPolicy::new();
721            for ruletok in body.slice(POLICY).iter() {
722                let accept = match ruletok.kwd_str() {
723                    "accept" => RuleKind::Accept,
724                    "reject" => RuleKind::Reject,
725                    _ => {
726                        return Err(Error::from(internal!(
727                            "tried to parse a strange line as a policy"
728                        ))
729                        .at_pos(ruletok.pos()));
730                    }
731                };
732                let pat: AddrPortPattern = ruletok
733                    .args_as_str()
734                    .parse()
735                    .map_err(|e| EK::BadPolicy.at_pos(ruletok.pos()).with_source(e))?;
736                pol.push(accept, pat);
737            }
738            pol
739        };
740
741        // ipv6 policy
742        let ipv6_policy = match body.get(IPV6_POLICY) {
743            Some(p) => p
744                .args_as_str()
745                .parse()
746                .map_err(|e| EK::BadPolicy.at_pos(p.pos()).with_source(e))?,
747            // Unwrap is safe here because str is not empty
748            #[allow(clippy::unwrap_used)]
749            None => "reject 1-65535".parse::<PortPolicy>().unwrap(),
750        };
751
752        // Now we're going to collect signatures and expiration times.
753        let (identity_cert, identity_sig) = identity_cert.dangerously_split().map_err(|err| {
754            EK::BadObjectVal
755                .with_msg("missing public key")
756                .with_source(err)
757        })?;
758        let (crosscert_cert, cc_sig) = crosscert_cert.dangerously_split().map_err(|err| {
759            EK::BadObjectVal
760                .with_msg("missing public key")
761                .with_source(err)
762        })?;
763        let mut signatures: Vec<Box<dyn ll::pk::ValidatableSignature>> = vec![
764            Box::new(rsa_signature),
765            Box::new(ed_signature),
766            Box::new(identity_sig),
767            Box::new(cc_sig),
768        ];
769        if let Some(s) = tap_crosscert_sig {
770            signatures.push(Box::new(s));
771        }
772
773        let identity_cert = identity_cert.dangerously_assume_timely();
774        let crosscert_cert = crosscert_cert.dangerously_assume_timely();
775        let mut expirations = vec![
776            published + time::Duration::new(ROUTER_EXPIRY_SECONDS, 0),
777            identity_cert.expiry(),
778            crosscert_cert.expiry(),
779        ];
780
781        for cert in family_certs {
782            let (inner, sig) = cert.dangerously_split().map_err(into_internal!(
783                "Missing a public key that was previously there."
784            ))?;
785            signatures.push(Box::new(sig));
786            expirations.push(inner.dangerously_assume_timely().expiry());
787        }
788
789        // Unwrap is safe here because `expirations` array is not empty
790        #[allow(clippy::unwrap_used)]
791        let expiry = *expirations.iter().min().unwrap();
792
793        let start_time = published - time::Duration::new(ROUTER_PRE_VALIDITY_SECONDS, 0);
794
795        let desc = RouterDesc {
796            nickname,
797            ipv4addr,
798            orport,
799            ipv6addr,
800            dirport,
801            uptime,
802            published,
803            identity_cert,
804            rsa_identity_key,
805            rsa_identity,
806            ntor_onion_key,
807            tap_onion_key,
808            proto,
809            is_dircache,
810            is_extrainfo_cache,
811            family,
812            family_ids,
813            platform,
814            ipv4_policy,
815            ipv6_policy: ipv6_policy.intern(),
816        };
817
818        let time_gated = timed::TimerangeBound::new(desc, start_time..expiry);
819        let sig_gated = signed::SignatureGated::new(time_gated, signatures);
820
821        Ok(sig_gated)
822    }
823}
824
825/// An iterator that parses one or more (possibly annotated
826/// router descriptors from a string.
827//
828// TODO: This is largely copy-pasted from MicrodescReader. Can/should they
829// be merged?
830pub struct RouterReader<'a> {
831    /// True iff we accept annotations
832    annotated: bool,
833    /// Reader that we're extracting items from.
834    reader: NetDocReader<'a, RouterKwd>,
835}
836
837/// Skip this reader forward until the next thing it reads looks like the
838/// start of a router descriptor.
839///
840/// Used to recover from errors.
841fn advance_to_next_routerdesc(reader: &mut NetDocReader<'_, RouterKwd>, annotated: bool) {
842    use RouterKwd::*;
843    loop {
844        let item = reader.peek();
845        match item {
846            Some(Ok(t)) => {
847                let kwd = t.kwd();
848                if (annotated && kwd.is_annotation()) || kwd == ROUTER {
849                    return;
850                }
851            }
852            Some(Err(_)) => {
853                // Skip over broken tokens.
854            }
855            None => {
856                return;
857            }
858        }
859        let _ = reader.next();
860    }
861}
862
863impl<'a> RouterReader<'a> {
864    /// Construct a RouterReader to take router descriptors from a string.
865    pub fn new(s: &'a str, allow: &AllowAnnotations) -> Result<Self> {
866        let reader = NetDocReader::new(s)?;
867        let annotated = allow == &AllowAnnotations::AnnotationsAllowed;
868        Ok(RouterReader { annotated, reader })
869    }
870
871    /// Extract an annotation from this reader.
872    fn take_annotation(&mut self) -> Result<RouterAnnotation> {
873        if self.annotated {
874            RouterAnnotation::take_from_reader(&mut self.reader)
875        } else {
876            Ok(RouterAnnotation::default())
877        }
878    }
879
880    /// Extract an annotated router descriptor from this reader
881    ///
882    /// (internal helper; does not clean up on failures.)
883    fn take_annotated_routerdesc_raw(&mut self) -> Result<AnnotatedRouterDesc> {
884        let ann = self.take_annotation()?;
885        let router = RouterDesc::parse_internal(&mut self.reader)?;
886        Ok(AnnotatedRouterDesc { ann, router })
887    }
888
889    /// Extract an annotated router descriptor from this reader
890    ///
891    /// Ensure that at least one token is consumed
892    fn take_annotated_routerdesc(&mut self) -> Result<AnnotatedRouterDesc> {
893        let pos_orig = self.reader.pos();
894        let result = self.take_annotated_routerdesc_raw();
895        if result.is_err() {
896            if self.reader.pos() == pos_orig {
897                // No tokens were consumed from the reader.  We need
898                // to drop at least one token to ensure we aren't in
899                // an infinite loop.
900                //
901                // (This might not be able to happen, but it's easier to
902                // explicitly catch this case than it is to prove that
903                // it's impossible.)
904                let _ = self.reader.next();
905            }
906            advance_to_next_routerdesc(&mut self.reader, self.annotated);
907        }
908        result
909    }
910}
911
912impl<'a> Iterator for RouterReader<'a> {
913    type Item = Result<AnnotatedRouterDesc>;
914    fn next(&mut self) -> Option<Self::Item> {
915        // Is there a next token? If not, we're done.
916        self.reader.peek()?;
917
918        Some(
919            self.take_annotated_routerdesc()
920                .map_err(|e| e.within(self.reader.str())),
921        )
922    }
923}
924
925#[cfg(test)]
926mod test {
927    // @@ begin test lint list maintained by maint/add_warning @@
928    #![allow(clippy::bool_assert_comparison)]
929    #![allow(clippy::clone_on_copy)]
930    #![allow(clippy::dbg_macro)]
931    #![allow(clippy::mixed_attributes_style)]
932    #![allow(clippy::print_stderr)]
933    #![allow(clippy::print_stdout)]
934    #![allow(clippy::single_char_pattern)]
935    #![allow(clippy::unwrap_used)]
936    #![allow(clippy::unchecked_duration_subtraction)]
937    #![allow(clippy::useless_vec)]
938    #![allow(clippy::needless_pass_by_value)]
939    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
940    use super::*;
941    const TESTDATA: &str = include_str!("../../testdata/routerdesc1.txt");
942    const TESTDATA2: &str = include_str!("../../testdata/routerdesc2.txt");
943    // Generated with a patched C tor to include "happy family" IDs.
944    const TESTDATA3: &str = include_str!("../../testdata/routerdesc3.txt");
945
946    fn read_bad(fname: &str) -> String {
947        use std::fs;
948        use std::path::PathBuf;
949        let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
950        path.push("testdata");
951        path.push("bad-routerdesc");
952        path.push(fname);
953
954        fs::read_to_string(path).unwrap()
955    }
956
957    #[test]
958    fn parse_arbitrary() -> Result<()> {
959        use std::str::FromStr;
960        use tor_checkable::{SelfSigned, Timebound};
961        let rd = RouterDesc::parse(TESTDATA)?
962            .check_signature()?
963            .dangerously_assume_timely();
964
965        assert_eq!(rd.nickname.as_str(), "Akka");
966        assert_eq!(rd.orport, 443);
967        assert_eq!(rd.dirport, 0);
968        assert_eq!(rd.uptime, Some(1036923));
969        assert_eq!(
970            rd.family.as_ref(),
971            &RelayFamily::from_str(
972                "$303509ab910ef207b7438c27435c4a2fd579f1b1 \
973                 $56927e61b51e6f363fb55498150a6ddfcf7077f2"
974            )
975            .unwrap()
976        );
977
978        assert_eq!(
979            rd.rsa_identity().to_string(),
980            "$56927e61b51e6f363fb55498150a6ddfcf7077f2"
981        );
982        assert_eq!(
983            rd.ed_identity().to_string(),
984            "CVTjf1oeaL616hH+1+UvYZ8OgkwF3z7UMITvJzm5r7A"
985        );
986        assert_eq!(
987            rd.protocols().to_string(),
988            "Cons=1-2 Desc=1-2 DirCache=2 FlowCtrl=1-2 HSDir=2 \
989             HSIntro=4-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 \
990             Padding=2 Relay=1-4"
991        );
992
993        assert_eq!(
994            hex::encode(rd.ntor_onion_key().to_bytes()),
995            "329b3b52991613392e35d1a821dd6753e1210458ecc3337f7b7d39bfcf5da273"
996        );
997        assert_eq!(
998            rd.published(),
999            humantime::parse_rfc3339("2022-11-14T19:58:52Z").unwrap()
1000        );
1001        assert_eq!(
1002            rd.or_ports().collect::<Vec<_>>(),
1003            vec![
1004                "95.216.33.58:443".parse().unwrap(),
1005                "[2a01:4f9:2a:2145::2]:443".parse().unwrap(),
1006            ]
1007        );
1008        assert!(rd.tap_onion_key.is_some());
1009
1010        Ok(())
1011    }
1012
1013    #[test]
1014    fn parse_no_tap_key() -> Result<()> {
1015        use tor_checkable::{SelfSigned, Timebound};
1016        let rd = RouterDesc::parse(TESTDATA2)?
1017            .check_signature()?
1018            .dangerously_assume_timely();
1019        assert!(rd.tap_onion_key.is_none());
1020
1021        Ok(())
1022    }
1023
1024    #[test]
1025    fn test_bad() {
1026        use crate::Pos;
1027        use crate::types::policy::PolicyError;
1028        fn check(fname: &str, e: &Error) {
1029            let text = read_bad(fname);
1030            let rd = RouterDesc::parse(&text);
1031            assert!(rd.is_err());
1032            assert_eq!(&rd.err().unwrap(), e);
1033        }
1034
1035        check(
1036            "bad-sig-order",
1037            &EK::UnexpectedToken
1038                .with_msg("router-sig-ed25519")
1039                .at_pos(Pos::from_line(50, 1)),
1040        );
1041        check(
1042            "bad-start1",
1043            &EK::MisplacedToken
1044                .with_msg("identity-ed25519")
1045                .at_pos(Pos::from_line(1, 1)),
1046        );
1047        check("bad-start2", &EK::MissingToken.with_msg("identity-ed25519"));
1048        check(
1049            "mismatched-fp",
1050            &EK::BadArgument
1051                .at_pos(Pos::from_line(12, 1))
1052                .with_msg("fingerprint does not match RSA identity"),
1053        );
1054        check("no-ed-sk", &EK::MissingToken.with_msg("identity-ed25519"));
1055
1056        check(
1057            "bad-cc-sign",
1058            &EK::BadArgument
1059                .at_pos(Pos::from_line(34, 26))
1060                .with_msg("not 0 or 1"),
1061        );
1062        check(
1063            "bad-ipv6policy",
1064            &EK::BadPolicy
1065                .at_pos(Pos::from_line(43, 1))
1066                .with_source(PolicyError::InvalidPolicy),
1067        );
1068        check(
1069            "no-ed-id-key-in-cert",
1070            &EK::BadObjectVal
1071                .at_pos(Pos::from_line(2, 1))
1072                .with_source(tor_cert::CertError::MissingPubKey),
1073        );
1074        check(
1075            "non-ed-sk-in-cert",
1076            &EK::BadObjectVal
1077                .at_pos(Pos::from_line(2, 1))
1078                .with_msg("wrong type for signing key in cert"),
1079        );
1080        check(
1081            "bad-ed-sk-in-cert",
1082            &EK::BadObjectVal
1083                .at_pos(Pos::from_line(2, 1))
1084                .with_msg("invalid ed25519 signing key"),
1085        );
1086        check(
1087            "mismatched-ed-sk-in-cert",
1088            &EK::BadObjectVal
1089                .at_pos(Pos::from_line(8, 1))
1090                .with_msg("master-key-ed25519 does not match key in identity-ed25519"),
1091        );
1092    }
1093
1094    #[test]
1095    fn parse_multiple_annotated() {
1096        use crate::AllowAnnotations;
1097        let mut s = read_bad("bad-cc-sign");
1098        s += "\
1099@uploaded-at 2020-09-26 18:15:41
1100@source \"127.0.0.1\"
1101";
1102        s += TESTDATA;
1103        s += "\
1104@uploaded-at 2020-09-26 18:15:41
1105@source \"127.0.0.1\"
1106";
1107        s += &read_bad("mismatched-fp");
1108
1109        let rd = RouterReader::new(&s, &AllowAnnotations::AnnotationsAllowed).unwrap();
1110        let v: Vec<_> = rd.collect();
1111        assert!(v[0].is_err());
1112        assert!(v[1].is_ok());
1113        assert_eq!(
1114            v[1].as_ref().unwrap().ann.source,
1115            Some("\"127.0.0.1\"".to_string())
1116        );
1117        assert!(v[2].is_err());
1118    }
1119
1120    #[test]
1121    fn test_platform() {
1122        let p = "Tor 0.4.4.4-alpha on a flying bison".parse::<RelayPlatform>();
1123        assert!(p.is_ok());
1124        assert_eq!(
1125            p.unwrap(),
1126            RelayPlatform::Tor(
1127                "0.4.4.4-alpha".parse().unwrap(),
1128                "a flying bison".to_string()
1129            )
1130        );
1131
1132        let p = "Tor 0.4.4.4-alpha on".parse::<RelayPlatform>();
1133        assert!(p.is_ok());
1134
1135        let p = "Tor 0.4.4.4-alpha ".parse::<RelayPlatform>();
1136        assert!(p.is_ok());
1137        let p = "Tor 0.4.4.4-alpha".parse::<RelayPlatform>();
1138        assert!(p.is_ok());
1139
1140        let p = "arti 0.0.0".parse::<RelayPlatform>();
1141        assert!(p.is_ok());
1142        assert_eq!(p.unwrap(), RelayPlatform::Other("arti 0.0.0".to_string()));
1143    }
1144
1145    #[test]
1146    fn test_family_ids() -> Result<()> {
1147        use tor_checkable::{SelfSigned, Timebound};
1148        let rd = RouterDesc::parse(TESTDATA3)?
1149            .check_signature()?
1150            .dangerously_assume_timely();
1151
1152        assert_eq!(
1153            rd.family_ids(),
1154            &[
1155                "ed25519:7sToQRuge1bU2hS0CG0ViMndc4m82JhO4B4kdrQey80"
1156                    .parse()
1157                    .unwrap(),
1158                "ed25519:szHUS3ItRd9uk85b1UVnOZx1gg4B0266jCpbuIMNjcM"
1159                    .parse()
1160                    .unwrap(),
1161            ]
1162        );
1163
1164        Ok(())
1165    }
1166}