1
//! Different kinds of messages that can be encoded in channel cells.
2

            
3
use super::{BoxedCellBody, ChanCmd, RawCellBody, CELL_DATA_LEN};
4
use std::net::{IpAddr, Ipv4Addr};
5
use tor_basic_utils::skip_fmt;
6
use tor_bytes::{self, EncodeError, EncodeResult, Error, Readable, Reader, Result, Writer};
7
use tor_memquota::derive_deftly_template_HasMemoryCost;
8
use tor_units::IntegerMilliseconds;
9

            
10
use caret::caret_int;
11
use derive_deftly::Deftly;
12
use educe::Educe;
13

            
14
/// Trait for the 'bodies' of channel messages.
15
pub trait Body: Readable {
16
    /// Decode a channel cell body from a provided reader.
17
3465
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
18
3465
        r.extract()
19
3465
    }
20
    /// Consume this message and encode its body onto `w`.
21
    ///
22
    /// Does not encode anything _but_ the cell body, and does not pad
23
    /// to the cell length.
24
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()>;
25
}
26

            
27
crate::restrict::restricted_msg! {
28
/// Decoded message from a channel.
29
///
30
/// A ChanMsg is an item received on a channel -- a message from
31
/// another Tor client or relay that we are connected to directly over
32
/// a TLS connection.
33
#[derive(Clone, Debug, Deftly)]
34
#[derive_deftly(HasMemoryCost)]
35
#[non_exhaustive]
36
@omit_from "avoid_conflict_with_a_blanket_implementation"
37
pub enum AnyChanMsg : ChanMsg {
38
    /// A Padding message
39
    Padding,
40
    /// Variable-length padding message
41
    Vpadding,
42
    /// (Deprecated) TAP-based cell to create a new circuit.
43
    Create,
44
    /// (Mostly deprecated) HMAC-based cell to create a new circuit.
45
    CreateFast,
46
    /// Cell to create a new circuit
47
    Create2,
48
    /// (Deprecated) Answer to a Create cell
49
    Created,
50
    /// (Mostly Deprecated) Answer to a CreateFast cell
51
    CreatedFast,
52
    /// Answer to a Create2 cell
53
    Created2,
54
    /// A message sent along a circuit, likely to a more-distant relay.
55
    Relay,
56
    /// A message sent along a circuit (limited supply)
57
    RelayEarly,
58
    /// Tear down a circuit
59
    Destroy,
60
    /// Part of channel negotiation: describes our position on the network
61
    Netinfo,
62
    /// Part of channel negotiation: describes what link protocol versions
63
    /// we support
64
    Versions,
65
    /// Negotiates what kind of channel padding to send
66
    PaddingNegotiate,
67
    /// Part of channel negotiation: additional certificates not in the
68
    /// TLS handshake
69
    Certs,
70
    /// Part of channel negotiation: additional random material to be used
71
    /// as part of authentication
72
    AuthChallenge,
73
    /// Part of channel negotiation: used to authenticate relays when they
74
    /// initiate the channel.
75
    Authenticate,
76
    /// Not yet used
77
    Authorize,
78
    _ =>
79
    /// Any cell whose command we don't recognize
80
    Unrecognized,
81
}
82
}
83

            
84
/// A Padding message is a fixed-length message on a channel that is
85
/// ignored.
86
///
87
/// Padding message can be used to disguise the true amount of data on a
88
/// channel, or as a "keep-alive".
89
///
90
/// The correct response to a padding cell is to drop it and do nothing.
91
#[derive(Clone, Debug, Default, Deftly)]
92
#[derive_deftly(HasMemoryCost)]
93
#[non_exhaustive]
94
pub struct Padding {}
95
impl Padding {
96
    /// Create a new fixed-length padding cell
97
275
    pub fn new() -> Self {
98
275
        Padding {}
99
275
    }
100
}
101
impl Body for Padding {
102
8
    fn encode_onto<W: Writer + ?Sized>(self, _w: &mut W) -> EncodeResult<()> {
103
8
        Ok(())
104
8
    }
105
}
106
impl Readable for Padding {
107
165
    fn take_from(_b: &mut Reader<'_>) -> Result<Self> {
108
165
        Ok(Padding {})
109
165
    }
110
}
111

            
112
/// A VPadding message is a variable-length padding message.
113
///
114
/// The correct response to a padding cell is to drop it and do nothing.
115
#[derive(Clone, Debug, Deftly)]
116
#[derive_deftly(HasMemoryCost)]
117
pub struct Vpadding {
118
    /// How much padding to send in this cell's body.
119
    len: u16,
120
}
121
impl Vpadding {
122
    /// Return a new vpadding cell with given length.
123
110
    pub fn new(len: u16) -> Self {
124
110
        Vpadding { len }
125
110
    }
126
}
127
impl Body for Vpadding {
128
8
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
129
8
        w.write_zeros(self.len as usize);
130
8
        Ok(())
131
8
    }
132
}
133
impl Readable for Vpadding {
134
330
    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
135
330
        if b.remaining() > u16::MAX as usize {
136
            return Err(Error::InvalidMessage(
137
                "Too many bytes in VPADDING cell".into(),
138
            ));
139
330
        }
140
330
        Ok(Vpadding {
141
330
            len: b.remaining() as u16,
142
330
        })
143
330
    }
