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.
35
use crate::parse::keyword::Keyword;
36
use crate::parse::parser::{Section, SectionRules};
37
use crate::parse::tokenize::{ItemResult, NetDocReader};
38
use crate::types::family::{RelayFamily, RelayFamilyId};
39
use crate::types::misc::*;
40
use crate::types::policy::*;
41
use crate::types::version::TorVersion;
42
use crate::util::PeekableIterator;
43
use crate::{doc, AllowAnnotations, Error, NetdocErrorKind as EK, Result};
44

            
45
use ll::pk::ed25519::Ed25519Identity;
46
use once_cell::sync::Lazy;
47
use std::sync::Arc;
48
use std::{net, time};
49
use tor_cert::CertType;
50
use tor_checkable::{signed, timed, Timebound};
51
use tor_error::{internal, into_internal};
52
use tor_llcrypto as ll;
53
use tor_llcrypto::pk::rsa::RsaIdentity;
54

            
55
use digest::Digest;
56

            
57
/// The digest of a RouterDesc document, as reported in a NS consensus.
58
pub type RdDigest = [u8; 20];
59

            
60
/// A router descriptor, with possible annotations.
61
#[allow(dead_code)]
62
#[cfg_attr(
63
    feature = "dangerous-expose-struct-fields",
64
    visible::StructFields(pub),
65
    non_exhaustive
66
)]
67
pub struct AnnotatedRouterDesc {
68
    /// Annotation for this router descriptor; possibly empty.
69
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
70
    ann: RouterAnnotation,
71
    /// Underlying router descriptor; signatures not checked yet.
72
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
73
    router: UncheckedRouterDesc,
74
}
75

            
76
/// Annotations about a router descriptor, as stored on disc.
77
#[allow(dead_code)] // don't warn about fields not getting read.
78
#[cfg_attr(
79
    feature = "dangerous-expose-struct-fields",
80
    visible::StructFields(pub),
81
    non_exhaustive
82
)]
83
#[derive(Default)]
84
pub struct RouterAnnotation {
85
    /// Description of where we got this router descriptor
86
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
87
    source: Option<String>,
88
    /// When this descriptor was first downloaded.
89
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
90
    downloaded: Option<time::SystemTime>,
91
    /// Description of what we're willing to use this descriptor for.
92
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
93
    purpose: Option<String>,
94
}
95

            
96
/// Information about a relay, parsed from a router descriptor.
97
///
98
/// This type does not hold all the information in the router descriptor
99
///
100
/// # Limitations
101
///
102
/// See module documentation.
103
///
104
/// Additionally, some fields that from router descriptors are not yet
105
/// parsed: see the comments in ROUTER_BODY_RULES for information about those.
106
///
107
/// Before using this type to connect to a relay, you MUST check that
108
/// it is valid, using is_expired_at().
109
#[allow(dead_code)] // don't warn about fields not getting read.
110
#[cfg_attr(
111
    feature = "dangerous-expose-struct-fields",
112
    visible::StructFields(pub),
113
    non_exhaustive
