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;
39
use crate::types::misc::*;
40
use crate::types::policy::*;
41
use crate::types::version::TorVersion;
42
use crate::{AllowAnnotations, Error, ParseErrorKind as EK, Result};
43

            
44
use once_cell::sync::Lazy;
45
use std::sync::Arc;
46
use std::{net, time};
47
use tor_checkable::{signed, timed, Timebound};
48
use tor_error::internal;
49
use tor_llcrypto as ll;
50
use tor_llcrypto::pk::rsa::RsaIdentity;
51

            
52
use digest::Digest;
53
#[allow(unused_imports)] // This 'use' is needed with ed25519 < 1.3.0
54
use signature::Signature;
55

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

            
59
/// A router descriptor, with possible annotations.
60
#[allow(dead_code)]
61
pub struct AnnotatedRouterDesc {
62
    /// Annotation for this router descriptor; possibly empty.
63
    ann: RouterAnnotation,
64
    /// Underlying router descriptor; signatures not checked yet.
65
    router: UncheckedRouterDesc,
66
}
67

            
68
/// Annotations about a router descriptor, as stored on disc.
69
#[allow(dead_code)] // don't warn about fields not getting read.
70
#[derive(Default)]
71
pub struct RouterAnnotation {
72
    /// Description of where we got this router descriptor
73
    source: Option<String>,
74
    /// When this descriptor was first downloaded.
75
    downloaded: Option<time::SystemTime>,
76
    /// Description of what we're willing to use this descriptor for.
77
    purpose: Option<String>,
78
}
79

            
80
/// Information about a relay, parsed from a router descriptor.
81
///
82
/// This type does not hold all the information in the router descriptor
83
///
84
/// # Limitations
85
///
86
/// See module documentation.
87
///
88
/// Additionally, some fields that from router descriptors are not yet
89
/// parsed: see the comments in ROUTER_BODY_RULES for information about those.
90
///
91
/// Before using this type to connect to a relay, you MUST check that
92
/// it is valid, using is_expired_at().
93
#[allow(dead_code)] // don't warn about fields not getting read.
94
pub struct RouterDesc {
95
    /// Human-readable nickname for this relay.
96
    ///
97
    /// This is not secure, and not guaranteed to be unique.
98
    nickname: String,
99
    /// IPv4 address for this relay.
100
    ipv4addr: Option<net::Ipv4Addr>,
101
    /// IPv4 ORPort for this relay.
102
    orport: u16,
103
    /// IPv6 address and port for this relay.
104
    // TODO: we don't use a socketaddrv6 because we don't care about
105
    // the flow and scope fields.  We should decide whether that's a
106
    // good idea.
107
    ipv6addr: Option<(net::Ipv6Addr, u16)>,
108
    /// Directory port for contacting this relay for direct HTTP
109
    /// directory downloads.
110
    dirport: u16,
111
    /// Declared uptime for this relay, in seconds.
112
    uptime: Option<u64>,
113
    /// Time when this router descriptor was published.
114
    published: time::SystemTime,
115
    /// Ed25519 identity certificate (identity key authenticating a
116
    /// signing key)
117
    identity_cert: tor_cert::Ed25519Cert,
118
    /// RSA identity for this relay. (Deprecated; never use this without
119
    /// the ed25519 identity as well).
120
    rsa_identity: ll::pk::rsa::PublicKey,
121
    /// Key for extending a circuit to this relay using the ntor protocol.
122
    ntor_onion_key: ll::pk::curve25519::PublicKey,
123
    /// Key for extending a circuit to this relay using the
124
    /// (deprecated) TAP protocol.
125
    tap_onion_key: ll::pk::rsa::PublicKey,
126
    /// List of subprotocol versions supported by this relay.
127
    proto: tor_protover::Protocols,
128
    /// True if this relay says it's a directory cache.
129
    is_dircache: bool,
130
    /// True if this relay says that it caches extrainfo documents.
131
    is_extrainfo_cache: bool,
132
    /// Declared family members for this relay.  If two relays are in the
133
    /// same family, they shouldn't be used in the same circuit.
134
    // TODO: these families can get bulky. Perhaps we should de-duplicate
135
    // them in a cache, like Tor does.
136
    family: Option<RelayFamily>,
137
    /// Software and version that this relay says it's running.
138
    platform: Option<RelayPlatform>,
139
    /// A complete address-level policy for which IPv4 addresses this relay
140
    /// says it supports.
141
    // TODO: these polices can get bulky too. Perhaps we should
142
    // de-duplicate them too.
143
    ipv4_policy: AddrPolicy,
144
    /// A summary of which ports this relay is willing to connect to
145
    /// on IPv6.
146
    ipv6_policy: Arc<PortPolicy>,
147
}
148

            
149
/// Description of the software a relay is running.
150
2
#[derive(Debug, Clone, PartialEq)]
151
#[non_exhaustive]
152
pub enum RelayPlatform {
153
    /// Software advertised to be some version of Tor, on some platform.
154
    Tor(TorVersion, String),
155
    /// Software not advertised to be Tor.
156
    Other(String),
157
}
158

            
159
impl std::str::FromStr for RelayPlatform {
160
    type Err = Error;
161
8
    fn from_str(args: &str) -> Result<Self> {
162
8
        if args.starts_with("Tor ") {
163
7
            let v: Vec<_> = args.splitn(4, ' ').collect();
164
7
            match &v[..] {
165
4
                ["Tor", ver, "on", p] => Ok(RelayPlatform::Tor(ver.parse()?, (*p).to_string())),
166
3
                ["Tor", ver, ..] => Ok(RelayPlatform::Tor(ver.parse()?, "".to_string())),
167
                _ => unreachable!(),
168
            }
169
        } else {
170
1
            Ok(RelayPlatform::Other(args.to_string()))
171
        }
172
8
    }
173
}
174

            
175
decl_keyword! {
176
    /// RouterKwd is an instance of Keyword, used to denote the different
177
    /// Items that are recognized as appearing in a router descriptor.
178
    RouterKwd {
179
        annotation "@source" => ANN_SOURCE,
180
        annotation "@downloaded-at" => ANN_DOWNLOADED_AT,
181
        annotation "@purpose" => ANN_PURPOSE,
182
        "accept" | "reject" => POLICY,
183
        "bandwidth" => BANDWIDTH,
184
        "bridge-distribution-request" => BRIDGE_DISTRIBUTION_REQUEST,
185
        "caches-extra-info" => CACHES_EXTRA_INFO,
186
        "contact" => CONTACT,
187
        "extra-info-digest" => EXTRA_INFO_DIGEST,
188
        "family" => FAMILY,
189
        "fingerprint" => FINGERPRINT,
190
        "hibernating" => HIBERNATING,
191
        "identity-ed25519" => IDENTITY_ED25519,
192
        "ipv6-policy" => IPV6_POLICY,
193
        "master-key-ed25519" => MASTER_KEY_ED25519,
194
        "ntor-onion-key" => NTOR_ONION_KEY,
195
        "ntor-onion-key-crosscert" => NTOR_ONION_KEY_CROSSCERT,
196
        "onion-key" => ONION_KEY,
197
        "onion-key-crosscert" => ONION_KEY_CROSSCERT,
198
        "or-address" => OR_ADDRESS,
199
        "platform" => PLATFORM,
200
        "proto" => PROTO,
201
        "published" => PUBLISHED,
202
        "router" => ROUTER,
203
        "router-sig-ed25519" => ROUTER_SIG_ED25519,
204
        "router-signature" => ROUTER_SIGNATURE,
205
        "signing-key" => SIGNING_KEY,
206
        "tunnelled_dir_server" => TUNNELLED_DIR_SERVER,
207
        "uptime" => UPTIME,
208
        // "protocols" once existed, but is obsolete
209
        // "eventdns" once existed, but is obsolete
210
        // "allow-single-hop-exits" is also obsolete.
211
    }
212
}
213

            
214
/// Rules for parsing a set of router descriptor annotations.
215
1
static ROUTER_ANNOTATIONS: Lazy<SectionRules<RouterKwd>> = Lazy::new(|| {
216
1
    use RouterKwd::*;
217
1

            
218
1
    let mut rules = SectionRules::new();
219
1
    rules.add(ANN_SOURCE.rule());
220
1
    rules.add(ANN_DOWNLOADED_AT.rule().args(1..));
221
1
    rules.add(ANN_PURPOSE.rule().args(1..));
222
1
    rules.add(ANN_UNRECOGNIZED.rule().may_repeat().obj_optional());
223
1
    rules
224
1
});
225
/// Rules for tokens that are allowed in the first part of a
226
/// router descriptor.
227
1
static ROUTER_HEADER_RULES: Lazy<SectionRules<RouterKwd>> = Lazy::new(|| {
228
1
    use RouterKwd::*;
229
1

            
230
1
    let mut rules = SectionRules::new();
231
1
    rules.add(ROUTER.rule().required().args(5..));
232
1
    rules.add(IDENTITY_ED25519.rule().required().no_args().obj_required());
233
1
    rules
234
1
});
235
/// Rules for  tokens that are allowed in the first part of a
236
/// router descriptor.
237
1
static ROUTER_BODY_RULES: Lazy<SectionRules<RouterKwd>> = Lazy::new(|| {
238
1
    use RouterKwd::*;
239
1

            
240
1
    let mut rules = SectionRules::new();
241
1
    rules.add(MASTER_KEY_ED25519.rule().required().args(1..));
242
1
    rules.add(PLATFORM.rule());
243
1
    rules.add(PUBLISHED.rule().required());
244
1
    rules.add(FINGERPRINT.rule());
245
1
    rules.add(UPTIME.rule().args(1..));
246
1
    rules.add(ONION_KEY.rule().no_args().required().obj_required());
247
1
    rules.add(
248
1
        ONION_KEY_CROSSCERT
249
1
            .rule()
250
1
            .required()
251
1
            .no_args()
252
1
            .obj_required(),
253
1
    );
254
1
    rules.add(NTOR_ONION_KEY.rule().required().args(1..));
255
1
    rules.add(
256
1
        NTOR_ONION_KEY_CROSSCERT
257
1
            .rule()
258
1
            .required()
259
1
            .args(1..=1)
260
1
            .obj_required(),
261
1
    );
262
1
    rules.add(SIGNING_KEY.rule().no_args().required().obj_required());
263
1
    rules.add(POLICY.rule().may_repeat().args(1..));
264
1
    rules.add(IPV6_POLICY.rule().args(2..));
265
1
    rules.add(FAMILY.rule().args(1..));
266
1
    rules.add(CACHES_EXTRA_INFO.rule().no_args());
267
1
    rules.add(OR_ADDRESS.rule().may_repeat().args(1..));
268
1
    rules.add(TUNNELLED_DIR_SERVER.rule());
269
1
    rules.add(PROTO.rule().required().args(1..));
270
1
    rules.add(UNRECOGNIZED.rule().may_repeat().obj_optional());
271
1
    // TODO: these aren't parsed yet.  Only authorities use them.
272
1
    {
273
1
        rules.add(BANDWIDTH.rule().required().args(3..));
274
1
        rules.add(BRIDGE_DISTRIBUTION_REQUEST.rule().args(1..));
275
1
        rules.add(HIBERNATING.rule().args(1..));
276
1
        rules.add(CONTACT.rule());
277
1
    }
278
1
    // TODO: this is ignored for now.
279
1
    {
280
1
        rules.add(EXTRA_INFO_DIGEST.rule().args(1..));
281
1
    }
282
1
    rules
283
1
});
284

            
285
/// Rules for items that appear at the end of a router descriptor.
286
1
static ROUTER_SIG_RULES: Lazy<SectionRules<RouterKwd>> = Lazy::new(|| {
287
1
    use RouterKwd::*;
288
1

            
289
1
    let mut rules = SectionRules::new();
290
1
    rules.add(ROUTER_SIG_ED25519.rule().required().args(1..));
291
1
    rules.add(ROUTER_SIGNATURE.rule().required().no_args().obj_required());
292
1
    rules
293
1
});
294

            
295
impl RouterAnnotation {
296
    /// Extract a single RouterAnnotation (possibly empty) from a reader.
297
3
    fn take_from_reader(reader: &mut NetDocReader<'_, RouterKwd>) -> Result<RouterAnnotation> {
298
3
        use RouterKwd::*;
299
7
        let mut items = reader.pause_at(|item| item.is_ok_with_non_annotation());
300

            
301
3
        let body = ROUTER_ANNOTATIONS.parse(&mut items)?;
302

            
303
3
        let source = body.maybe(ANN_SOURCE).args_as_str().map(String::from);
304
3
        let purpose = body.maybe(ANN_PURPOSE).args_as_str().map(String::from);
305
3
        let downloaded = body
306
3
            .maybe(ANN_DOWNLOADED_AT)
307
3
            .parse_args_as_str::<Iso8601TimeSp>()?
308
3
            .map(|t| t.into());
309
3
        Ok(RouterAnnotation {
310
3
            source,
311
3
            downloaded,
312
3
            purpose,
313
3
        })
314
3
    }
315
}
316

            
317
/// A parsed router descriptor whose signatures and/or validity times
318
/// may or may not be invalid.
319
pub type UncheckedRouterDesc = signed::SignatureGated<timed::TimerangeBound<RouterDesc>>;
320

            
321
/// How long after its published time is a router descriptor officially
322
/// supposed to be usable?
323
const ROUTER_EXPIRY_SECONDS: u64 = 5 * 86400;
324

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

            
332
impl RouterDesc {
333
    /// Helper: tokenize `s`, and divide it into three validated sections.
334
11
    fn parse_sections<'a>(
335
11
        reader: &mut NetDocReader<'a, RouterKwd>,
336
11
    ) -> Result<(
337
11
        Section<'a, RouterKwd>,
338
11
        Section<'a, RouterKwd>,
339
11
        Section<'a, RouterKwd>,
340
11
    )> {
341
11
        use RouterKwd::*;
342
11

            
343
11
        // Parse everything up through the header.
344
11
        let mut reader =
345
30
            reader.pause_at(|item| item.is_ok_with_kwd_not_in(&[ROUTER, IDENTITY_ED25519]));
346
11
        let header = ROUTER_HEADER_RULES.parse(&mut reader)?;
347

            
348
        // Parse everything up to but not including the signature.
349
9
        let mut reader =
350
154
            reader.new_pred(|item| item.is_ok_with_kwd_in(&[ROUTER_SIGNATURE, ROUTER_SIG_ED25519]));
351
9
        let body = ROUTER_BODY_RULES.parse(&mut reader)?;
352

            
353
        // Parse the signature.
354
9
        let mut reader =
355
20
            reader.new_pred(|item| item.is_ok_with_annotation() || item.is_ok_with_kwd(ROUTER));
356
9
        let sig = ROUTER_SIG_RULES.parse(&mut reader)?;
357

            
358
9
        Ok((header, body, sig))
359
11
    }