144
}
145

            
146
/// helper -- declare a fixed-width cell for handshake commands, in which
147
/// a fixed number of bytes matter and the rest are ignored
148
macro_rules! fixed_len_handshake {
149
    {
150
        $(#[$meta:meta])*
151
        $name:ident , $cmd:ident, $len:ident
152
    } => {
153
        $(#[$meta])*
154
        #[derive(Clone,Debug,Deftly)]
155
        #[derive_deftly(HasMemoryCost)]
156
        pub struct $name {
157
            handshake: Vec<u8>
158
        }
159
        impl $name {
160
            /// Create a new cell from a provided handshake.
161
34
            pub fn new<B>(handshake: B) -> Self
162
34
                where B: Into<Vec<u8>>
163
34
            {
164
34
                let handshake = handshake.into();
165
34
                $name { handshake }
166
34
            }
167
        }
168
        impl Body for $name {
169
16
            fn encode_onto<W: Writer + ?Sized>(self, w: &mut W)  -> EncodeResult<()> {
170
16
                w.write_all(&self.handshake[..]);
171
16
                Ok(())
172
16
            }
173
        }
174
        impl Readable for $name {
175
220
            fn take_from(b: &mut Reader<'_>) -> Result<Self> {
176
220
                Ok($name {
177
220
                    handshake: b.take($len)?.into(),
178
                })
179
220
            }
180
        }
181
    }
182
}
183

            
184
/// Number of bytes used for a TAP handshake by the initiator.
185
pub(crate) const TAP_C_HANDSHAKE_LEN: usize = 128 + 16 + 42;
186
/// Number of bytes used for a TAP handshake response
187
pub(crate) const TAP_S_HANDSHAKE_LEN: usize = 128 + 20;
188

            
189
/// Number of bytes used for a CREATE_FAST handshake by the initiator
190
const FAST_C_HANDSHAKE_LEN: usize = 20;
191
/// Number of bytes used for a CREATE_FAST handshake response
192
const FAST_S_HANDSHAKE_LEN: usize = 20 + 20;
193

            
194
fixed_len_handshake! {
195
    /// A Create message creates a circuit, using the TAP handshake.
196
    ///
197
    /// TAP is an obsolete handshake based on RSA-1024 and DH-1024.
198
    /// Relays respond to Create message with a Created reply on
199
    /// success, or a Destroy message on failure.
200
    ///
201
    /// In Tor today, Create is only used for the deprecated v2 onion
202
    /// service protocol.
203
    Create, CREATE, TAP_C_HANDSHAKE_LEN
204
}
205
fixed_len_handshake! {
206
    /// A Created message responds to a Created message, using the TAP
207
    /// handshake.
208
    ///
209
    /// TAP is an obsolete handshake based on RSA-1024 and DH-1024.
210
    Created, CREATED, TAP_S_HANDSHAKE_LEN
211
}
212
fixed_len_handshake! {
213
    /// A CreateFast message creates a circuit using no public-key crypto.
214
    ///
215
    /// CreateFast is safe only when used on an already-secure TLS
216
    /// connection.  It can only be used for the first hop of a circuit.
217
    ///
218
    /// Relays reply to a CreateFast message with CreatedFast on
219
    /// success, or a Destroy message on failure.
220
    ///
221
    /// This handshake was originally used for the first hop of every
222
    /// circuit.  Nowadays it is used for creating one-hop circuits
223
    /// when we don't know any onion key for the first hop.
224
    CreateFast, CREATE_FAST, FAST_C_HANDSHAKE_LEN
225
}
226
impl CreateFast {
227
    /// Return the content of this handshake
228
275
    pub fn handshake(&self) -> &[u8] {
229
275
        &self.handshake
230
275
    }
231
}
232
fixed_len_handshake! {
233
    /// A CreatedFast message responds to a CreateFast message
234
    ///
235
    /// Relays send this message back to indicate that the CrateFast handshake
236
    /// is complete.
237
    CreatedFast, CREATED_FAST, FAST_S_HANDSHAKE_LEN
238
}
239
impl CreatedFast {
240
    /// Consume this message and return the content of this handshake
241
275
    pub fn into_handshake(self) -> Vec<u8> {
242
275
        self.handshake
243
275
    }
244
}
245

            
246
caret_int! {
247
    /// Handshake type, corresponding to [`HTYPE` in
248
    /// tor-spec](https://spec.torproject.org/tor-spec/create-created-cells.html).
249
    #[derive(Deftly)]
250
    #[derive_deftly(HasMemoryCost)]
251
    pub struct HandshakeType(u16) {
252
        /// [TAP](https://spec.torproject.org/tor-spec/create-created-cells.html#TAP) -- the original Tor handshake.
253
        TAP = 0,
254

            
255
        // 1 is reserved
256

            
257
        /// [ntor](https://spec.torproject.org/tor-spec/create-created-cells.html#ntor) -- the ntor+curve25519+sha256 handshake.
258
        NTOR = 2,
259
        /// [ntor-v3](https://spec.torproject.org/tor-spec/create-created-cells.html#ntor-v3) -- ntor extended with extra data.
260
        NTOR_V3 = 3,
261
    }
262
}
263

            
264
/// A Create2 message create a circuit on the current channel.
265
///
266
/// To create a circuit, the client sends a Create2 cell containing a
267
/// handshake of a given type; the relay responds with a Created2 cell
268
/// containing a reply.
269
///
270
/// Currently, most Create2 cells contain a client-side instance of the
271
/// "ntor" handshake.
272
#[derive(Clone, Debug, Deftly)]
273
#[derive_deftly(HasMemoryCost)]
274
pub struct Create2 {
275
    /// Identifier for what kind of handshake this is.
276
    handshake_type: HandshakeType,
277
    /// Body of the handshake.
278
    handshake: Vec<u8>,
279
}
280
impl Body for Create2 {
281
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
282
4
        w.write_u16(self.handshake_type.into());
283
4
        let handshake_len = self
284
4
            .handshake
285
4
            .len()
286
4
            .try_into()
287
4
            .map_err(|_| EncodeError::BadLengthValue)?;
288
4
        w.write_u16(handshake_len);
289
4
        w.write_all(&self.handshake[..]);
290
4
        Ok(())
291
4
    }
292
}
293
impl Readable for Create2 {
294
55
    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
295
55
        let handshake_type = HandshakeType::from(b.take_u16()?);
296
55
        let hlen = b.take_u16()?;
297
55
        let handshake = b.take(hlen as usize)?.into();
298
55
        Ok(Create2 {
299
55
            handshake_type,
300
55
            handshake,
301
55
        })
302
55
    }
303
}
304
impl Create2 {
305
    /// Wrap a typed handshake as a Create2 message
306
36
    pub fn new<B>(handshake_type: HandshakeType, handshake: B) -> Self
307
36
    where
308
36
        B: Into<Vec<u8>>,
309
36
    {
310
36
        let handshake = handshake.into();
311
36
        Create2 {
312
36
            handshake_type,
313
36
            handshake,
314
36
        }
315
36
    }
316

            
317
    /// Return the type of this handshake.
318
55
    pub fn handshake_type(&self) -> HandshakeType {
319
55
        self.handshake_type
320
55
    }
321

            
322
    /// Return the body of this handshake.
323
715
    pub fn body(&self) -> &[u8] {
324
715
        &self.handshake[..]
325
715
    }
326
}
327

            
328
/// A Created2 message completes a circuit-creation handshake.
329
///
330
/// When a relay receives a valid Create2 message that it can handle, it
331
/// establishes the circuit and replies with a Created2.
332
#[derive(Clone, Debug, Deftly)]
333
#[derive_deftly(HasMemoryCost)]
334
pub struct Created2 {
335
    /// Body of the handshake reply
336
    handshake: Vec<u8>,
337
}
338
impl Created2 {
339
    /// Create a new Created2 to hold a given handshake.
340
56
    pub fn new<B>(handshake: B) -> Self
341
56
    where
342
56
        B: Into<Vec<u8>>,
343
56
    {
344
56
        let handshake = handshake.into();
345
56
        Created2 { handshake }
346
56
    }
347
    /// Consume this created2 cell and return its body.
348
715
    pub fn into_body(self) -> Vec<u8> {
349
715
        self.handshake
350
715
    }
351
}
352
impl Body for Created2 {
353
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
354
4
        let handshake_len = self
355
4
            .handshake
356
4
            .len()
357
4
            .try_into()
358
4
            .map_err(|_| EncodeError::BadLengthValue)?;
359
4
        w.write_u16(handshake_len);
360
4
        w.write_all(&self.handshake[..]);
361
4
        Ok(())
362
4
    }