114
)]
115
#[derive(Clone, Debug)]
116
pub struct RouterDesc {
117
    /// Human-readable nickname for this relay.
118
    ///
119
    /// This is not secure, and not guaranteed to be unique.
120
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
121
    nickname: Nickname,
122
    /// IPv4 address for this relay.
123
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
124
    ipv4addr: Option<net::Ipv4Addr>,
125
    /// IPv4 ORPort for this relay.
126
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
127
    orport: u16,
128
    /// IPv6 address and port for this relay.
129
    // TODO: we don't use a socketaddrv6 because we don't care about
130
    // the flow and scope fields.  We should decide whether that's a
131
    // good idea.
132
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
133
    ipv6addr: Option<(net::Ipv6Addr, u16)>,
134
    /// Directory port for contacting this relay for direct HTTP
135
    /// directory downloads.
136
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
137
    dirport: u16,
138
    /// Declared uptime for this relay, in seconds.
139
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
140
    uptime: Option<u64>,
141
    /// Time when this router descriptor was published.
142
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
143
    published: time::SystemTime,
144
    /// Ed25519 identity certificate (identity key authenticating a
145
    /// signing key)
146
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
147
    identity_cert: tor_cert::Ed25519Cert,
148
    /// RSA identity key for this relay. (Deprecated; never use this without
149
    /// the ed25519 identity as well).
150
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
151
    rsa_identity_key: ll::pk::rsa::PublicKey,
152
    /// RSA identity key for this relay. (Deprecated; never use this without
153
    /// the ed25519 identity as well).
154
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
155
    rsa_identity: ll::pk::rsa::RsaIdentity,
156
    /// Key for extending a circuit to this relay using the ntor protocol.
157
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
158
    ntor_onion_key: ll::pk::curve25519::PublicKey,
159
    /// Key for extending a circuit to this relay using the
160
    /// (deprecated) TAP protocol.
161
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
162
    tap_onion_key: Option<ll::pk::rsa::PublicKey>,
163
    /// List of subprotocol versions supported by this relay.
164
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
165
    proto: Arc<tor_protover::Protocols>,
166
    /// True if this relay says it's a directory cache.
167
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
168
    is_dircache: bool,
169
    /// True if this relay says that it caches extrainfo documents.
170
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
171
    is_extrainfo_cache: bool,
172
    /// Declared family members for this relay.  If two relays are in the
173
    /// same family, they shouldn't be used in the same circuit.
174
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
175
    family: Arc<RelayFamily>,
176
    /// Declared (and proven) family IDs for this relay. If two relays
177
    /// share a family ID, they shouldn't be used in the same circuit.
178
    family_ids: Vec<RelayFamilyId>,
179
    /// Software and version that this relay says it's running.
180
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
181
    platform: Option<RelayPlatform>,
182
    /// A complete address-level policy for which IPv4 addresses this relay
183
    /// says it supports.
184
    // TODO: these polices can get bulky too. Perhaps we should
185
    // de-duplicate them too.
186
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
187
    ipv4_policy: AddrPolicy,
188
    /// A summary of which ports this relay is willing to connect to
189
    /// on IPv6.
190
    #[cfg_attr(docsrs, doc(cfg(feature = "dangerous-expose-struct-fields")))]
191
    ipv6_policy: Arc<PortPolicy>,
192
}
193

            
194
/// Description of the software a relay is running.
195
#[derive(Debug, Clone, PartialEq, Eq)]
196
#[non_exhaustive]
197
pub enum RelayPlatform {
198
    /// Software advertised to be some version of Tor, on some platform.
199
    Tor(TorVersion, String),
200
    /// Software not advertised to be Tor.
201
    Other(String),
202
}
203

            
204
impl std::str::FromStr for RelayPlatform {
205
    type Err = Error;
206
1994
    fn from_str(args: &str) -> Result<Self> {
207
1994
        if args.starts_with("Tor ") {
208
1992
            let v: Vec<_> = args.splitn(4, ' ').collect();
209
1992
            match &v[..] {
210
1986
                ["Tor", ver, "on", p] => Ok(RelayPlatform::Tor(ver.parse()?, (*p).to_string())),
211
6
                ["Tor", ver, ..] => Ok(RelayPlatform::Tor(ver.parse()?, "".to_string())),
212
                _ => unreachable!(),
213
            }
214
        } else {
215
2
            Ok(RelayPlatform::Other(args.to_string()))
216
        }
217
1994
    }
218
}
219

            
220
decl_keyword! {
221
    /// RouterKwd is an instance of Keyword, used to denote the different
222
    /// Items that are recognized as appearing in a router descriptor.
223
    RouterKwd {
224
        annotation "@source" => ANN_SOURCE,
225
        annotation "@downloaded-at" => ANN_DOWNLOADED_AT,
226
        annotation "@purpose" => ANN_PURPOSE,
227
        "accept" | "reject" => POLICY,
228
        "bandwidth" => BANDWIDTH,
229
        "bridge-distribution-request" => BRIDGE_DISTRIBUTION_REQUEST,
230
        "caches-extra-info" => CACHES_EXTRA_INFO,
231
        "contact" => CONTACT,
232
        "extra-info-digest" => EXTRA_INFO_DIGEST,
233
        "family" => FAMILY,
234
        "family-cert" => FAMILY_CERT,
235
        "fingerprint" => FINGERPRINT,
236
        "hibernating" => HIBERNATING,
237
        "identity-ed25519" => IDENTITY_ED25519,
238
        "ipv6-policy" => IPV6_POLICY,
239
        "master-key-ed25519" => MASTER_KEY_ED25519,
240
        "ntor-onion-key" => NTOR_ONION_KEY,
241
        "ntor-onion-key-crosscert" => NTOR_ONION_KEY_CROSSCERT,
242
        "onion-key" => ONION_KEY,
243
        "onion-key-crosscert" => ONION_KEY_CROSSCERT,
244
        "or-address" => OR_ADDRESS,
245
        "platform" => PLATFORM,
246
        "proto" => PROTO,
247
        "published" => PUBLISHED,
248
        "router" => ROUTER,
249
        "router-sig-ed25519" => ROUTER_SIG_ED25519,
250
        "router-signature" => ROUTER_SIGNATURE,
251
        "signing-key" => SIGNING_KEY,
252
        "tunnelled_dir_server" => TUNNELLED_DIR_SERVER,
253
        "uptime" => UPTIME,
254
        // "protocols" once existed, but is obsolete
255
        // "eventdns" once existed, but is obsolete
256
        // "allow-single-hop-exits" is also obsolete.
257
    }
258
}
259

            
260
/// Rules for parsing a set of router descriptor annotations.
261
2
static ROUTER_ANNOTATIONS: Lazy<SectionRules<RouterKwd>> = Lazy::new(|| {
262
    use RouterKwd::*;
263

            
264
2
    let mut rules = SectionRules::builder();
265
2
    rules.add(ANN_SOURCE.rule());
266
2
    rules.add(ANN_DOWNLOADED_AT.rule().args(1..));
267
2
    rules.add(ANN_PURPOSE.rule().args(1..));
268
2
    rules.add(ANN_UNRECOGNIZED.rule().may_repeat().obj_optional());
269
2
    // Unrecognized annotations are fine; anything else is an error in this
270
2
    // context.
271
2
    rules.reject_unrecognized();
272
2
    rules.build()
273
2
});
274
/// Rules for tokens that are allowed in the first part of a
275
/// router descriptor.
276
49
static ROUTER_HEADER_RULES: Lazy<SectionRules<RouterKwd>> = Lazy::new(|| {
277
    use RouterKwd::*;
278

            
279
49
    let mut rules = SectionRules::builder();
280
49
    rules.add(ROUTER.rule().required().args(5..));
281
49
    rules.add(IDENTITY_ED25519.rule().required().no_args().obj_required());
282
49
    // No other intervening tokens are permitted in the header.
283
49
    rules.reject_unrecognized();
284
49
    rules.build()
285
49
});
286
/// Rules for  tokens that are allowed in the first part of a
287
/// router descriptor.
288
49
static ROUTER_BODY_RULES: Lazy<SectionRules<RouterKwd>> = Lazy::new(|| {
289
    use RouterKwd::*;
290

            
291
49
    let mut rules = SectionRules::builder();
292
49
    rules.add(MASTER_KEY_ED25519.rule().required().args(1..));
293
49
    rules.add(PLATFORM.rule());
294
49
    rules.add(PUBLISHED.rule().required());
295
49
    rules.add(FINGERPRINT.rule());
296
49
    rules.add(UPTIME.rule().args(1..));
297
49
    rules.add(ONION_KEY.rule().no_args().obj_required());
298
49
    rules.add(ONION_KEY_CROSSCERT.rule().no_args().obj_required());
299
49
    rules.add(NTOR_ONION_KEY.rule().required().args(1..));
300
49
    rules.add(
301
49
        NTOR_ONION_KEY_CROSSCERT
302
49
            .rule()
303
49
            .required()
304
49
            .args(1..=1)
305
49
            .obj_required(),
306
49
    );
307
49
    rules.add(SIGNING_KEY.rule().no_args().required().obj_required());
308
49
    rules.add(POLICY.rule().may_repeat().args(1..));
309
49
    rules.add(IPV6_POLICY.rule().args(2..));
310
49
    rules.add(FAMILY.rule().args(1..));
311
49
    rules.add(FAMILY_CERT.rule().obj_required().may_repeat());
312
49
    rules.add(CACHES_EXTRA_INFO.rule().no_args());
313
49
    rules.add(OR_ADDRESS.rule().may_repeat().args(1..));
314
49
    rules.add(TUNNELLED_DIR_SERVER.rule());
315
49
    rules.add(PROTO.rule().required().args(1..));
316
49
    rules.add(UNRECOGNIZED.rule().may_repeat().obj_optional());
317
49
    // TODO: these aren't parsed yet.  Only authorities use them.
318
49
    {
319
49
        rules.add(BANDWIDTH.rule().required().args(3..));
320
49
        rules.add(BRIDGE_DISTRIBUTION_REQUEST.rule().args(1..));
321
49
        rules.add(HIBERNATING.rule().args(1..));
322
49
        rules.add(CONTACT.rule());
323
49
    }
324
49
    // TODO: this is ignored for now.
325
49
    {
326
49
        rules.add(EXTRA_INFO_DIGEST.rule().args(1..));
327
49
    }
328
49
    rules.build()
329
49
});
330

            
331
/// Rules for items that appear at the end of a router descriptor.
332
49
static ROUTER_SIG_RULES: Lazy<SectionRules<RouterKwd>> = Lazy::new(|| {
333
    use RouterKwd::*;
334

            
335
49
    let mut rules = SectionRules::builder();
336
49
    rules.add(ROUTER_SIG_ED25519.rule().required().args(1..));
337
49
    rules.add(ROUTER_SIGNATURE.rule().required().no_args().obj_required());
338
49
    // No intervening tokens are allowed in the footer.
339
49
    rules.reject_unrecognized();
340
49
    rules.build()
341
49
});
342

            
343
impl RouterAnnotation {
344
    /// Extract a single RouterAnnotation (possibly empty) from a reader.
345
8
    fn take_from_reader(reader: &mut NetDocReader<'_, RouterKwd>) -> Result<RouterAnnotation> {
346
        use RouterKwd::*;
347
20
        let mut items = reader.pause_at(|item| item.is_ok_with_non_annotation());
348

            
349
8
        let body = ROUTER_ANNOTATIONS.parse(&mut items)?;
350

            
351
6
        let source = body.maybe(ANN_SOURCE).args_as_str().map(String::from);
352
6
        let purpose = body.maybe(ANN_PURPOSE).args_as_str().map(String::from);
353
6
        let downloaded = body
354
6
            .maybe(ANN_DOWNLOADED_AT)
355
6
            .parse_args_as_str::<Iso8601TimeSp>()?
356
6
            .map(|t| t.into());
357
6
        Ok(RouterAnnotation {
358
6
            source,
359
6
            downloaded,
360
6
            purpose,
361
6
        })
362
8
    }
363
}
364

            
365
/// A parsed router descriptor whose signatures and/or validity times
366
/// may or may not be invalid.
367
pub type UncheckedRouterDesc = signed::SignatureGated<timed::TimerangeBound<RouterDesc>>;
368

            
369
/// How long after its published time is a router descriptor officially
370
/// supposed to be usable?
371
const ROUTER_EXPIRY_SECONDS: u64 = 5 * 86400;
372

            
373
/// How long before its published time is a router descriptor usable?
374
// TODO(nickm): This valid doesn't match C tor, which only enforces this rule
375
// ("routers should not some from the future") at directory authorities, and
376
// there only enforces a 12-hour limit (`ROUTER_ALLOW_SKEW`).  Eventually we
377
// should probably harmonize these cutoffs.
378
const ROUTER_PRE_VALIDITY_SECONDS: u64 = 86400;
379

            
380
impl RouterDesc {
381
    /// Return a reference to this relay's RSA identity.
382
2
    pub fn rsa_identity(&self) -> &RsaIdentity {
383
2
        &self.rsa_identity
384
2
    }
385

            
386
    /// Return a reference to this relay's Ed25519 identity.
387
2
    pub fn ed_identity(&self) -> &Ed25519Identity {
388
2
        self.identity_cert
389
2
            .signing_key()
390
2
            .expect("No ed25519 identity key on identity cert")
391
2
    }
392

            
393
    /// Return a reference to the list of subprotocol versions supported by this
394
    /// relay.
395
2
    pub fn protocols(&self) -> &tor_protover::Protocols {
396
2
        self.proto.as_ref()
397
2
    }
398

            
399
    /// Return a reference to this relay's Ntor onion key.
400
2
    pub fn ntor_onion_key(&self) -> &ll::pk::curve25519::PublicKey {
401
2
        &self.ntor_onion_key
402
2
    }
403

            
404
    /// Return the publication
405
284
    pub fn published(&self) -> time::SystemTime {
406
284
        self.published
407
284
    }
408

            
409
    /// Return an iterator of every `SocketAddr` at which this descriptor says
410
    /// its relay can be reached.
411
2
    pub fn or_ports(&self) -> impl Iterator<Item = net::SocketAddr> + '_ {
412
2
        self.ipv4addr
413
3
            .map(|a| net::SocketAddr::new(a.into(), self.orport))
414
2
            .into_iter()
415
2
            .chain(self.ipv6addr.map(net::SocketAddr::from))
416
2
    }