360

            
361
    /// Try to parse `s` as a router descriptor.
362
    ///
363
    /// Does not actually check liveness or signatures; you need to do that
364
    /// yourself before you can do the output.
365
8
    pub fn parse(s: &str) -> Result<UncheckedRouterDesc> {
366
8
        let mut reader = crate::parse::tokenize::NetDocReader::new(s);
367
8
        let result = Self::parse_internal(&mut reader).map_err(|e| e.within(s))?;
368
1
        reader.should_be_exhausted().map_err(|e| e.within(s))?;
369
1
        Ok(result)
370
8
    }
371

            
372
    /// Helper: parse a router descriptor from `s`.
373
    ///
374
    /// This function does the same as parse(), but returns errors based on
375
    /// byte-wise positions.  The parse() function converts such errors
376
    /// into line-and-byte positions.
377
11
    fn parse_internal(r: &mut NetDocReader<'_, RouterKwd>) -> Result<UncheckedRouterDesc> {
378
11
        // TODO: This function is too long!  The little "paragraphs" here
379
11
        // that parse one item at a time should be made into sub-functions.
380
11
        use RouterKwd::*;
381
11

            
382
11
        let s = r.str();
383
11
        let (header, body, sig) = RouterDesc::parse_sections(r)?;
384

            
385
        // Unwrap should be safe because inline `required` call should return
386
        // `Error::MissingToken` if `ROUTER` is not `Ok`
387
        #[allow(clippy::unwrap_used)]
388
9
        let start_offset = header.required(ROUTER)?.offset_in(s).unwrap();
389

            
390
        // ed25519 identity and signing key.
391
8
        let (identity_cert, ed25519_signing_key) = {
392
9
            let cert_tok = header.required(IDENTITY_ED25519)?;
393
            // Unwrap should be safe because above `required` call should
394
            // return `Error::MissingToken` if `IDENTITY_ED25519` is not `Ok`
395
            #[allow(clippy::unwrap_used)]
396
9
            if cert_tok.offset_in(s).unwrap() < start_offset {
397
1
                return Err(EK::MisplacedToken
398
1
                    .with_msg("identity-ed25519")
399
1
                    .at_pos(cert_tok.pos()));
400
8
            }
401
8
            let cert: tor_cert::UncheckedCert = cert_tok
402
8
                .parse_obj::<UnvalidatedEdCert>("ED25519 CERT")?
403
8
                .check_cert_type(tor_cert::CertType::IDENTITY_V_SIGNING)?
404
8
                .into_unchecked()
405
8
                .check_key(&None)?;
406
8
            let sk = cert.peek_subject_key().as_ed25519().ok_or_else(|| {
407
                EK::BadObjectVal
408
                    .at_pos(cert_tok.pos())
409
                    .with_msg("no ed25519 signing key")
410
8
            })?;
411
8
            let sk = *sk;
412
8
            (cert, sk)
413
        };
414

            
415
        // master-key-ed25519: required, and should match certificate.
416
        {
417
8
            let master_key_tok = body.required(MASTER_KEY_ED25519)?;
418
8
            let ed_id: Ed25519Public = master_key_tok.parse_arg(0)?;
419
8
            let ed_id: ll::pk::ed25519::Ed25519Identity = ed_id.into();
420
8
            if ed_id != identity_cert.peek_signing_key().into() {
421
                #[cfg(not(fuzzing))]
422
                return Err(EK::BadObjectVal
423
                    .at_pos(master_key_tok.pos())
424
                    .with_msg("master-key-ed25519 does not match key in identity-ed25519"));
425
8
            }
426
        }
427

            
428
        // Legacy RSA identity
429
8
        let rsa_identity: ll::pk::rsa::PublicKey = body
430
8
            .required(SIGNING_KEY)?
431
8
            .parse_obj::<RsaPublic>("RSA PUBLIC KEY")?
432
8
            .check_len_eq(1024)?
433
8
            .check_exponent(65537)?
434
8
            .into();
435

            
436
8
        let ed_sig = sig.required(ROUTER_SIG_ED25519)?;
437
8
        let rsa_sig = sig.required(ROUTER_SIGNATURE)?;
438
        // Unwrap should be safe because above `required` calls should return
439
        // an `Error::MissingToken` if `ROUTER_...` is not `Ok`
440
        #[allow(clippy::unwrap_used)]
441
8
        let ed_sig_pos = ed_sig.offset_in(s).unwrap();
442
8
        #[allow(clippy::unwrap_used)]
443
8
        let rsa_sig_pos = rsa_sig.offset_in(s).unwrap();
444
8

            
445
8
        if ed_sig_pos > rsa_sig_pos {
446
1
            return Err(EK::UnexpectedToken
447
1
                .with_msg(ROUTER_SIG_ED25519.to_str())
448
1
                .at_pos(ed_sig.pos()));
449
7
        }
450

            
451
        // Extract ed25519 signature.
452
7
        let ed_signature: ll::pk::ed25519::ValidatableEd25519Signature = {
453
7
            let mut d = ll::d::Sha256::new();
454
7
            d.update(&b"Tor router descriptor signature v1"[..]);
455
7
            let signed_end = ed_sig_pos + b"router-sig-ed25519 ".len();
456
7
            d.update(&s[start_offset..signed_end]);
457
7
            let d = d.finalize();
458
7
            let sig: B64 = ed_sig.parse_arg(0)?;
459
7
            let sig = ll::pk::ed25519::Signature::from_bytes(sig.as_bytes())
460
7
                .map_err(|_| EK::BadSignature.at_pos(ed_sig.pos()))?;
461

            
462
7
            ll::pk::ed25519::ValidatableEd25519Signature::new(ed25519_signing_key, sig, &d)
463
        };
464

            
465
        // Extract legacy RSA signature.
466
7
        let rsa_signature: ll::pk::rsa::ValidatableRsaSignature = {
467
7
            let mut d = ll::d::Sha1::new();
468
7
            let signed_end = rsa_sig_pos + b"router-signature\n".len();
469
7
            d.update(&s[start_offset..signed_end]);
470
7
            let d = d.finalize();
471
7
            let sig = rsa_sig.obj("SIGNATURE")?;
472
            // TODO: we need to accept prefixes here. COMPAT BLOCKER.
473

            
474
7
            ll::pk::rsa::ValidatableRsaSignature::new(&rsa_identity, &sig, &d)
475
        };
476

            
477
        // router nickname ipv4addr orport socksport dirport
478
7
        let (nickname, ipv4addr, orport, dirport) = {
479
7
            let rtrline = header.required(ROUTER)?;
480
            (
481
                // Unwrap should be safe because above `required` should return
482
                // an `Error::MissingToken` if `ROUTER` is not `Ok`
483
                #[allow(clippy::unwrap_used)]
484
7
                rtrline.arg(0).unwrap().to_string(),
485
7
                Some(rtrline.parse_arg::<net::Ipv4Addr>(1)?),
486
7
                rtrline.parse_arg(2)?,
487
                // Skipping socksport.
488
7
                rtrline.parse_arg(4)?,
489
            )
490
        };
491

            
492
        // uptime
493
7
        let uptime = body.maybe(UPTIME).parse_arg(0)?;
494

            
495
        // published time.
496
7
        let published = body
497
7
            .required(PUBLISHED)?
498
7
            .args_as_str()
499
7
            .parse::<Iso8601TimeSp>()?
500
7
            .into();
501

            
502
        // ntor key
503
7
        let ntor_onion_key: Curve25519Public = body.required(NTOR_ONION_KEY)?.parse_arg(0)?;
504
7
        let ntor_onion_key: ll::pk::curve25519::PublicKey = ntor_onion_key.into();
505
        // ntor crosscert
506
5
        let crosscert_cert: tor_cert::UncheckedCert = {
507
7
            let cc = body.required(NTOR_ONION_KEY_CROSSCERT)?;
508
7
            let sign: u8 = cc.parse_arg(0)?;
509
7
            if sign != 0 && sign != 1 {
510
2
                return Err(EK::BadArgument.at_pos(cc.arg_pos(0)).with_msg("not 0 or 1"));
511
5
            }
512
5
            let ntor_as_ed =
513
5
                ll::pk::keymanip::convert_curve25519_to_ed25519_public(&ntor_onion_key, sign)
514
5
                    .ok_or_else(|| {
515
                        EK::BadArgument
516
                            .at_pos(cc.pos())
517
                            .with_msg("Uncheckable crosscert")
518
5
                    })?;
519

            
520
5
            cc.parse_obj::<UnvalidatedEdCert>("ED25519 CERT")?
521
5
                .check_cert_type(tor_cert::CertType::NTOR_CC_IDENTITY)?
522
5
                .check_subject_key_is(identity_cert.peek_signing_key())?
523
5
                .into_unchecked()
524
5
                .check_key(&Some(ntor_as_ed))?
525
        };
526

            
527
        // TAP key
528
5
        let tap_onion_key: ll::pk::rsa::PublicKey = body
529
5
            .required(ONION_KEY)?
530
5
            .parse_obj::<RsaPublic>("RSA PUBLIC KEY")?
531
5
            .check_len_eq(1024)?
532
5
            .check_exponent(65537)?
533
5
            .into();
534

            
535
        // TAP crosscert
536
5
        let tap_crosscert_sig = {
537
5
            let cc_tok = body.required(ONION_KEY_CROSSCERT)?;
538
5
            let cc_val = cc_tok.obj("CROSSCERT")?;
539
5
            let mut signed = Vec::new();
540
5
            signed.extend(rsa_identity.to_rsa_identity().as_bytes());
541
5
            signed.extend(identity_cert.peek_signing_key().as_bytes());
542
5
            ll::pk::rsa::ValidatableRsaSignature::new(&tap_onion_key, &cc_val, &signed)
543
        };
544

            
545
        // List of subprotocol versions
546
5
        let proto = {
547
5
            let proto_tok = body.required(PROTO)?;
548
5
            proto_tok
549
5
                .args_as_str()
550
5
                .parse::<tor_protover::Protocols>()
551
5
                .map_err(|e| EK::BadArgument.at_pos(proto_tok.pos()).with_source(e))?
552
        };
553

            
554
        // tunneled-dir-server
555
5
        let is_dircache = (dirport != 0) || body.get(TUNNELLED_DIR_SERVER).is_some();
556

            
557
        // caches-extra-info
558
5
        let is_extrainfo_cache = body.get(CACHES_EXTRA_INFO).is_some();
559

            
560
        // fingerprint: check for consistency with RSA identity.
561
5
        if let Some(fp_tok) = body.get(FINGERPRINT) {
562
5
            let fp: RsaIdentity = fp_tok.args_as_str().parse::<SpFingerprint>()?.into();
563
5
            if fp != rsa_identity.to_rsa_identity() {
564
2
                return Err(EK::BadArgument
565
2
                    .at_pos(fp_tok.pos())
566
2
                    .with_msg("fingerprint does not match RSA identity"));
567
3
            }
568
        }
569

            
570
        // Family
571
3
        let family = body.maybe(FAMILY).parse_args_as_str::<RelayFamily>()?;
572

            
573
        // or-address
574
        // Extract at most one ipv6 address from the list.  It's not great,
575
        // but it's what Tor does.
576
3
        let mut ipv6addr = None;
577
3
        for tok in body.slice(OR_ADDRESS) {
578
            if let Ok(net::SocketAddr::V6(a)) = tok.parse_arg::<net::SocketAddr>(0) {
579
                ipv6addr = Some((*a.ip(), a.port()));
580
                break;
581
            }
582
            // We skip over unparsable addresses. Is that right?
583
        }
584

            
585
        // platform
586
3
        let platform = body.maybe(PLATFORM).parse_args_as_str::<RelayPlatform>()?;
587

            
588
        // ipv4_policy
589
3
        let ipv4_policy = {
590
3
            let mut pol = AddrPolicy::new();
591
3
            for ruletok in body.slice(POLICY).iter() {
592
3
                let accept = match ruletok.kwd_str() {
593
3
                    "accept" => RuleKind::Accept,
594
3
                    "reject" => RuleKind::Reject,
595
                    _ => {
596
                        return Err(Error::from(internal!(
597
                            "tried to parse a strange line as a policy"
598
                        ))
599
                        .at_pos(ruletok.pos()))
600
                    }
601
                };
602
3
                let pat: AddrPortPattern = ruletok
603
3
                    .args_as_str()
604
3
                    .parse()
605
3
                    .map_err(|e| EK::BadPolicy.at_pos(ruletok.pos()).with_source(e))?;
606
3
                pol.push(accept, pat);
607
            }
608
3
            pol
609
        };
610

            
611
        // ipv6 policy
612
3
        let ipv6_policy = match body.get(IPV6_POLICY) {
613
1
            Some(p) => p
614
1
                .args_as_str()
615
1
                .parse()
616
1
                .map_err(|e| EK::BadPolicy.at_pos(p.pos()).with_source(e))?,
617
            // Unwrap is safe here because str is not empty
618
            #[allow(clippy::unwrap_used)]
619
2
            None => "reject 1-65535".parse::<PortPolicy>().unwrap(),
620
        };
621

            
622
        // Now we're going to collect signatures and expiration times.
623
2
        let (identity_cert, identity_sig) = identity_cert.dangerously_split()?;
624
2
        let (crosscert_cert, cc_sig) = crosscert_cert.dangerously_split()?;
625
2
        let signatures: Vec<Box<dyn ll::pk::ValidatableSignature>> = vec![
626
2
            Box::new(rsa_signature),
627
2
            Box::new(ed_signature),
628
2
            Box::new(identity_sig),
629
2
            Box::new(cc_sig),
630
2
            Box::new(tap_crosscert_sig),
631
2
        ];
632
2

            
633
2
        let identity_cert = identity_cert.dangerously_assume_timely();
634
2
        let crosscert_cert = crosscert_cert.dangerously_assume_timely();
635
2
        let expirations = &[
636
2
            published + time::Duration::new(ROUTER_EXPIRY_SECONDS, 0),
637
2
            identity_cert.expiry(),
638
2
            crosscert_cert.expiry(),
639
2
        ];
640
2
        // Unwrap is safe here because `expirations` array is not empty
641
2
        #[allow(clippy::unwrap_used)]
642
2
        let expiry = *expirations.iter().max().unwrap();
643
2

            
644
2
        let start_time = published - time::Duration::new(ROUTER_PRE_VALIDITY_SECONDS, 0);
645
2

            
646
2
        let desc = RouterDesc {
647
2
            nickname,
648
2
            ipv4addr,
649
2
            orport,
650
2
            ipv6addr,
651
2
            dirport,
652
2
            uptime,
653
2
            published,
654
2
            identity_cert,
655
2
            rsa_identity,
656
2
            ntor_onion_key,
657
2
            tap_onion_key,
658
2
            proto,
659
2
            is_dircache,
660
2
            is_extrainfo_cache,
661
2
            family,
662
2
            platform,
663
2
            ipv4_policy,
664
2
            ipv6_policy: ipv6_policy.intern(),
665
2
        };
666
2

            
667
2
        let time_gated = timed::TimerangeBound::new(desc, start_time..expiry);
668
2
        let sig_gated = signed::SignatureGated::new(time_gated, signatures);
669
2

            
670
2
        Ok(sig_gated)
671
11
    }