363
}
364
impl Readable for Created2 {
365
55
    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
366
55
        let hlen = b.take_u16()?;
367
55
        let handshake = b.take(hlen as usize)?.into();
368
55
        Ok(Created2 { handshake })
369
55
    }
370
}
371

            
372
/// A Relay cell - that is, one transmitted over a circuit.
373
///
374
/// Once a circuit has been established, relay cells can be sent over
375
/// it.  Clients can send relay cells to any relay on the circuit. Any
376
/// relay on the circuit can send relay cells to the client, either
377
/// directly (if it is the first hop), or indirectly through the
378
/// intermediate hops.
379
///
380
/// A different protocol is defined over the relay cells; it is implemented
381
/// in the [crate::relaycell] module.
382
5170
#[derive(Clone, Educe, derive_more::From, Deftly)]
383
#[derive_deftly(HasMemoryCost)]
384
#[educe(Debug)]
385
pub struct Relay {
386
    /// The contents of the relay cell as encoded for transfer.
387
    ///
388
    /// TODO(nickm): It's nice that this is boxed, since we don't want to copy
389
    /// cell data all over the place. But unfortunately, there are some other
390
    /// places where we _don't_ Box things that we should, and more copies than
391
    /// necessary happen. We should refactor our data handling until we're mostly
392
    /// moving around pointers rather than copying data;  see ticket #7.
393
    #[educe(Debug(method = "skip_fmt"))]
394
    body: BoxedCellBody,
395
}
396
impl Relay {
397
    /// Construct a Relay message from a slice containing its contents.
398
26
    pub fn new<P>(body: P) -> Self
399
26
    where
400
26
        P: AsRef<[u8]>,
401
26
    {
402
26
        let body = body.as_ref();
403
26
        let mut r = [0_u8; CELL_DATA_LEN];
404
26
        // TODO: This will panic if body is too long, but that would be a
405
26
        // programming error anyway.
406
26
        r[..body.len()].copy_from_slice(body);
407
26
        Relay { body: Box::new(r) }
408
26
    }
409
    /// Construct a Relay message from its body.
410
55
    pub fn from_raw(body: RawCellBody) -> Self {
411
55
        Relay {
412
55
            body: Box::new(body),
413
55
        }
414
55
    }
415
    /// Consume this Relay message and return a BoxedCellBody for
416
    /// encryption/decryption.
417
77605
    pub fn into_relay_body(self) -> BoxedCellBody {
418
77605
        self.body
419
77605
    }
420
    /// Wrap this Relay message into a RelayMsg as a RELAY_EARLY cell.
421
55
    pub fn into_early(self) -> AnyChanMsg {
422
55
        AnyChanMsg::RelayEarly(RelayEarly(self))
423
55
    }
424
}
425
impl Body for Relay {
426
12
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
427
12
        w.write_all(&self.body[..]);
428
12
        Ok(())
429
12
    }
430
}
431
impl Readable for Relay {
432
330
    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
433
330
        let mut body = Box::new([0_u8; CELL_DATA_LEN]);
434
330
        body.copy_from_slice(b.take(CELL_DATA_LEN)?);
435
330
        Ok(Relay { body })
436
330
    }
437
}
438

            
439
/// A Relay cell that is allowed to contain a CREATE message.
440
///
441
/// Only a limited number of these may be sent on each circuit.
442
#[derive(Clone, Debug, derive_more::Deref, derive_more::From, derive_more::Into, Deftly)]
443
#[derive_deftly(HasMemoryCost)]
444
pub struct RelayEarly(Relay);
445
impl Readable for RelayEarly {
446
55
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
447
55
        Ok(RelayEarly(Relay::take_from(r)?))
448
55
    }
449
}
450
impl Body for RelayEarly {
451
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
452
4
        self.0.encode_onto(w)
453
4
    }
454
}
455
impl RelayEarly {
456
    /// Consume this RelayEarly message and return a BoxedCellBody for
457
    /// encryption/decryption.
458
    //
459
    // (Since this method takes `self` by value, we can't take advantage of
460
    // Deref.)
461
440
    pub fn into_relay_body(self) -> BoxedCellBody {
462
440
        self.0.body
463
440
    }
464
}
465

            
466
/// The Destroy message tears down a circuit.
467
///
468
/// On receiving a Destroy message, a Tor implementation should
469
/// tear down the associated circuit, and pass the destroy message
470
/// down the circuit to later/earlier hops on the circuit (if any).
471
#[derive(Clone, Debug, Deftly)]
472
#[derive_deftly(HasMemoryCost)]
473
pub struct Destroy {
474
    /// Reason code given for tearing down this circuit
475
    reason: DestroyReason,
476
}
477
impl Destroy {
478
    /// Create a new destroy cell.
479
1870
    pub fn new(reason: DestroyReason) -> Self {
480
1870
        Destroy { reason }
481
1870
    }
482
    /// Return the provided reason for destroying the circuit.
483
220
    pub fn reason(&self) -> DestroyReason {
484
220
        self.reason
485
220
    }
486
}
487
impl Body for Destroy {
488
16
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
489
16
        w.write_u8(self.reason.into());
490
16
        Ok(())
491
16
    }