417

            
418
    /// Return the declared family of this descriptor.
419
    pub fn family(&self) -> Arc<RelayFamily> {
420
        Arc::clone(&self.family)
421
    }
422

            
423
    /// Return the authenticated family IDs of this descriptor.
424
2
    pub fn family_ids(&self) -> &[RelayFamilyId] {
425
2
        &self.family_ids[..]
426
2
    }
427

            
428
    /// Helper: tokenize `s`, and divide it into three validated sections.
429
2102
    fn parse_sections<'a>(
430
2102
        reader: &mut NetDocReader<'a, RouterKwd>,
431
2102
    ) -> Result<(
432
2102
        Section<'a, RouterKwd>,
433
2102
        Section<'a, RouterKwd>,
434
2102
        Section<'a, RouterKwd>,
435
2102
    )> {
436
        use RouterKwd::*;
437

            
438
        // Parse everything up through the header.
439
2102
        let header = ROUTER_HEADER_RULES.parse(
440
6173
            reader.pause_at(|item| item.is_ok_with_kwd_not_in(&[ROUTER, IDENTITY_ED25519])),
441
2102
        )?;
442

            
443
        // Parse everything up to but not including the signature.
444
2004
        let body =
445
34169
            ROUTER_BODY_RULES.parse(reader.pause_at(|item| {
446
34112
                item.is_ok_with_kwd_in(&[ROUTER_SIGNATURE, ROUTER_SIG_ED25519])
447
34169
            }))?;
448

            
449
        // Parse the signature.
450
4079
        let sig = ROUTER_SIG_RULES.parse(reader.pause_at(|item| {
451
4022
            item.is_ok_with_annotation() || item.is_ok_with_kwd(ROUTER) || item.is_empty_line()
452
4079
        }))?;
453

            
454
2004
        Ok((header, body, sig))
455
2102
    }