672
}
673

            
674
/// An iterator that parses one or more (possibly annotated
675
/// router descriptors from a string.
676
//
677
// TODO: This is largely copy-pasted from MicrodescReader. Can/should they
678
// be merged?
679
pub struct RouterReader<'a> {
680
    /// True iff we accept annotations
681
    annotated: bool,
682
    /// Reader that we're extracting items from.
683
    reader: NetDocReader<'a, RouterKwd>,
684
}
685

            
686
/// Skip this reader forward until the next thing it reads looks like the
687
/// start of a router descriptor.
688
///
689
/// Used to recover from errors.
690
2
fn advance_to_next_routerdesc(reader: &mut NetDocReader<'_, RouterKwd>, annotated: bool) {
691
2
    use RouterKwd::*;
692
2
    let iter = reader.iter();
693
    loop {
694
2
        let item = iter.peek();
695
1
        match item {
696
1
            Some(Ok(t)) => {
697
1
                let kwd = t.kwd();
698
1
                if (annotated && kwd.is_annotation()) || kwd == ROUTER {
699
1
                    return;
700
                }
701
            }
702
            Some(Err(_)) => {
703
                // Skip over broken tokens.
704
            }
705
            None => {
706
1
                return;
707
            }
708
        }
709
        let _ = iter.next();
710
    }
711
2
}
712

            
713
impl<'a> RouterReader<'a> {
714
    /// Construct a RouterReader to take router descriptors from a string.
715
1
    pub fn new(s: &'a str, allow: &AllowAnnotations) -> Self {
716
1
        let reader = NetDocReader::new(s);
717
1
        let annotated = allow == &AllowAnnotations::AnnotationsAllowed;
718
1
        RouterReader { annotated, reader }
719
1
    }
720

            
721
    /// Extract an annotation from this reader.
722
3
    fn take_annotation(&mut self) -> Result<RouterAnnotation> {
723
3
        if self.annotated {
724
3
            RouterAnnotation::take_from_reader(&mut self.reader)
725
        } else {
726
            Ok(RouterAnnotation::default())
727
        }
728
3
    }
729

            
730
    /// Extract an annotated router descriptor from this reader
731
    ///
732
    /// (internal helper; does not clean up on failures.)
733
3
    fn take_annotated_routerdesc_raw(&mut self) -> Result<AnnotatedRouterDesc> {
734
3
        let ann = self.take_annotation()?;
735
3
        let router = RouterDesc::parse_internal(&mut self.reader)?;
736
1
        Ok(AnnotatedRouterDesc { ann, router })
737
3
    }
738

            
739
    /// Extract an annotated router descriptor from this reader
740
    ///
741
    /// Ensure that at least one token is consumed
742
3
    fn take_annotated_routerdesc(&mut self) -> Result<AnnotatedRouterDesc> {
743
3
        let pos_orig = self.reader.pos();
744
3
        let result = self.take_annotated_routerdesc_raw();
745
3
        if result.is_err() {
746
2
            if self.reader.pos() == pos_orig {
747
                // No tokens were consumed from the reader.  We need
748
                // to drop at least one token to ensure we aren't in
749
                // an infinite loop.
750
                //
751
                // (This might not be able to happen, but it's easier to
752
                // explicitly catch this case than it is to prove that
753
                // it's impossible.)
754
                let _ = self.reader.iter().next();
755
2
            }
756
2
            advance_to_next_routerdesc(&mut self.reader, self.annotated);
757
1
        }
758
3
        result
759
3
    }
760
}
761

            
762
impl<'a> Iterator for RouterReader<'a> {
763
    type Item = Result<AnnotatedRouterDesc>;
764
    fn next(&mut self) -> Option<Self::Item> {
765
        // Is there a next token? If not, we're done.
766
4
        self.reader.iter().peek()?;
767

            
768
3
        Some(
769
3
            self.take_annotated_routerdesc()
770
3
                .map_err(|e| e.within(self.reader.str())),
771
3
        )
772
4
    }
773
}
774

            
775
#[cfg(test)]
776
mod test {
777
    #![allow(clippy::unwrap_used)]
778
    use super::*;
779
    const TESTDATA: &str = include_str!("../../testdata/routerdesc1.txt");
780

            
781
    fn read_bad(fname: &str) -> String {
782
        use std::fs;
783
        use std::path::PathBuf;
784
        let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
785
        path.push("testdata");
786
        path.push("bad-routerdesc");
787
        path.push(fname);
788

            
789
        fs::read_to_string(path).unwrap()
790
    }
791

            
792
    #[test]
793
    fn parse_arbitrary() -> Result<()> {
794
        use tor_checkable::{SelfSigned, Timebound};
795
        let rd = RouterDesc::parse(TESTDATA)?
796
            .check_signature()?
797
            .dangerously_assume_timely();
798

            
799
        assert_eq!(rd.nickname, "idun2");
800
        assert_eq!(rd.orport, 9001);
801
        assert_eq!(rd.dirport, 0);
802

            
803
        assert_eq!(rd.uptime, Some(1828391));
804
        //assert_eq!(rd.platform.unwrap(), "Tor 0.4.2.6 on Linux");
805

            
806
        Ok(())
807
    }
808

            
809
    #[test]
810
    fn test_bad() {
811
        use crate::types::policy::PolicyError;
812
        use crate::Pos;
813
        fn check(fname: &str, e: &Error) {
814
            let text = read_bad(fname);
815
            let rd = RouterDesc::parse(&text);
816
            assert!(rd.is_err());
817
            assert_eq!(&rd.err().unwrap(), e);
818
        }
819

            
820
        check(
821
            "bad-sig-order",
822
            &EK::UnexpectedToken
823
                .with_msg("router-sig-ed25519")
824
                .at_pos(Pos::from_line(50, 1)),
825
        );
826
        check(
827
            "bad-start1",
828
            &EK::MisplacedToken
829
                .with_msg("identity-ed25519")
830
                .at_pos(Pos::from_line(1, 1)),
831
        );
832
        check("bad-start2", &EK::MissingToken.with_msg("identity-ed25519"));
833
        check(
834
            "mismatched-fp",
835
            &EK::BadArgument
836
                .at_pos(Pos::from_line(12, 1))
837
                .with_msg("fingerprint does not match RSA identity"),
838
        );
839
        check("no-ed-sk", &EK::MissingToken.with_msg("identity-ed25519"));
840

            
841
        check(
842
            "bad-cc-sign",
843
            &EK::BadArgument
844
                .at_pos(Pos::from_line(34, 26))
845
                .with_msg("not 0 or 1"),
846
        );
847
        check(
848
            "bad-ipv6policy",
849
            &EK::BadPolicy
850
                .at_pos(Pos::from_line(43, 1))
851
                .with_source(PolicyError::InvalidPolicy),
852
        );
853
    }
854

            
855
    #[test]
856
    fn parse_multiple_annotated() {
857
        use crate::AllowAnnotations;
858
        let mut s = read_bad("bad-cc-sign");
859
        s += "\
860
@uploaded-at 2020-09-26 18:15:41
861
@source \"127.0.0.1\"
862
";
863
        s += TESTDATA;
864
        s += "\
865
@uploaded-at 2020-09-26 18:15:41
866
@source \"127.0.0.1\"
867
";
868
        s += &read_bad("mismatched-fp");
869

            
870
        let rd = RouterReader::new(&s, &AllowAnnotations::AnnotationsAllowed);
871
        let v: Vec<_> = rd.collect();
872
        assert!(v[0].is_err());
873
        assert!(v[1].is_ok());
874
        assert_eq!(
875
            v[1].as_ref().unwrap().ann.source,
876
            Some("\"127.0.0.1\"".to_string())
877
        );
878
        assert!(v[2].is_err());
879
    }
880

            
881
    #[test]
882
    fn test_platform() {
883
        let p = "Tor 0.4.4.4-alpha on a flying bison".parse::<RelayPlatform>();
884
        assert!(p.is_ok());
885
        assert_eq!(
886
            p.unwrap(),
887
            RelayPlatform::Tor(
888
                "0.4.4.4-alpha".parse().unwrap(),
889
                "a flying bison".to_string()
890
            )
891
        );
892

            
893
        let p = "Tor 0.4.4.4-alpha on".parse::<RelayPlatform>();
894
        assert!(p.is_ok());
895

            
896
        let p = "Tor 0.4.4.4-alpha ".parse::<RelayPlatform>();
897
        assert!(p.is_ok());
898
        let p = "Tor 0.4.4.4-alpha".parse::<RelayPlatform>();
899
        assert!(p.is_ok());
900

            
901
        let p = "arti 0.0.0".parse::<RelayPlatform>();
902
        assert!(p.is_ok());
903
        assert_eq!(p.unwrap(), RelayPlatform::Other("arti 0.0.0".to_string()));
904
    }
905
}