492
}
493
impl Readable for Destroy {
494
330
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
495
330
        let reason = r.take_u8()?.into();
496
330
        Ok(Destroy { reason })
497
330
    }
498
}
499

            
500
caret_int! {
501
    /// Declared reason for ending a circuit.
502
    #[derive(Deftly)]
503
    #[derive_deftly(HasMemoryCost)]
504
    pub struct DestroyReason(u8) {
505
        /// No reason given.
506
        ///
507
        /// This is the only reason that clients send.
508
        NONE = 0,
509
        /// Protocol violation
510
        PROTOCOL = 1,
511
        /// Internal error.
512
        INTERNAL = 2,
513
        /// Client sent a TRUNCATE command.
514
        REQUESTED = 3,
515
        /// Relay is hibernating and not accepting requests
516
        HIBERNATING = 4,
517
        /// Ran out of memory, sockets, or circuit IDs
518
        RESOURCELIMIT = 5,
519
        /// Couldn't connect to relay.
520
        CONNECTFAILED = 6,
521
        /// Connected to a relay, but its OR identity wasn't as requested.
522
        OR_IDENTITY = 7,
523
        /// One of the OR channels carrying this circuit died.
524
        CHANNEL_CLOSED = 8,
525
        /// Circuit expired for being too dirty or old
526
        FINISHED = 9,
527
        /// Circuit construction took too long
528
        TIMEOUT = 10,
529
        /// Circuit was destroyed w/o client truncate (?)
530
        DESTROYED = 11,
531
        /// Request for unknown onion service
532
        NOSUCHSERVICE = 12
533
    }
534
}
535

            
536
impl DestroyReason {
537
    /// Return a human-readable string for this reason.
538
224
    pub fn human_str(&self) -> &'static str {
539
224
        match *self {
540
            DestroyReason::NONE => "No reason",
541
            DestroyReason::PROTOCOL => "Protocol violation",
542
            DestroyReason::INTERNAL => "Internal error",
543
            DestroyReason::REQUESTED => "Client sent a TRUNCATE command",
544
220
            DestroyReason::HIBERNATING => "Relay is hibernating and not accepting requests",
545
            DestroyReason::RESOURCELIMIT => "Relay ran out of resources",
546
2
            DestroyReason::CONNECTFAILED => "Couldn't connect to relay",
547
            DestroyReason::OR_IDENTITY => "Connected to relay with different OR identity",
548
            DestroyReason::CHANNEL_CLOSED => "The OR channels carrying this circuit died",
549
            DestroyReason::FINISHED => "Circuit expired for being too dirty or old",
550
            DestroyReason::TIMEOUT => "Circuit construction took too long",
551
            DestroyReason::DESTROYED => "Circuit was destroyed without client truncate",
552
            DestroyReason::NOSUCHSERVICE => "No such onion service",
553
2
            _ => "Unrecognized reason",
554
        }
555
224
    }
556
}
557

            
558
/// The netinfo message ends channel negotiation.
559
///
560
/// It tells the other party on the channel our view of the current time,
561
/// our own list of public addresses, and our view of its address.
562
///
563
/// When we get a netinfo cell, we can start creating circuits on a
564
/// channel and sending data.
565
#[derive(Clone, Debug, Deftly)]
566
#[derive_deftly(HasMemoryCost)]
567
pub struct Netinfo {
568
    /// Time when this cell was sent, or 0 if this cell is sent by a client.
569
    ///
570
    /// TODO-SPEC(nickm): Y2038 issue here.  Better add a new handshake version
571
    /// to solve it.  See
572
    /// [torspec#80](https://gitlab.torproject.org/tpo/core/torspec/-/issues/80).
573
    timestamp: u32,
574
    /// Observed address for party that did not send the netinfo cell.
575
    their_addr: Option<IpAddr>,
576
    /// Canonical addresses for the party that did send the netinfo cell.
577
    my_addr: Vec<IpAddr>,
578
}
579
/// helper: encode a single address in the form that netinfo messages expect
580
32
fn enc_one_netinfo_addr<W: Writer + ?Sized>(w: &mut W, addr: &IpAddr) {
581
32
    match addr {
582
24
        IpAddr::V4(ipv4) => {
583
24
            w.write_u8(0x04); // type.
584
24
            w.write_u8(4); // length.
585
24
            w.write_all(&ipv4.octets()[..]);
586
24
        }
587
8
        IpAddr::V6(ipv6) => {
588
8
            w.write_u8(0x06); // type.
589
8
            w.write_u8(16); // length.
590
8
            w.write_all(&ipv6.octets()[..]);
591
8
        }
592
    }
593
32
}
594
/// helper: take an address as encoded in a netinfo message
595
1210
fn take_one_netinfo_addr(r: &mut Reader<'_>) -> Result<Option<IpAddr>> {
596
1210
    let atype = r.take_u8()?;
597
1210
    let alen = r.take_u8()?;
598
1210
    let abody = r.take(alen as usize)?;
599
1210
    match (atype, alen) {
600
        (0x04, 4) => {
601
825
            let bytes = [abody[0], abody[1], abody[2], abody[3]];
602
825
            Ok(Some(IpAddr::V4(bytes.into())))
603
        }
604
        (0x06, 16) => {
605
            // TODO(nickm) is there a better way?
606
165
            let mut bytes = [0_u8; 16];
607
165
            bytes.copy_from_slice(abody);
608
165
            Ok(Some(IpAddr::V6(bytes.into())))
609
        }
610
220
        (_, _) => Ok(None),
611
    }
612
1210
}
613
impl Netinfo {
614
    /// Construct a new Netinfo to be sent by a client.
615
825
    pub fn from_client(their_addr: Option<IpAddr>) -> Self {
616
825
        Netinfo {
617
825
            timestamp: 0, // clients don't report their timestamps.
618
825
            their_addr,
619
825
            my_addr: Vec::new(), // clients don't report their addrs.
620
825
        }
621
825
    }
622
    /// Construct a new Netinfo to be sent by a relay
623
6
    pub fn from_relay<V>(timestamp: u32, their_addr: Option<IpAddr>, my_addrs: V) -> Self
624
6
    where
625
6
        V: Into<Vec<IpAddr>>,
626
6
    {
627
6
        let my_addr = my_addrs.into();
628
6
        Netinfo {
629
6
            timestamp,
630
6
            their_addr,
631
6
            my_addr,
632
6
        }
633
6
    }
634
    /// Return the time reported in this NETINFO cell.
635
220
    pub fn timestamp(&self) -> Option<std::time::SystemTime> {
636
        use std::time::{Duration, SystemTime};
637
220
        if self.timestamp == 0 {
638
55
            None
639
        } else {
640
165
            Some(SystemTime::UNIX_EPOCH + Duration::from_secs(self.timestamp.into()))
641
        }
642
220
    }
643
}
644
impl Body for Netinfo {
645
20
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
646
20
        w.write_u32(self.timestamp);
647
20
        let their_addr = self
648
20
            .their_addr
649
20
            .unwrap_or_else(|| Ipv4Addr::UNSPECIFIED.into());
650
20
        enc_one_netinfo_addr(w, &their_addr);
651
20
        let n_addrs: u8 = self
652
20
            .my_addr
653
20
            .len()
654
20
            .try_into()
655
20
            .map_err(|_| EncodeError::BadLengthValue)?;
656
20
        w.write_u8(n_addrs);
657
32
        for addr in &self.my_addr {
658
12
            enc_one_netinfo_addr(w, addr);
659
12
        }
660
20
        Ok(())
661
20
    }
