Skip to main content

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