456

            
457
    /// Try to parse `s` as a router descriptor.
458
    ///
459
    /// Does not actually check liveness or signatures; you need to do that
460
    /// yourself before you can do the output.
461
2096
    pub fn parse(s: &str) -> Result<UncheckedRouterDesc> {
462
2096
        let mut reader = crate::parse::tokenize::NetDocReader::new(s)?;
463
2109
        let result = Self::parse_internal(&mut reader).map_err(|e| e.within(s))?;
464
        // We permit empty lines at the end of router descriptors, since there's
465
        // a known issue in Tor relays that causes them to return them this way.
466
1980
        reader
467
1980
            .should_be_exhausted_but_for_empty_lines()
468
1980
            .map_err(|e| e.within(s))?;
469
1980
        Ok(result)
470
2096
    }
471

            
472
    /// Helper: parse a router descriptor from `s`.
473
    ///
474
    /// This function does the same as parse(), but returns errors based on
475
    /// byte-wise positions.  The parse() function converts such errors
476
    /// into line-and-byte positions.
477
2102
    fn parse_internal(r: &mut NetDocReader<'_, RouterKwd>) -> Result<UncheckedRouterDesc> {
478
        // TODO: This function is too long!  The little "paragraphs" here
479
        // that parse one item at a time should be made into sub-functions.
480
        use RouterKwd::*;
481

            
482
2102
        let s = r.str();
483
2102
        let (header, body, sig) = RouterDesc::parse_sections(r)?;
484

            
485
        // Unwrap should be safe because inline `required` call should return
486
        // `Error::MissingToken` if `ROUTER` is not `Ok`
487
        #[allow(clippy::unwrap_used)]
488
2004
        let start_offset = header.required(ROUTER)?.offset_in(s).unwrap();
489

            
490
        // ed25519 identity and signing key.
491
1996
        let (identity_cert, ed25519_signing_key) = {
492
2004
            let cert_tok = header.required(IDENTITY_ED25519)?;
493
            // Unwrap should be safe because above `required` call should
494
            // return `Error::MissingToken` if `IDENTITY_ED25519` is not `Ok`
495
            #[allow(clippy::unwrap_used)]
496
2004
            if cert_tok.offset_in(s).unwrap() < start_offset {
497
2
                return Err(EK::MisplacedToken
498
2
                    .with_msg("identity-ed25519")
499
2
                    .at_pos(cert_tok.pos()));
500
2002
            }
501
2002
            let cert: tor_cert::UncheckedCert = cert_tok
502
2002
                .parse_obj::<UnvalidatedEdCert>("ED25519 CERT")?
503
2002
                .check_cert_type(tor_cert::CertType::IDENTITY_V_SIGNING)?
504
2002
                .into_unchecked()
505
2002
                .should_have_signing_key()
506
2003
                .map_err(|err| {
507
2
                    EK::BadObjectVal
508
2
                        .err()
509
2
                        .with_source(err)
510
2
                        .at_pos(cert_tok.pos())
511
2003
                })?;
512
2001
            let sk = *cert.peek_subject_key().as_ed25519().ok_or_else(|| {
513
2
                EK::BadObjectVal
514
2
                    .at_pos(cert_tok.pos())
515
2
                    .with_msg("wrong type for signing key in cert")
516
2001
            })?;
517
1999
            let sk: ll::pk::ed25519::PublicKey = sk.try_into().map_err(|_| {
518
2
                EK::BadObjectVal
519
2
                    .at_pos(cert_tok.pos())
520
2
                    .with_msg("invalid ed25519 signing key")
521
1999
            })?;
522
1996
            (cert, sk)
523
        };
524

            
525
        // master-key-ed25519: required, and should match certificate.
526
        #[allow(unexpected_cfgs)]
527
        {
528
1996
            let master_key_tok = body.required(MASTER_KEY_ED25519)?;
529
1996
            let ed_id: Ed25519Public = master_key_tok.parse_arg(0)?;
530
1996
            let ed_id: ll::pk::ed25519::Ed25519Identity = ed_id.into();
531
1996
            if ed_id != *identity_cert.peek_signing_key() {
532
                #[cfg(not(fuzzing))] // No feature here; never omit in production.
533
2
                return Err(EK::BadObjectVal
534
2
                    .at_pos(master_key_tok.pos())
535
2
                    .with_msg("master-key-ed25519 does not match key in identity-ed25519"));
536
1994
            }
537
        }
538

            
539
        // Legacy RSA identity
540
1994
        let rsa_identity_key: ll::pk::rsa::PublicKey = body
541
1994
            .required(SIGNING_KEY)?
542
1994
            .parse_obj::<RsaPublic>("RSA PUBLIC KEY")?
543
1994
            .check_len_eq(1024)?
544
1994
            .check_exponent(65537)?
545
1994
            .into();
546
1994
        let rsa_identity = rsa_identity_key.to_rsa_identity();
547

            
548
1994
        let ed_sig = sig.required(ROUTER_SIG_ED25519)?;
549
1994
        let rsa_sig = sig.required(ROUTER_SIGNATURE)?;
550
        // Unwrap should be safe because above `required` calls should return
551
        // an `Error::MissingToken` if `ROUTER_...` is not `Ok`
552
        #[allow(clippy::unwrap_used)]
553
1994
        let ed_sig_pos = ed_sig.offset_in(s).unwrap();
554
1994
        #[allow(clippy::unwrap_used)]
555
1994
        let rsa_sig_pos = rsa_sig.offset_in(s).unwrap();
556
1994

            
557
1994
        if ed_sig_pos > rsa_sig_pos {
558
2
            return Err(EK::UnexpectedToken
559
2
                .with_msg(ROUTER_SIG_ED25519.to_str())
560
2
                .at_pos(ed_sig.pos()));
561
1992
        }
562

            
563
        // Extract ed25519 signature.
564
1992
        let ed_signature: ll::pk::ed25519::ValidatableEd25519Signature = {
565
1992
            let mut d = ll::d::Sha256::new();
566
1992
            d.update(&b"Tor router descriptor signature v1"[..]);
567
1992
            let signed_end = ed_sig_pos + b"router-sig-ed25519 ".len();
568
1992
            d.update(&s[start_offset..signed_end]);
569
1992
            let d = d.finalize();
570
1992
            let sig: [u8; 64] = ed_sig
571
1992
                .parse_arg::<B64>(0)?
572
1992
                .into_array()
573
1992
                .map_err(|_| EK::BadSignature.at_pos(ed_sig.pos()))?;
574
1992
            let sig = ll::pk::ed25519::Signature::from(sig);
575
1992
            ll::pk::ed25519::ValidatableEd25519Signature::new(ed25519_signing_key, sig, &d)
576
        };
577

            
578
        // Extract legacy RSA signature.
579
1992
        let rsa_signature: ll::pk::rsa::ValidatableRsaSignature = {
580
1992
            let mut d = ll::d::Sha1::new();
581
1992
            let signed_end = rsa_sig_pos + b"router-signature\n".len();
582
1992
            d.update(&s[start_offset..signed_end]);
583
1992
            let d = d.finalize();
584
1992
            let sig = rsa_sig.obj("SIGNATURE")?;
585
            // TODO: we need to accept prefixes here. COMPAT BLOCKER.
586

            
587
1992
            ll::pk::rsa::ValidatableRsaSignature::new(&rsa_identity_key, &sig, &d)
588
        };
589

            
590
        // router nickname ipv4addr orport socksport dirport
591
1992
        let (nickname, ipv4addr, orport, dirport) = {
592
1992
            let rtrline = header.required(ROUTER)?;
593
            (
594
1992
                rtrline.parse_arg::<Nickname>(0)?,
595
1992
                Some(rtrline.parse_arg::<net::Ipv4Addr>(1)?),
596
1992
                rtrline.parse_arg(2)?,
597
                // Skipping socksport.
598
1992
                rtrline.parse_arg(4)?,
599
            )
600
        };
601

            
602
        // uptime
603
1992
        let uptime = body.maybe(UPTIME).parse_arg(0)?;
604

            
605
        // published time.
606
1992
        let published = body
607
1992
            .required(PUBLISHED)?
608
1992
            .args_as_str()
609
1992
            .parse::<Iso8601TimeSp>()?
610
1992
            .into();
611

            
612
        // ntor key
613
1992
        let ntor_onion_key: Curve25519Public = body.required(NTOR_ONION_KEY)?.parse_arg(0)?;
614
1992
        let ntor_onion_key: ll::pk::curve25519::PublicKey = ntor_onion_key.into();
615
        // ntor crosscert
616
1988
        let crosscert_cert: tor_cert::UncheckedCert = {
617
1992
            let cc = body.required(NTOR_ONION_KEY_CROSSCERT)?;
618
1992
            let sign: u8 = cc.parse_arg(0)?;
619
1992
            if sign != 0 && sign != 1 {
620
4
                return Err(EK::BadArgument.at_pos(cc.arg_pos(0)).with_msg("not 0 or 1"));
621
1988
            }
622
1988
            let ntor_as_ed: ll::pk::ed25519::PublicKey =
623
1988
                ll::pk::keymanip::convert_curve25519_to_ed25519_public(&ntor_onion_key, sign)
624
1988
                    .ok_or_else(|| {
625
                        EK::BadArgument
626
                            .at_pos(cc.pos())
627
                            .with_msg("Uncheckable crosscert")
628
1988
                    })?;
629

            
630
1988
            cc.parse_obj::<UnvalidatedEdCert>("ED25519 CERT")?
631
1988
                .check_cert_type(tor_cert::CertType::NTOR_CC_IDENTITY)?
632
1988
                .check_subject_key_is(identity_cert.peek_signing_key())?
633
1988
                .into_unchecked()
634
1988
                .should_be_signed_with(&ntor_as_ed.into())
635
1988
                .map_err(|err| EK::BadSignature.err().with_source(err))?
636
        };
637

            
638
        // TAP key
639
1988
        let tap_onion_key: Option<ll::pk::rsa::PublicKey> = if let Some(tok) = body.get(ONION_KEY) {
640
            Some(
641
1986
                tok.parse_obj::<RsaPublic>("RSA PUBLIC KEY")?
642
1986
                    .check_len_eq(1024)?
643
1986
                    .check_exponent(65537)?
644
1986
                    .into(),
645
            )
646
        } else {
647
2
            None
648
        };
649

            
650
        // TAP crosscert
651
1988
        let tap_crosscert_sig = if let Some(cc_tok) = body.get(ONION_KEY_CROSSCERT) {
652
1986
            let cc_val = cc_tok.obj("CROSSCERT")?;
653
1986
            let mut signed = Vec::new();
654
1986
            signed.extend(rsa_identity.as_bytes());
655
1986
            signed.extend(identity_cert.peek_signing_key().as_bytes());
656
1986
            Some(ll::pk::rsa::ValidatableRsaSignature::new(
657
1986
                tap_onion_key.as_ref().ok_or_else(|| {
658
                    EK::MissingToken.with_msg("onion-key-crosscert without onion-key")
659
1986
                })?,
660
1986
                &cc_val,
661
1986
                &signed,
662
            ))
663
2
        } else if tap_onion_key.is_some() {
664
            return Err(EK::MissingToken.with_msg("onion-key without onion-key-crosscert"));
665
        } else {
666
2
            None
667
        };
668

            
669
        // List of subprotocol versions
670
1988
        let proto = {
671
1988
            let proto_tok = body.required(PROTO)?;
672
1988
            doc::PROTOVERS_CACHE.intern(
673
1988
                proto_tok
674
1988
                    .args_as_str()
675
1988
                    .parse::<tor_protover::Protocols>()
676
1988
                    .map_err(|e| EK::BadArgument.at_pos(proto_tok.pos()).with_source(e))?,
677
            )
678
        };
679

            
680
        // tunneled-dir-server
681
1988
        let is_dircache = (dirport != 0) || body.get(TUNNELLED_DIR_SERVER).is_some();
682

            
683
        // caches-extra-info
684
1988
        let is_extrainfo_cache = body.get(CACHES_EXTRA_INFO).is_some();
685

            
686
        // fingerprint: check for consistency with RSA identity.
687
1988
        if let Some(fp_tok) = body.get(FINGERPRINT) {
688
1988
            let fp: RsaIdentity = fp_tok.args_as_str().parse::<SpFingerprint>()?.into();
689
1988
            if fp != rsa_identity {
690
4
                return Err(EK::BadArgument
691
4
                    .at_pos(fp_tok.pos())
692
4
                    .with_msg("fingerprint does not match RSA identity"));
693
1984
            }
694
        }
695

            
696
        // Family
697
1984
        let family = {
698
1984
            let mut family = body
699
1984
                .maybe(FAMILY)
700
1984
                .parse_args_as_str::<RelayFamily>()?
701
1984
                .unwrap_or_else(RelayFamily::new);
702
1984
            if !family.is_empty() {
703
4
                // If this family is nonempty, we add our own RSA id to it, on
704
4
                // the theory that doing so will improve the odds of having a
705
4
                // canonical family shared by all of the members of this family.
706
4
                // If the family is empty, there's no point in adding our own ID
707
4
                // to it, and doing so would only waste memory.
708
4
                family.push(rsa_identity);
709
1980
            }
710
1984
            family.intern()
711
        };
712

            
713
        // Family ids (for "happy families")
714
1984
        let family_certs: Vec<tor_cert::UncheckedCert> = body
715
1984
            .slice(FAMILY_CERT)
716
1984
            .iter()
717
1986
            .map(|ent| {
718
4
                ent.parse_obj::<UnvalidatedEdCert>("FAMILY CERT")?
719
4
                    .check_cert_type(CertType::FAMILY_V_IDENTITY)?
720
4
                    .check_subject_key_is(identity_cert.peek_signing_key())?
721
4
                    .into_unchecked()
722
4
                    .should_have_signing_key()
723
4
                    .map_err(|e| {
724
                        EK::BadObjectVal
725
                            .with_msg("missing public key")
726
                            .at_pos(ent.pos())
727
                            .with_source(e)
728
4
                    })
729
1986
            })
730
1984
            .collect::<Result<_>>()?;
731

            
732
1984
        let mut family_ids: Vec<_> = family_certs
733
1984
            .iter()
734
1986
            .map(|cert| RelayFamilyId::Ed25519(*cert.peek_signing_key()))
735
1984
            .collect();
736
1984
        family_ids.sort();
737
1984
        family_ids.dedup();
738
1984

            
739
1984
        // or-address
740
1984
        // Extract at most one ipv6 address from the list.  It's not great,
741
1984
        // but it's what Tor does.
742
1984
        let mut ipv6addr = None;
743
1984
        for tok in body.slice(OR_ADDRESS) {
744
6
            if let Ok(net::SocketAddr::V6(a)) = tok.parse_arg::<net::SocketAddr>(0) {
745
6
                ipv6addr = Some((*a.ip(), a.port()));
746
6
                break;
747
            }
748
            // We skip over unparsable addresses. Is that right?
749
        }
750

            
751
        // platform
752
1984
        let platform = body.maybe(PLATFORM).parse_args_as_str::<RelayPlatform>()?;
753

            
754
        // ipv4_policy
755
1984
        let ipv4_policy = {
756
1984
            let mut pol = AddrPolicy::new();
757
1986
            for ruletok in body.slice(POLICY).iter() {
758
1986
                let accept = match ruletok.kwd_str() {
759
1986
                    "accept" => RuleKind::Accept,
760
1984
                    "reject" => RuleKind::Reject,
761
                    _ => {
762
                        return Err(Error::from(internal!(
763
                            "tried to parse a strange line as a policy"
764
                        ))
765
                        .at_pos(ruletok.pos()))
766
                    }
767
                };
768
1986
                let pat: AddrPortPattern = ruletok
769
1986
                    .args_as_str()
770
1986
                    .parse()
771
1986
                    .map_err(|e| EK::BadPolicy.at_pos(ruletok.pos()).with_source(e))?;
772
1986
                pol.push(accept, pat);
773
            }
774
1984
            pol
775
        };
776

            
777
        // ipv6 policy
778
1984
        let ipv6_policy = match body.get(IPV6_POLICY) {
779
2
            Some(p) => p
780
2
                .args_as_str()
781
2
                .parse()
782
3
                .map_err(|e| EK::BadPolicy.at_pos(p.pos()).with_source(e))?,
783
            // Unwrap is safe here because str is not empty
784
            #[allow(clippy::unwrap_used)]
785
1982
            None => "reject 1-65535".parse::<PortPolicy>().unwrap(),
786
        };
787

            
788
        // Now we're going to collect signatures and expiration times.
789
1982
        let (identity_cert, identity_sig) = identity_cert.dangerously_split().map_err(|err| {
790
            EK::BadObjectVal
791
                .with_msg("missing public key")
792
                .with_source(err)
793
1982
        })?;
794
1982
        let (crosscert_cert, cc_sig) = crosscert_cert.dangerously_split().map_err(|err| {
795
            EK::BadObjectVal
796
                .with_msg("missing public key")
797
                .with_source(err)
798
1982
        })?;
799
1982
        let mut signatures: Vec<Box<dyn ll::pk::ValidatableSignature>> = vec![
800
1982
            Box::new(rsa_signature),
801
1982
            Box::new(ed_signature),
802
1982
            Box::new(identity_sig),
803
1982
            Box::new(cc_sig),
804
1982
        ];
805
1982
        if let Some(s) = tap_crosscert_sig {
806
1980
            signatures.push(Box::new(s));
807
1980
        }
808

            
809
1982
        let identity_cert = identity_cert.dangerously_assume_timely();
810
1982
        let crosscert_cert = crosscert_cert.dangerously_assume_timely();
811
1982
        let mut expirations = vec![
812
1982
            published + time::Duration::new(ROUTER_EXPIRY_SECONDS, 0),
813
1982
            identity_cert.expiry(),
814
1982
            crosscert_cert.expiry(),
815
1982
        ];
816

            
817
1986
        for cert in family_certs {
818
4
            let (inner, sig) = cert.dangerously_split().map_err(into_internal!(
819
4
                "Missing a public key that was previously there."
820
4
            ))?;
821
4
            signatures.push(Box::new(sig));
822
4
            expirations.push(inner.dangerously_assume_timely().expiry());
823
        }
824

            
825
        // Unwrap is safe here because `expirations` array is not empty
826
        #[allow(clippy::unwrap_used)]
827
1982
        let expiry = *expirations.iter().min().unwrap();
828
1982

            
829
1982
        let start_time = published - time::Duration::new(ROUTER_PRE_VALIDITY_SECONDS, 0);
830
1982

            
831
1982
        let desc = RouterDesc {
832
1982
            nickname,
833
1982
            ipv4addr,
834
1982
            orport,
835
1982
            ipv6addr,
836
1982
            dirport,
837
1982
            uptime,
838
1982
            published,
839
1982
            identity_cert,
840
1982
            rsa_identity_key,
841
1982
            rsa_identity,
842
1982
            ntor_onion_key,
843
1982
            tap_onion_key,
844
1982
            proto,
845
1982
            is_dircache,
846
1982
            is_extrainfo_cache,
847
1982
            family,
848
1982
            family_ids,
849
1982
            platform,
850
1982
            ipv4_policy,
851
1982
            ipv6_policy: ipv6_policy.intern(),
852
1982
        };
853
1982

            
854
1982
        let time_gated = timed::TimerangeBound::new(desc, start_time..expiry);
855
1982
        let sig_gated = signed::SignatureGated::new(time_gated, signatures);
856
1982

            
857
1982
        Ok(sig_gated)
858
2102
    }