662
}
663
impl Readable for Netinfo {
664
605
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
665
605
        let timestamp = r.take_u32()?;
666
614
        let their_addr = take_one_netinfo_addr(r)?.filter(|a| !a.is_unspecified());
667
605
        let my_n_addrs = r.take_u8()?;
668
605
        let mut my_addr = Vec::with_capacity(my_n_addrs as usize);
669
605
        for _ in 0..my_n_addrs {
670
605
            if let Some(a) = take_one_netinfo_addr(r)? {
671
495
                my_addr.push(a);
672
495
            }
673
        }
674
605
        Ok(Netinfo {
675
605
            timestamp,
676
605
            their_addr,
677
605
            my_addr,
678
605
        })
679
605
    }
680
}
681

            
682
/// A Versions message begins channel negotiation.
683
///
684
/// Every channel must begin by sending a Versions message.  This message
685
/// lists the link protocol versions that this Tor implementation supports.
686
///
687
/// Note that we should never actually send Versions cells using the
688
/// usual channel cell encoding: Versions cells _always_ use two-byte
689
/// circuit IDs, whereas all the other cell types use four-byte
690
/// circuit IDs [assuming a non-obsolete version is negotiated].
691
#[derive(Clone, Debug, Deftly)]
692
#[derive_deftly(HasMemoryCost)]
693
pub struct Versions {
694
    /// List of supported link protocol versions
695
    versions: Vec<u16>,
696
}
697
impl Versions {
698
    /// Construct a new Versions message using a provided list of link
699
    /// protocols.
700
    ///
701
    /// Returns an error if the list of versions is too long.
702
32
    pub fn new<B>(vs: B) -> crate::Result<Self>
703
32
    where
704
32
        B: Into<Vec<u16>>,
705
32
    {
706
32
        let versions = vs.into();
707
32
        if versions.len() < (u16::MAX / 2) as usize {
708
32
            Ok(Self { versions })
709
        } else {
710
            Err(crate::Error::CantEncode("Too many versions"))
711
        }
712
32
    }
713
    /// Encode this VERSIONS cell in the manner expected for a handshake.
714
    ///
715
    /// (That's different from a standard cell encoding, since we
716
    /// have not negotiated versions yet, and so our circuit-ID length
717
    /// is an obsolete 2 bytes).
718
715
    pub fn encode_for_handshake(self) -> EncodeResult<Vec<u8>> {
719
715
        let mut v = Vec::new();
720
715
        v.write_u16(0); // obsolete circuit ID length.
721
715
        v.write_u8(ChanCmd::VERSIONS.into());
722
715
        v.write_u16((self.versions.len() * 2) as u16); // message length.
723
715
        self.encode_onto(&mut v)?;
724
715
        Ok(v)
725
715
    }
726
    /// Return the best (numerically highest) link protocol that is
727
    /// shared by this versions cell and my_protos.
728
880
    pub fn best_shared_link_protocol(&self, my_protos: &[u16]) -> Option<u16> {
729
880
        // NOTE: this implementation is quadratic, but it shouldn't matter
730
880
        // much so long as my_protos is small.
731
880
        let p = my_protos
732
880
            .iter()
733
1941
            .filter(|p| self.versions.contains(p))
734
1501
            .fold(0_u16, |a, b| u16::max(a, *b));
735
880
        if p == 0 {
736
165
            None
737
        } else {
738
715
            Some(p)
739
        }
740
880
    }
741
}
742
impl Body for Versions {
743
825
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
744
2640
        for v in &self.versions {
745
1815
            w.write_u16(*v);
746
1815
        }
747
825
        Ok(())
748
825
    }
749
}
750
impl Readable for Versions {
751
660
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
752
660
        let mut versions = Vec::new();
753
2585
        while r.remaining() > 0 {
754
1925
            versions.push(r.take_u16()?);
755
        }
756
660
        Ok(Versions { versions })
757
660
    }
