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, KeywordEncodable, NetdocErrorKind as EK, Result};
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: 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
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::<RsaPublicParse1Helper>("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::<RsaPublicParse1Helper>("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            proto_tok
637                .args_as_str()
638                .parse::<tor_protover::Protocols>()
639                .map_err(|e| EK::BadArgument.at_pos(proto_tok.pos()).with_source(e))?
640        };
641
642        // tunneled-dir-server
643        let is_dircache = (dirport != 0) || body.get(TUNNELLED_DIR_SERVER).is_some();
644
645        // caches-extra-info
646        let is_extrainfo_cache = body.get(CACHES_EXTRA_INFO).is_some();
647
648        // fingerprint: check for consistency with RSA identity.
649        if let Some(fp_tok) = body.get(FINGERPRINT) {
650            let fp: RsaIdentity = fp_tok.args_as_str().parse::<SpFingerprint>()?.into();
651            if fp != rsa_identity {
652                return Err(EK::BadArgument
653                    .at_pos(fp_tok.pos())
654                    .with_msg("fingerprint does not match RSA identity"));
655            }
656        }
657
658        // Family
659        let family = {
660            let mut family = body
661                .maybe(FAMILY)
662                .parse_args_as_str::<RelayFamily>()?
663                .unwrap_or_else(RelayFamily::new);
664            if !family.is_empty() {
665                // If this family is nonempty, we add our own RSA id to it, on
666                // the theory that doing so will improve the odds of having a
667                // canonical family shared by all of the members of this family.
668                // If the family is empty, there's no point in adding our own ID
669                // to it, and doing so would only waste memory.
670                family.push(rsa_identity);
671            }
672            family.intern()
673        };
674
675        // Family ids (for "happy families")
676        let family_certs: Vec<tor_cert::UncheckedCert> = body
677            .slice(FAMILY_CERT)
678            .iter()
679            .map(|ent| {
680                ent.parse_obj::<UnvalidatedEdCert>("FAMILY CERT")?
681                    .check_cert_type(CertType::FAMILY_V_IDENTITY)?
682                    .check_subject_key_is(identity_cert.peek_signing_key())?
683                    .into_unchecked()
684                    .should_have_signing_key()
685                    .map_err(|e| {
686                        EK::BadObjectVal
687                            .with_msg("missing public key")
688                            .at_pos(ent.pos())
689                            .with_source(e)
690                    })
691            })
692            .collect::<Result<_>>()?;
693
694        let mut family_ids: Vec<_> = family_certs
695            .iter()
696            .map(|cert| RelayFamilyId::Ed25519(*cert.peek_signing_key()))
697            .collect();
698        family_ids.sort();
699        family_ids.dedup();
700
701        // or-address
702        // Extract at most one ipv6 address from the list.  It's not great,
703        // but it's what Tor does.
704        let mut ipv6addr = None;
705        for tok in body.slice(OR_ADDRESS) {
706            if let Ok(net::SocketAddr::V6(a)) = tok.parse_arg::<net::SocketAddr>(0) {
707                ipv6addr = Some((*a.ip(), a.port()));
708                break;
709            }
710            // We skip over unparsable addresses. Is that right?
711        }
712
713        // platform
714        let platform = body.maybe(PLATFORM).parse_args_as_str::<RelayPlatform>()?;
715
716        // ipv4_policy
717        let ipv4_policy = {
718            let mut pol = AddrPolicy::new();
719            for ruletok in body.slice(POLICY).iter() {
720                let accept = match ruletok.kwd_str() {
721                    "accept" => RuleKind::Accept,
722                    "reject" => RuleKind::Reject,
723                    _ => {
724                        return Err(Error::from(internal!(
725                            "tried to parse a strange line as a policy"
726                        ))
727                        .at_pos(ruletok.pos()));
728                    }
729                };
730                let pat: AddrPortPattern = ruletok
731                    .args_as_str()
732                    .parse()
733                    .map_err(|e| EK::BadPolicy.at_pos(ruletok.pos()).with_source(e))?;
734                pol.push(accept, pat);
735            }
736            pol
737        };
738
739        // ipv6 policy
740        let ipv6_policy = match body.get(IPV6_POLICY) {
741            Some(p) => p
742                .args_as_str()
743                .parse()
744                .map_err(|e| EK::BadPolicy.at_pos(p.pos()).with_source(e))?,
745            // Unwrap is safe here because str is not empty
746            #[allow(clippy::unwrap_used)]
747            None => "reject 1-65535".parse::<PortPolicy>().unwrap(),
748        };
749
750        // Now we're going to collect signatures and expiration times.
751        let (identity_cert, identity_sig) = identity_cert.dangerously_split().map_err(|err| {
752            EK::BadObjectVal
753                .with_msg("missing public key")
754                .with_source(err)
755        })?;
756        let (crosscert_cert, cc_sig) = crosscert_cert.dangerously_split().map_err(|err| {
757            EK::BadObjectVal
758                .with_msg("missing public key")
759                .with_source(err)
760        })?;
761        let mut signatures: Vec<Box<dyn ll::pk::ValidatableSignature>> = vec![
762            Box::new(rsa_signature),
763            Box::new(ed_signature),
764            Box::new(identity_sig),
765            Box::new(cc_sig),
766        ];
767        if let Some(s) = tap_crosscert_sig {
768            signatures.push(Box::new(s));
769        }
770
771        let identity_cert = identity_cert.dangerously_assume_timely();
772        let crosscert_cert = crosscert_cert.dangerously_assume_timely();
773        let mut expirations = vec![
774            published + time::Duration::new(ROUTER_EXPIRY_SECONDS, 0),
775            identity_cert.expiry(),
776            crosscert_cert.expiry(),
777        ];
778
779        for cert in family_certs {
780            let (inner, sig) = cert.dangerously_split().map_err(into_internal!(
781                "Missing a public key that was previously there."
782            ))?;
783            signatures.push(Box::new(sig));
784            expirations.push(inner.dangerously_assume_timely().expiry());
785        }
786
787        // Unwrap is safe here because `expirations` array is not empty
788        #[allow(clippy::unwrap_used)]
789        let expiry = *expirations.iter().min().unwrap();
790
791        let start_time = published - time::Duration::new(ROUTER_PRE_VALIDITY_SECONDS, 0);
792
793        let desc = RouterDesc {
794            nickname,
795            ipv4addr,
796            orport,
797            ipv6addr,
798            dirport,
799            uptime,
800            published,
801            identity_cert,
802            rsa_identity_key,
803            rsa_identity,
804            ntor_onion_key,
805            tap_onion_key,
806            proto,
807            is_dircache,
808            is_extrainfo_cache,
809            family,
810            family_ids,
811            platform,
812            ipv4_policy,
813            ipv6_policy: ipv6_policy.intern(),
814        };
815
816        let time_gated = timed::TimerangeBound::new(desc, start_time..expiry);
817        let sig_gated = signed::SignatureGated::new(time_gated, signatures);
818
819        Ok(sig_gated)
820    }
821}
822
823/// An iterator that parses one or more (possibly annotated
824/// router descriptors from a string.
825//
826// TODO: This is largely copy-pasted from MicrodescReader. Can/should they
827// be merged?
828pub struct RouterReader<'a> {
829    /// True iff we accept annotations
830    annotated: bool,
831    /// Reader that we're extracting items from.
832    reader: NetDocReader<'a, RouterKwd>,
833}
834
835/// Skip this reader forward until the next thing it reads looks like the
836/// start of a router descriptor.
837///
838/// Used to recover from errors.
839fn advance_to_next_routerdesc(reader: &mut NetDocReader<'_, RouterKwd>, annotated: bool) {
840    use RouterKwd::*;
841    loop {
842        let item = reader.peek();
843        match item {
844            Some(Ok(t)) => {
845                let kwd = t.kwd();
846                if (annotated && kwd.is_annotation()) || kwd == ROUTER {
847                    return;
848                }
849            }
850            Some(Err(_)) => {
851                // Skip over broken tokens.
852            }
853            None => {
854                return;
855            }
856        }
857        let _ = reader.next();
858    }
859}
860
861impl<'a> RouterReader<'a> {
862    /// Construct a RouterReader to take router descriptors from a string.
863    pub fn new(s: &'a str, allow: &AllowAnnotations) -> Result<Self> {
864        let reader = NetDocReader::new(s)?;
865        let annotated = allow == &AllowAnnotations::AnnotationsAllowed;
866        Ok(RouterReader { annotated, reader })
867    }
868
869    /// Extract an annotation from this reader.
870    fn take_annotation(&mut self) -> Result<RouterAnnotation> {
871        if self.annotated {
872            RouterAnnotation::take_from_reader(&mut self.reader)
873        } else {
874            Ok(RouterAnnotation::default())
875        }
876    }
877
878    /// Extract an annotated router descriptor from this reader
879    ///
880    /// (internal helper; does not clean up on failures.)
881    fn take_annotated_routerdesc_raw(&mut self) -> Result<AnnotatedRouterDesc> {
882        let ann = self.take_annotation()?;
883        let router = RouterDesc::parse_internal(&mut self.reader)?;
884        Ok(AnnotatedRouterDesc { ann, router })
885    }
886
887    /// Extract an annotated router descriptor from this reader
888    ///
889    /// Ensure that at least one token is consumed
890    fn take_annotated_routerdesc(&mut self) -> Result<AnnotatedRouterDesc> {
891        let pos_orig = self.reader.pos();
892        let result = self.take_annotated_routerdesc_raw();
893        if result.is_err() {
894            if self.reader.pos() == pos_orig {
895                // No tokens were consumed from the reader.  We need
896                // to drop at least one token to ensure we aren't in
897                // an infinite loop.
898                //
899                // (This might not be able to happen, but it's easier to
900                // explicitly catch this case than it is to prove that
901                // it's impossible.)
902                let _ = self.reader.next();
903            }
904            advance_to_next_routerdesc(&mut self.reader, self.annotated);
905        }
906        result
907    }
908}
909
910impl<'a> Iterator for RouterReader<'a> {
911    type Item = Result<AnnotatedRouterDesc>;
912    fn next(&mut self) -> Option<Self::Item> {
913        // Is there a next token? If not, we're done.
914        self.reader.peek()?;
915
916        Some(
917            self.take_annotated_routerdesc()
918                .map_err(|e| e.within(self.reader.str())),
919        )
920    }
921}
922
923#[cfg(test)]
924mod test {
925    // @@ begin test lint list maintained by maint/add_warning @@
926    #![allow(clippy::bool_assert_comparison)]
927    #![allow(clippy::clone_on_copy)]
928    #![allow(clippy::dbg_macro)]
929    #![allow(clippy::mixed_attributes_style)]
930    #![allow(clippy::print_stderr)]
931    #![allow(clippy::print_stdout)]
932    #![allow(clippy::single_char_pattern)]
933    #![allow(clippy::unwrap_used)]
934    #![allow(clippy::unchecked_time_subtraction)]
935    #![allow(clippy::useless_vec)]
936    #![allow(clippy::needless_pass_by_value)]
937    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
938    use super::*;
939    const TESTDATA: &str = include_str!("../../testdata/routerdesc1.txt");
940    const TESTDATA2: &str = include_str!("../../testdata/routerdesc2.txt");
941    // Generated with a patched C tor to include "happy family" IDs.
942    const TESTDATA3: &str = include_str!("../../testdata/routerdesc3.txt");
943
944    fn read_bad(fname: &str) -> String {
945        use std::fs;
946        use std::path::PathBuf;
947        let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
948        path.push("testdata");
949        path.push("bad-routerdesc");
950        path.push(fname);
951
952        fs::read_to_string(path).unwrap()
953    }
954
955    #[test]
956    fn parse_arbitrary() -> Result<()> {
957        use std::str::FromStr;
958        use tor_checkable::{SelfSigned, Timebound};
959        let rd = RouterDesc::parse(TESTDATA)?
960            .check_signature()?
961            .dangerously_assume_timely();
962
963        assert_eq!(rd.nickname.as_str(), "Akka");
964        assert_eq!(rd.orport, 443);
965        assert_eq!(rd.dirport, 0);
966        assert_eq!(rd.uptime, Some(1036923));
967        assert_eq!(
968            rd.family.as_ref(),
969            &RelayFamily::from_str(
970                "$303509ab910ef207b7438c27435c4a2fd579f1b1 \
971                 $56927e61b51e6f363fb55498150a6ddfcf7077f2"
972            )
973            .unwrap()
974        );
975
976        assert_eq!(
977            rd.rsa_identity().to_string(),
978            "$56927e61b51e6f363fb55498150a6ddfcf7077f2"
979        );
980        assert_eq!(
981            rd.ed_identity().to_string(),
982            "CVTjf1oeaL616hH+1+UvYZ8OgkwF3z7UMITvJzm5r7A"
983        );
984        assert_eq!(
985            rd.protocols().to_string(),
986            "Cons=1-2 Desc=1-2 DirCache=2 FlowCtrl=1-2 HSDir=2 \
987             HSIntro=4-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 \
988             Padding=2 Relay=1-4"
989        );
990
991        assert_eq!(
992            hex::encode(rd.ntor_onion_key().to_bytes()),
993            "329b3b52991613392e35d1a821dd6753e1210458ecc3337f7b7d39bfcf5da273"
994        );
995        assert_eq!(
996            rd.published(),
997            humantime::parse_rfc3339("2022-11-14T19:58:52Z").unwrap()
998        );
999        assert_eq!(
1000            rd.or_ports().collect::<Vec<_>>(),
1001            vec![
1002                "95.216.33.58:443".parse().unwrap(),
1003                "[2a01:4f9:2a:2145::2]:443".parse().unwrap(),
1004            ]
1005        );
1006        assert!(rd.tap_onion_key.is_some());
1007
1008        Ok(())
1009    }
1010
1011    #[test]
1012    fn parse_no_tap_key() -> Result<()> {
1013        use tor_checkable::{SelfSigned, Timebound};
1014        let rd = RouterDesc::parse(TESTDATA2)?
1015            .check_signature()?
1016            .dangerously_assume_timely();
1017        assert!(rd.tap_onion_key.is_none());
1018
1019        Ok(())
1020    }
1021
1022    #[test]
1023    fn test_bad() {
1024        use crate::Pos;
1025        use crate::types::policy::PolicyError;
1026        fn check(fname: &str, e: &Error) {
1027            let text = read_bad(fname);
1028            let rd = RouterDesc::parse(&text);
1029            assert!(rd.is_err());
1030            assert_eq!(&rd.err().unwrap(), e);
1031        }
1032
1033        check(
1034            "bad-sig-order",
1035            &EK::UnexpectedToken
1036                .with_msg("router-sig-ed25519")
1037                .at_pos(Pos::from_line(50, 1)),
1038        );
1039        check(
1040            "bad-start1",
1041            &EK::MisplacedToken
1042                .with_msg("identity-ed25519")
1043                .at_pos(Pos::from_line(1, 1)),
1044        );
1045        check("bad-start2", &EK::MissingToken.with_msg("identity-ed25519"));
1046        check(
1047            "mismatched-fp",
1048            &EK::BadArgument
1049                .at_pos(Pos::from_line(12, 1))
1050                .with_msg("fingerprint does not match RSA identity"),
1051        );
1052        check("no-ed-sk", &EK::MissingToken.with_msg("identity-ed25519"));
1053
1054        check(
1055            "bad-cc-sign",
1056            &EK::BadArgument
1057                .at_pos(Pos::from_line(34, 26))
1058                .with_msg("not 0 or 1"),
1059        );
1060        check(
1061            "bad-ipv6policy",
1062            &EK::BadPolicy
1063                .at_pos(Pos::from_line(43, 1))
1064                .with_source(PolicyError::InvalidPolicy),
1065        );
1066        check(
1067            "no-ed-id-key-in-cert",
1068            &EK::BadObjectVal
1069                .at_pos(Pos::from_line(2, 1))
1070                .with_source(tor_cert::CertError::MissingPubKey),
1071        );
1072        check(
1073            "non-ed-sk-in-cert",
1074            &EK::BadObjectVal
1075                .at_pos(Pos::from_line(2, 1))
1076                .with_msg("wrong type for signing key in cert"),
1077        );
1078        check(
1079            "bad-ed-sk-in-cert",
1080            &EK::BadObjectVal
1081                .at_pos(Pos::from_line(2, 1))
1082                .with_msg("invalid ed25519 signing key"),
1083        );
1084        check(
1085            "mismatched-ed-sk-in-cert",
1086            &EK::BadObjectVal
1087                .at_pos(Pos::from_line(8, 1))
1088                .with_msg("master-key-ed25519 does not match key in identity-ed25519"),
1089        );
1090    }
1091
1092    #[test]
1093    fn parse_multiple_annotated() {
1094        use crate::AllowAnnotations;
1095        let mut s = read_bad("bad-cc-sign");
1096        s += "\
1097@uploaded-at 2020-09-26 18:15:41
1098@source \"127.0.0.1\"
1099";
1100        s += TESTDATA;
1101        s += "\
1102@uploaded-at 2020-09-26 18:15:41
1103@source \"127.0.0.1\"
1104";
1105        s += &read_bad("mismatched-fp");
1106
1107        let rd = RouterReader::new(&s, &AllowAnnotations::AnnotationsAllowed).unwrap();
1108        let v: Vec<_> = rd.collect();
1109        assert!(v[0].is_err());
1110        assert!(v[1].is_ok());
1111        assert_eq!(
1112            v[1].as_ref().unwrap().ann.source,
1113            Some("\"127.0.0.1\"".to_string())
1114        );
1115        assert!(v[2].is_err());
1116    }
1117
1118    #[test]
1119    fn test_platform() {
1120        let p = "Tor 0.4.4.4-alpha on a flying bison".parse::<RelayPlatform>();
1121        assert!(p.is_ok());
1122        assert_eq!(
1123            p.unwrap(),
1124            RelayPlatform::Tor(
1125                "0.4.4.4-alpha".parse().unwrap(),
1126                "a flying bison".to_string()
1127            )
1128        );
1129
1130        let p = "Tor 0.4.4.4-alpha on".parse::<RelayPlatform>();
1131        assert!(p.is_ok());
1132
1133        let p = "Tor 0.4.4.4-alpha ".parse::<RelayPlatform>();
1134        assert!(p.is_ok());
1135        let p = "Tor 0.4.4.4-alpha".parse::<RelayPlatform>();
1136        assert!(p.is_ok());
1137
1138        let p = "arti 0.0.0".parse::<RelayPlatform>();
1139        assert!(p.is_ok());
1140        assert_eq!(p.unwrap(), RelayPlatform::Other("arti 0.0.0".to_string()));
1141    }
1142
1143    #[test]
1144    fn test_family_ids() -> Result<()> {
1145        use tor_checkable::{SelfSigned, Timebound};
1146        let rd = RouterDesc::parse(TESTDATA3)?
1147            .check_signature()?
1148            .dangerously_assume_timely();
1149
1150        assert_eq!(
1151            rd.family_ids(),
1152            &[
1153                "ed25519:7sToQRuge1bU2hS0CG0ViMndc4m82JhO4B4kdrQey80"
1154                    .parse()
1155                    .unwrap(),
1156                "ed25519:szHUS3ItRd9uk85b1UVnOZx1gg4B0266jCpbuIMNjcM"
1157                    .parse()
1158                    .unwrap(),
1159            ]
1160        );
1161
1162        Ok(())
1163    }
1164}