859
}
860

            
861
/// An iterator that parses one or more (possibly annotated
862
/// router descriptors from a string.
863
//
864
// TODO: This is largely copy-pasted from MicrodescReader. Can/should they
865
// be merged?
866
pub struct RouterReader<'a> {
867
    /// True iff we accept annotations
868
    annotated: bool,
869
    /// Reader that we're extracting items from.
870
    reader: NetDocReader<'a, RouterKwd>,
871
}
872

            
873
/// Skip this reader forward until the next thing it reads looks like the
874
/// start of a router descriptor.
875
///
876
/// Used to recover from errors.
877
6
fn advance_to_next_routerdesc(reader: &mut NetDocReader<'_, RouterKwd>, annotated: bool) {
878
    use RouterKwd::*;
879
    loop {
880
6
        let item = reader.peek();
881
4
        match item {
882
4
            Some(Ok(t)) => {
883
4
                let kwd = t.kwd();
884
4
                if (annotated && kwd.is_annotation()) || kwd == ROUTER {
885
4
                    return;
886
                }
887
            }
888
            Some(Err(_)) => {
889
                // Skip over broken tokens.
890
            }
891
            None => {
892
2
                return;
893
            }
894
        }
895
        let _ = reader.next();
896
    }
897
6
}
898

            
899
impl<'a> RouterReader<'a> {
900
    /// Construct a RouterReader to take router descriptors from a string.
901
2
    pub fn new(s: &'a str, allow: &AllowAnnotations) -> Result<Self> {
902
2
        let reader = NetDocReader::new(s)?;
903
2
        let annotated = allow == &AllowAnnotations::AnnotationsAllowed;
904
2
        Ok(RouterReader { annotated, reader })
905
2
    }
906

            
907
    /// Extract an annotation from this reader.
908
8
    fn take_annotation(&mut self) -> Result<RouterAnnotation> {
909
8
        if self.annotated {
910
8
            RouterAnnotation::take_from_reader(&mut self.reader)
911
        } else {
912
            Ok(RouterAnnotation::default())
913
        }
914
8
    }
915

            
916
    /// Extract an annotated router descriptor from this reader
917
    ///
918
    /// (internal helper; does not clean up on failures.)
919
8
    fn take_annotated_routerdesc_raw(&mut self) -> Result<AnnotatedRouterDesc> {
920
8
        let ann = self.take_annotation()?;
921
6
        let router = RouterDesc::parse_internal(&mut self.reader)?;
922
2
        Ok(AnnotatedRouterDesc { ann, router })
923
8
    }
924

            
925
    /// Extract an annotated router descriptor from this reader
926
    ///
927
    /// Ensure that at least one token is consumed
928
8
    fn take_annotated_routerdesc(&mut self) -> Result<AnnotatedRouterDesc> {
929
8
        let pos_orig = self.reader.pos();
930
8
        let result = self.take_annotated_routerdesc_raw();
931
8
        if result.is_err() {
932
6
            if self.reader.pos() == pos_orig {
933
                // No tokens were consumed from the reader.  We need
934
                // to drop at least one token to ensure we aren't in
935
                // an infinite loop.
936
                //
937
                // (This might not be able to happen, but it's easier to
938
                // explicitly catch this case than it is to prove that
939
                // it's impossible.)
940
                let _ = self.reader.next();
941
6
            }
942
6
            advance_to_next_routerdesc(&mut self.reader, self.annotated);
943
2
        }
944
8
        result
945
8
    }
946
}
947

            
948
impl<'a> Iterator for RouterReader<'a> {
949
    type Item = Result<AnnotatedRouterDesc>;
950
10
    fn next(&mut self) -> Option<Self::Item> {
951
10
        // Is there a next token? If not, we're done.
952
10
        self.reader.peek()?;
953

            
954
8
        Some(
955
8
            self.take_annotated_routerdesc()
956
11
                .map_err(|e| e.within(self.reader.str())),
957
8
        )
958
10
    }
959
}
960

            
961
#[cfg(test)]
962
mod test {
963
    // @@ begin test lint list maintained by maint/add_warning @@
964
    #![allow(clippy::bool_assert_comparison)]
965
    #![allow(clippy::clone_on_copy)]
966
    #![allow(clippy::dbg_macro)]
967
    #![allow(clippy::mixed_attributes_style)]
968
    #![allow(clippy::print_stderr)]
969
    #![allow(clippy::print_stdout)]
970
    #![allow(clippy::single_char_pattern)]
971
    #![allow(clippy::unwrap_used)]
972
    #![allow(clippy::unchecked_duration_subtraction)]
973
    #![allow(clippy::useless_vec)]
974
    #![allow(clippy::needless_pass_by_value)]
975
    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
976
    use super::*;
977
    const TESTDATA: &str = include_str!("../../testdata/routerdesc1.txt");
978
    const TESTDATA2: &str = include_str!("../../testdata/routerdesc2.txt");
979
    // Generated with a patched C tor to include "happy family" IDs.
980
    const TESTDATA3: &str = include_str!("../../testdata/routerdesc3.txt");
981

            
982
    fn read_bad(fname: &str) -> String {
983
        use std::fs;
984
        use std::path::PathBuf;
985
        let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
986
        path.push("testdata");
987
        path.push("bad-routerdesc");
988
        path.push(fname);
989

            
990
        fs::read_to_string(path).unwrap()
991
    }
992

            
993
    #[test]
994
    fn parse_arbitrary() -> Result<()> {
995
        use std::str::FromStr;
996
        use tor_checkable::{SelfSigned, Timebound};
997
        let rd = RouterDesc::parse(TESTDATA)?
998
            .check_signature()?
999
            .dangerously_assume_timely();
        assert_eq!(rd.nickname.as_str(), "Akka");
        assert_eq!(rd.orport, 443);
        assert_eq!(rd.dirport, 0);
        assert_eq!(rd.uptime, Some(1036923));
        assert_eq!(
            rd.family.as_ref(),
            &RelayFamily::from_str(
                "$303509ab910ef207b7438c27435c4a2fd579f1b1 \
                 $56927e61b51e6f363fb55498150a6ddfcf7077f2"
            )
            .unwrap()
        );
        assert_eq!(
            rd.rsa_identity().to_string(),
            "$56927e61b51e6f363fb55498150a6ddfcf7077f2"
        );
        assert_eq!(
            rd.ed_identity().to_string(),
            "CVTjf1oeaL616hH+1+UvYZ8OgkwF3z7UMITvJzm5r7A"
        );
        assert_eq!(
            rd.protocols().to_string(),
            "Cons=1-2 Desc=1-2 DirCache=2 FlowCtrl=1-2 HSDir=2 \
             HSIntro=4-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 \
             Padding=2 Relay=1-4"
        );
        assert_eq!(
            hex::encode(rd.ntor_onion_key().to_bytes()),
            "329b3b52991613392e35d1a821dd6753e1210458ecc3337f7b7d39bfcf5da273"
        );
        assert_eq!(
            rd.published(),
            humantime::parse_rfc3339("2022-11-14T19:58:52Z").unwrap()
        );
        assert_eq!(
            rd.or_ports().collect::<Vec<_>>(),
            vec![
                "95.216.33.58:443".parse().unwrap(),
                "[2a01:4f9:2a:2145::2]:443".parse().unwrap(),
            ]
        );
        assert!(rd.tap_onion_key.is_some());
        Ok(())
    }
    #[test]
    fn parse_no_tap_key() -> Result<()> {
        use tor_checkable::{SelfSigned, Timebound};
        let rd = RouterDesc::parse(TESTDATA2)?
            .check_signature()?
            .dangerously_assume_timely();
        assert!(rd.tap_onion_key.is_none());
        Ok(())
    }
    #[test]
    fn test_bad() {
        use crate::types::policy::PolicyError;
        use crate::Pos;
        fn check(fname: &str, e: &Error) {
            let text = read_bad(fname);
            let rd = RouterDesc::parse(&text);
            assert!(rd.is_err());
            assert_eq!(&rd.err().unwrap(), e);
        }
        check(
            "bad-sig-order",
            &EK::UnexpectedToken
                .with_msg("router-sig-ed25519")
                .at_pos(Pos::from_line(50, 1)),
        );
        check(
            "bad-start1",
            &EK::MisplacedToken
                .with_msg("identity-ed25519")
                .at_pos(Pos::from_line(1, 1)),
        );
        check("bad-start2", &EK::MissingToken.with_msg("identity-ed25519"));
        check(
            "mismatched-fp",
            &EK::BadArgument
                .at_pos(Pos::from_line(12, 1))
                .with_msg("fingerprint does not match RSA identity"),
        );
        check("no-ed-sk", &EK::MissingToken.with_msg("identity-ed25519"));
        check(
            "bad-cc-sign",
            &EK::BadArgument
                .at_pos(Pos::from_line(34, 26))
                .with_msg("not 0 or 1"),
        );
        check(
            "bad-ipv6policy",
            &EK::BadPolicy
                .at_pos(Pos::from_line(43, 1))
                .with_source(PolicyError::InvalidPolicy),
        );
        check(
            "no-ed-id-key-in-cert",
            &EK::BadObjectVal
                .at_pos(Pos::from_line(2, 1))
                .with_source(tor_cert::CertError::MissingPubKey),
        );
        check(
            "non-ed-sk-in-cert",
            &EK::BadObjectVal
                .at_pos(Pos::from_line(2, 1))
                .with_msg("wrong type for signing key in cert"),
        );
        check(
            "bad-ed-sk-in-cert",
            &EK::BadObjectVal
                .at_pos(Pos::from_line(2, 1))
                .with_msg("invalid ed25519 signing key"),
        );
        check(
            "mismatched-ed-sk-in-cert",
            &EK::BadObjectVal
                .at_pos(Pos::from_line(8, 1))
                .with_msg("master-key-ed25519 does not match key in identity-ed25519"),
        );
    }
    #[test]
    fn parse_multiple_annotated() {
        use crate::AllowAnnotations;
        let mut s = read_bad("bad-cc-sign");
        s += "\
@uploaded-at 2020-09-26 18:15:41
@source \"127.0.0.1\"
";
        s += TESTDATA;
        s += "\
@uploaded-at 2020-09-26 18:15:41
@source \"127.0.0.1\"
";
        s += &read_bad("mismatched-fp");
        let rd = RouterReader::new(&s, &AllowAnnotations::AnnotationsAllowed).unwrap();
        let v: Vec<_> = rd.collect();
        assert!(v[0].is_err());
        assert!(v[1].is_ok());
        assert_eq!(
            v[1].as_ref().unwrap().ann.source,
            Some("\"127.0.0.1\"".to_string())
        );
        assert!(v[2].is_err());
    }
    #[test]
    fn test_platform() {
        let p = "Tor 0.4.4.4-alpha on a flying bison".parse::<RelayPlatform>();
        assert!(p.is_ok());
        assert_eq!(
            p.unwrap(),
            RelayPlatform::Tor(
                "0.4.4.4-alpha".parse().unwrap(),
                "a flying bison".to_string()
            )
        );
        let p = "Tor 0.4.4.4-alpha on".parse::<RelayPlatform>();
        assert!(p.is_ok());
        let p = "Tor 0.4.4.4-alpha ".parse::<RelayPlatform>();
        assert!(p.is_ok());
        let p = "Tor 0.4.4.4-alpha".parse::<RelayPlatform>();
        assert!(p.is_ok());
        let p = "arti 0.0.0".parse::<RelayPlatform>();
        assert!(p.is_ok());
        assert_eq!(p.unwrap(), RelayPlatform::Other("arti 0.0.0".to_string()));
    }
    #[test]
    fn test_family_ids() -> Result<()> {
        use tor_checkable::{SelfSigned, Timebound};
        let rd = RouterDesc::parse(TESTDATA3)?
            .check_signature()?
            .dangerously_assume_timely();
        assert_eq!(
            rd.family_ids(),
            &[
                "ed25519:7sToQRuge1bU2hS0CG0ViMndc4m82JhO4B4kdrQey80"
                    .parse()
                    .unwrap(),
                "ed25519:szHUS3ItRd9uk85b1UVnOZx1gg4B0266jCpbuIMNjcM"
                    .parse()
                    .unwrap(),
            ]
        );
        Ok(())
    }
}