758
}
759

            
760
caret_int! {
761
    /// A ChanCmd is the type of a channel cell.  The value of the ChanCmd
762
    /// indicates the meaning of the cell, and (possibly) its length.
763
    #[derive(Deftly)]
764
    #[derive_deftly(HasMemoryCost)]
765
    pub struct PaddingNegotiateCmd(u8) {
766
        /// Start padding
767
        START = 2,
768

            
769
        /// Stop padding
770
        STOP = 1,
771
    }
772
}
773

            
774
/// A PaddingNegotiate message is used to negotiate channel padding.
775
///
776
/// Sent by a client to its guard node,
777
/// to instruct the relay to enable/disable channel padding.
778
/// (Not relevant for channels used only for directory lookups,
779
/// nor inter-relay channels.)
780
/// See `padding-spec.txt`, section 2.2.
781
///
782
/// This message is constructed in the channel manager and transmitted by the reactor.
783
///
784
/// The `Default` impl is the same as [`start_default()`](PaddingNegotiate::start_default`)
785
#[derive(Clone, Debug, Eq, PartialEq, Deftly)]
786
#[derive_deftly(HasMemoryCost)]
787
pub struct PaddingNegotiate {
788
    /// Whether to start or stop padding
789
    command: PaddingNegotiateCmd,
790
    /// Suggested lower-bound value for inter-packet timeout in msec.
791
    // TODO(nickm) is that right?
792
    ito_low_ms: u16,
793
    /// Suggested upper-bound value for inter-packet timeout in msec.
794
    // TODO(nickm) is that right?
795
    ito_high_ms: u16,
796
}
797
impl PaddingNegotiate {
798
    /// Create a new PADDING_NEGOTIATE START message requesting consensus timing parameters.
799
    ///
800
    /// This message restores the state to the one which exists at channel startup.
801
4290
    pub fn start_default() -> Self {
802
4290
        // Tor Spec section 7.3, padding-spec section 2.5.
803
4290
        Self {
804
4290
            command: PaddingNegotiateCmd::START,
805
4290
            ito_low_ms: 0,
806
4290
            ito_high_ms: 0,
807
4290
        }
808
4290
    }
809

            
810
    /// Create a new PADDING_NEGOTIATE START message.
811
55
    pub fn start(ito_low: IntegerMilliseconds<u16>, ito_high: IntegerMilliseconds<u16>) -> Self {
812
55
        // Tor Spec section 7.3
813
55
        Self {
814
55
            command: PaddingNegotiateCmd::START,
815
55
            ito_low_ms: ito_low.as_millis(),
816
55
            ito_high_ms: ito_high.as_millis(),
817
55
        }
818
55
    }
819

            
820
    /// Create a new PADDING_NEGOTIATE STOP message.
821
935
    pub fn stop() -> Self {
822
935
        // Tor Spec section 7.3
823
935
        Self {
824
935
            command: PaddingNegotiateCmd::STOP,
825
935
            ito_low_ms: 0,
826
935
            ito_high_ms: 0,
827
935
        }
828
935
    }
829

            
830
    /// Construct from the three fields: command, low_ms, high_ms, as a tuple
831
    ///
832
    /// For testing only
833
    #[cfg(feature = "testing")]
834
220
    pub fn from_raw(command: PaddingNegotiateCmd, ito_low_ms: u16, ito_high_ms: u16) -> Self {
835
220
        PaddingNegotiate {
836
220
            command,
837
220
            ito_low_ms,
838
220
            ito_high_ms,
839
220
        }
840
220
    }
841
}
842
impl Default for PaddingNegotiate {
843
2475
    fn default() -> Self {
844
2475
        Self::start_default()
845
2475
    }
846
}
847

            
848
impl Body for PaddingNegotiate {
849
8
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
850
8
        w.write_u8(0); // version
851
8
        w.write_u8(self.command.get());
852
8
        w.write_u16(self.ito_low_ms);
853
8
        w.write_u16(self.ito_high_ms);
854
8
        Ok(())
855
8
    }
856
}
857
impl Readable for PaddingNegotiate {
858
165
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
859
165
        let v = r.take_u8()?;
860
165
        if v != 0 {
861
55
            return Err(Error::InvalidMessage(
862
55
                "Unrecognized padding negotiation version".into(),
863
55
            ));
864
110
        }
865
110
        let command = r.take_u8()?.into();
866
110
        let ito_low_ms = r.take_u16()?;
867
110
        let ito_high_ms = r.take_u16()?;
868
110
        Ok(PaddingNegotiate {
869
110
            command,
870
110
            ito_low_ms,
871
110
            ito_high_ms,
872
110
        })
873
165
    }
874
}
875

            
876
/// A single certificate in a Certs cell.
877
///
878
/// The formats used here are implemented in tor-cert. Ed25519Cert is the
879
/// most common.
880
#[derive(Clone, Debug, Deftly)]
881
#[derive_deftly(HasMemoryCost)]
882
struct TorCert {
883
    /// Type code for this certificate.
884
    certtype: u8,
885
    /// Encoded certificate
886
    cert: Vec<u8>,
887
}
888
/// encode a single TorCert `c` onto a Writer `w`.
889
20
fn enc_one_tor_cert<W: Writer + ?Sized>(w: &mut W, c: &TorCert) -> EncodeResult<()> {
890
20
    w.write_u8(c.certtype);
891
20
    let cert_len: u16 = c
892
20
        .cert
893
20
        .len()
894
20
        .try_into()
895
20
        .map_err(|_| EncodeError::BadLengthValue)?;
896
20
    w.write_u16(cert_len);
897
20
    w.write_all(&c.cert[..]);
898
20
    Ok(())
899
20
}
900
/// Try to extract a TorCert from the reader `r`.
901
605
fn take_one_tor_cert(r: &mut Reader<'_>) -> Result<TorCert> {
902
605
    let certtype = r.take_u8()?;
903
550
    let certlen = r.take_u16()?;
904
550
    let cert = r.take(certlen as usize)?;
905
550
    Ok(TorCert {
906
550
        certtype,
907
550
        cert: cert.into(),
908
550
    })
909
605
}
910
/// A Certs message is used as part of the channel handshake to send
911
/// additional certificates.
912
///
913
/// These certificates are not presented as part of the TLS handshake.
914
/// Originally this was meant to make Tor TLS handshakes look "normal", but
915
/// nowadays it serves less purpose, especially now that we have TLS 1.3.
916
///
917
/// Every relay sends this message as part of channel negotiation;
918
/// clients do not send them.
919
#[derive(Clone, Debug, Deftly)]
920
#[derive_deftly(HasMemoryCost)]
921
pub struct Certs {
922
    /// The certificates in this cell
923
    certs: Vec<TorCert>,
924
}
925
impl Certs {
926
    /// Return a new empty certs cell.
927
1045
    pub fn new_empty() -> Self {
928
1045
        Certs { certs: Vec::new() }
929
1045
    }
930
    /// Add a new encoded certificate to this cell.
931
    ///
932
    /// Does not check anything about the well-formedness of the certificate.
933
68
    pub fn push_cert_body<B>(&mut self, certtype: tor_cert::CertType, cert: B)
934
68
    where
935
68
        B: Into<Vec<u8>>,
936
68
    {
937
68
        let certtype = certtype.into();
938
68
        let cert = cert.into();
939
68
        self.certs.push(TorCert { certtype, cert });
940
68
    }
941

            
942
    /// Return the body of the certificate tagged with 'tp', if any.
943
2145
    pub fn cert_body(&self, tp: tor_cert::CertType) -> Option<&[u8]> {
944
2145
        let tp: u8 = tp.into();
945
2145
        self.certs
946
2145
            .iter()
947
5759
            .find(|c| c.certtype == tp)
948
2178
            .map(|c| &c.cert[..])
949
2145
    }
950

            
951
    /// Look for a certificate of type 'tp' in this cell; return it if
952
    /// there is one.
953
1320
    pub fn parse_ed_cert(&self, tp: tor_cert::CertType) -> crate::Result<tor_cert::KeyUnknownCert> {
954
1320
        let body = self
955
1320
            .cert_body(tp)
956
1323
            .ok_or_else(|| crate::Error::ChanProto(format!("Missing {} certificate", tp)))?;
957

            
958
1156
        let cert = tor_cert::Ed25519Cert::decode(body).map_err(|be| crate::Error::BytesErr {
959
55
            err: be,
960
55
            parsed: "ed25519 certificate",
961
1156
        })?;
962
1100
        if cert.peek_cert_type() != tp {
963
            return Err(crate::Error::ChanProto(format!(
964
                "Found a {} certificate labeled as {}",
965
                cert.peek_cert_type(),
966
                tp
967
            )));
968
1100
        }
969
1100

            
970
1100
        Ok(cert)
971
1320
    }
972
}
973

            
974
impl Body for Certs {
975
12
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
976
12
        let n_certs: u8 = self
977
12
            .certs
978
12
            .len()
979
12
            .try_into()
980
12
            .map_err(|_| EncodeError::BadLengthValue)?;
981
12
        w.write_u8(n_certs);
982
32
        for c in &self.certs {
983
20
            enc_one_tor_cert(w, c)?;
984
        }
985
12
        Ok(())
986
12
    }
987
}
988
impl Readable for Certs {
989
770
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
990
770
        let n = r.take_u8()?;
991
770
        let mut certs = Vec::new();
992
770
        for _ in 0..n {
993
605
            certs.push(take_one_tor_cert(r)?);
994
        }
995
715
        Ok(Certs { certs })
996
770
    }
997
}
998

            
999
/// Length of the body for an authentication challenge
const CHALLENGE_LEN: usize = 32;
/// An AuthChallenge message is part of negotiation, sent by
/// responders to initiators.
///
/// The AuthChallenge cell is used to ensure that some unpredictable material
/// has been sent on the channel, and to tell the initiator what
/// authentication methods will be accepted.
///
/// Clients can safely ignore this message: they don't need to authenticate.
#[derive(Clone, Debug, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct AuthChallenge {
    /// Random challenge to be used in generating response
    challenge: [u8; CHALLENGE_LEN],
    /// List of permitted authentication methods
    methods: Vec<u16>,
}
impl AuthChallenge {
    /// Construct a new AuthChallenge cell with a given challenge
    /// value (chosen randomly) and a set of acceptable authentication methods.
2
    pub fn new<B, M>(challenge: B, methods: M) -> Self
2
    where
2
        B: Into<[u8; CHALLENGE_LEN]>,
2
        M: Into<Vec<u16>>,
2
    {
2
        AuthChallenge {
2
            challenge: challenge.into(),
2
            methods: methods.into(),
2
        }
2
    }
}
impl Body for AuthChallenge {
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
4
        w.write_all(&self.challenge[..]);
4
        let n_methods = self
4
            .methods
4
            .len()
4
            .try_into()
4
            .map_err(|_| EncodeError::BadLengthValue)?;
4
        w.write_u16(n_methods);
12
        for m in self.methods {
8
            w.write_u16(m);
8
        }
4
        Ok(())
4
    }
}
impl Readable for AuthChallenge {
275
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
        //let challenge = r.take(CHALLENGE_LEN)?.into();
275
        let challenge = r.extract()?;
275
        let n_methods = r.take_u16()?;
275
        let mut methods = Vec::new();
275
        for _ in 0..n_methods {
550
            methods.push(r.take_u16()?);
        }
275
        Ok(AuthChallenge { challenge, methods })
275
    }
}
/// Part of negotiation: sent by initiators to responders.
///
/// The Authenticate cell proves the initiator's identity to the
/// responder, even if TLS client authentication was not used.
///
/// Clients do not use this.
#[derive(Clone, Debug, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct Authenticate {
    /// Authentication method in use
    authtype: u16,
    /// Encoded authentication object
    auth: Vec<u8>,
}
impl Authenticate {
    /// Create a new Authenticate message from a given type and body.
2
    pub fn new<B>(authtype: u16, body: B) -> Self
2
    where
2
        B: Into<Vec<u8>>,
2
    {
2
        Authenticate {
2
            authtype,
2
            auth: body.into(),
2
        }
2
    }
}
impl Body for Authenticate {
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
4
        w.write_u16(self.authtype);
4
        let authlen = self
4
            .auth
4
            .len()
4
            .try_into()
4
            .map_err(|_| EncodeError::BadLengthValue)?;
4
        w.write_u16(authlen);
4
        w.write_all(&self.auth[..]);
4
        Ok(())
4
    }
}
impl Readable for Authenticate {
55
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
55
        let authtype = r.take_u16()?;
55
        let authlen = r.take_u16()?;
55
        let auth = r.take(authlen as usize)?.into();
55
        Ok(Authenticate { authtype, auth })
55
    }
}
/// The Authorize message type is not yet used.
#[derive(Clone, Debug, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct Authorize {
    /// The cell's content, which isn't really specified yet.
    content: Vec<u8>,
}
impl Authorize {
    /// Construct a new Authorize cell.
2
    pub fn new<B>(content: B) -> Self
2
    where
2
        B: Into<Vec<u8>>,
2
    {
2
        let content = content.into();
2
        Authorize { content }
2
    }
}
impl Body for Authorize {
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
4
        w.write_all(&self.content[..]);
4
        Ok(())
4
    }
}
impl Readable for Authorize {
55
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
55
        Ok(Authorize {
55
            content: r.take(r.remaining())?.into(),
        })
55
    }
}
/// Holds any message whose command we don't recognize.
///
/// Well-behaved Tor implementations are required to ignore commands
/// like this.
///
/// TODO: I believe that this is not a risky case of Postel's law,
/// since it is only for channels, but we should be careful here.
#[derive(Clone, Debug, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct Unrecognized {
    /// The channel command that we got with this cell
    cmd: ChanCmd,
    /// The contents of the cell
    content: Vec<u8>,
}
impl Unrecognized {
    /// Construct a new cell of arbitrary or unrecognized type.
6
    pub fn new<B>(cmd: ChanCmd, content: B) -> Self
6
    where
6
        B: Into<Vec<u8>>,
6
    {
6
        let content = content.into();
6
        Unrecognized { cmd, content }
6
    }
    /// Return the command from this cell.
220
    pub fn cmd(&self) -> ChanCmd {
220
        self.cmd
220
    }
    /// Take an unrecognized cell's body from a reader `r`, and apply
    /// the given command to it.
220
    pub fn decode_with_cmd(cmd: ChanCmd, r: &mut Reader<'_>) -> Result<Unrecognized> {
220
        let mut u = Unrecognized::take_from(r)?;
220
        u.cmd = cmd;
220
        Ok(u)
220
    }
}
impl Body for Unrecognized {
12
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
12
        w.write_all(&self.content[..]);
12
        Ok(())
12
    }
}
impl Readable for Unrecognized {
220
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
220
        Ok(Unrecognized {
220
            cmd: 0.into(),
220
            content: r.take(r.remaining())?.into(),
        })
220
    }
}
/// Helper: declare a From<> implementation from message types for
/// cells that don't take a circid.
macro_rules! msg_into_cell {
    ($body:ident) => {
        impl From<$body> for super::AnyChanCell {
165
            fn from(body: $body) -> super::AnyChanCell {
165
                super::AnyChanCell {
165
                    circid: None,
165
                    msg: body.into(),
165
                }
165
            }
        }
    };
}
msg_into_cell!(Padding);
msg_into_cell!(Vpadding);
msg_into_cell!(Netinfo);
msg_into_cell!(Versions);
msg_into_cell!(PaddingNegotiate);
msg_into_cell!(Certs);
msg_into_cell!(AuthChallenge);
msg_into_cell!(Authenticate);
msg_into_cell!(Authorize);
/// Helper: declare a ChanMsg implementation for a message type that has a
/// fixed command.
//
// TODO: It might be better to merge Body with ChanMsg, but that is complex,
// since their needs are _slightly_ different.
//
// TODO: If we *do* make the change above, then perhaps we should also implement
// our restricted enums in terms of this, so that there is only one instance of
// [<$body:snake:upper>]
macro_rules! msg_impl_chanmsg {
    ($($body:ident,)*) =>
    {paste::paste!{
       $(impl crate::chancell::ChanMsg for $body {
4730
            fn cmd(&self) -> crate::chancell::ChanCmd { crate::chancell::ChanCmd::[< $body:snake:upper >] }
            fn encode_onto<W: tor_bytes::Writer + ?Sized>(self, w: &mut W) -> tor_bytes::EncodeResult<()> {
                crate::chancell::msg::Body::encode_onto(self, w)
            }
            fn decode_from_reader(cmd: ChanCmd, r: &mut tor_bytes::Reader<'_>) -> tor_bytes::Result<Self> {
                if cmd != crate::chancell::ChanCmd::[< $body:snake:upper >] {
                    return Err(tor_bytes::Error::InvalidMessage(
                        format!("Expected {} command; got {cmd}", stringify!([< $body:snake:upper >])).into()
                    ));
                }
                crate::chancell::msg::Body::decode_from_reader(r)
            }
        })*
    }}
}
// We implement ChanMsg for every body type, so that you can write code that does
// e.g. ChanCell<Relay>.
msg_impl_chanmsg!(
    Padding,
    Vpadding,
    Create,
    CreateFast,
    Create2,
    Created,
    CreatedFast,
    Created2,
    Relay,
    RelayEarly,
    Destroy,
    Netinfo,
    Versions,
    PaddingNegotiate,
    Certs,
    AuthChallenge,
    Authenticate,
    Authorize,
);
#[cfg(test)]
mod test {
    // @@ begin test lint list maintained by maint/add_warning @@
    #![allow(clippy::bool_assert_comparison)]
    #![allow(clippy::clone_on_copy)]
    #![allow(clippy::dbg_macro)]
    #![allow(clippy::mixed_attributes_style)]
    #![allow(clippy::print_stderr)]
    #![allow(clippy::print_stdout)]
    #![allow(clippy::single_char_pattern)]
    #![allow(clippy::unwrap_used)]
    #![allow(clippy::unchecked_duration_subtraction)]
    #![allow(clippy::useless_vec)]
    #![allow(clippy::needless_pass_by_value)]
    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
    use super::*;
    #[test]
    fn destroy_reason() {
        let r1 = DestroyReason::CONNECTFAILED;
        assert_eq!(r1.human_str(), "Couldn't connect to relay");
        let r2 = DestroyReason::from(200); // not a specified number.
        assert_eq!(r2.human_str(), "Unrecognized reason");
    }
}