tor_cell/chancell/
msg.rs

1//! Different kinds of messages that can be encoded in channel cells.
2
3use super::{BoxedCellBody, ChanCmd, RawCellBody, CELL_DATA_LEN};
4use std::net::{IpAddr, Ipv4Addr};
5use tor_basic_utils::skip_fmt;
6use tor_bytes::{self, EncodeError, EncodeResult, Error, Readable, Reader, Result, Writer};
7use tor_memquota::derive_deftly_template_HasMemoryCost;
8use tor_units::IntegerMilliseconds;
9
10use caret::caret_int;
11use derive_deftly::Deftly;
12use educe::Educe;
13
14/// Trait for the 'bodies' of channel messages.
15pub trait Body: Readable {
16    /// Decode a channel cell body from a provided reader.
17    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
18        r.extract()
19    }
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
27crate::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"
37pub 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]
94pub struct Padding {}
95impl Padding {
96    /// Create a new fixed-length padding cell
97    pub fn new() -> Self {
98        Padding {}
99    }
100}
101impl Body for Padding {
102    fn encode_onto<W: Writer + ?Sized>(self, _w: &mut W) -> EncodeResult<()> {
103        Ok(())
104    }
105}
106impl Readable for Padding {
107    fn take_from(_b: &mut Reader<'_>) -> Result<Self> {
108        Ok(Padding {})
109    }
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)]
117pub struct Vpadding {
118    /// How much padding to send in this cell's body.
119    len: u16,
120}
121impl Vpadding {
122    /// Return a new vpadding cell with given length.
123    pub fn new(len: u16) -> Self {
124        Vpadding { len }
125    }
126}
127impl Body for Vpadding {
128    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
129        w.write_zeros(self.len as usize);
130        Ok(())
131    }
132}
133impl Readable for Vpadding {
134    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
135        if b.remaining() > u16::MAX as usize {
136            return Err(Error::InvalidMessage(
137                "Too many bytes in VPADDING cell".into(),
138            ));
139        }
140        Ok(Vpadding {
141            len: b.remaining() as u16,
142        })
143    }
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
148macro_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            pub fn new<B>(handshake: B) -> Self
162                where B: Into<Vec<u8>>
163            {
164                let handshake = handshake.into();
165                $name { handshake }
166            }
167        }
168        impl Body for $name {
169            fn encode_onto<W: Writer + ?Sized>(self, w: &mut W)  -> EncodeResult<()> {
170                w.write_all(&self.handshake[..]);
171                Ok(())
172            }
173        }
174        impl Readable for $name {
175            fn take_from(b: &mut Reader<'_>) -> Result<Self> {
176                Ok($name {
177                    handshake: b.take($len)?.into(),
178                })
179            }
180        }
181    }
182}
183
184/// Number of bytes used for a TAP handshake by the initiator.
185pub(crate) const TAP_C_HANDSHAKE_LEN: usize = 128 + 16 + 42;
186/// Number of bytes used for a TAP handshake response
187pub(crate) const TAP_S_HANDSHAKE_LEN: usize = 128 + 20;
188
189/// Number of bytes used for a CREATE_FAST handshake by the initiator
190const FAST_C_HANDSHAKE_LEN: usize = 20;
191/// Number of bytes used for a CREATE_FAST handshake response
192const FAST_S_HANDSHAKE_LEN: usize = 20 + 20;
193
194fixed_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}
205fixed_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}
212fixed_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}
226impl CreateFast {
227    /// Return the content of this handshake
228    pub fn handshake(&self) -> &[u8] {
229        &self.handshake
230    }
231}
232fixed_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}
239impl CreatedFast {
240    /// Consume this message and return the content of this handshake
241    pub fn into_handshake(self) -> Vec<u8> {
242        self.handshake
243    }
244}
245
246caret_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)]
274pub 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}
280impl Body for Create2 {
281    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
282        w.write_u16(self.handshake_type.into());
283        let handshake_len = self
284            .handshake
285            .len()
286            .try_into()
287            .map_err(|_| EncodeError::BadLengthValue)?;
288        w.write_u16(handshake_len);
289        w.write_all(&self.handshake[..]);
290        Ok(())
291    }
292}
293impl Readable for Create2 {
294    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
295        let handshake_type = HandshakeType::from(b.take_u16()?);
296        let hlen = b.take_u16()?;
297        let handshake = b.take(hlen as usize)?.into();
298        Ok(Create2 {
299            handshake_type,
300            handshake,
301        })
302    }
303}
304impl Create2 {
305    /// Wrap a typed handshake as a Create2 message
306    pub fn new<B>(handshake_type: HandshakeType, handshake: B) -> Self
307    where
308        B: Into<Vec<u8>>,
309    {
310        let handshake = handshake.into();
311        Create2 {
312            handshake_type,
313            handshake,
314        }
315    }
316
317    /// Return the type of this handshake.
318    pub fn handshake_type(&self) -> HandshakeType {
319        self.handshake_type
320    }
321
322    /// Return the body of this handshake.
323    pub fn body(&self) -> &[u8] {
324        &self.handshake[..]
325    }
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)]
334pub struct Created2 {
335    /// Body of the handshake reply
336    handshake: Vec<u8>,
337}
338impl Created2 {
339    /// Create a new Created2 to hold a given handshake.
340    pub fn new<B>(handshake: B) -> Self
341    where
342        B: Into<Vec<u8>>,
343    {
344        let handshake = handshake.into();
345        Created2 { handshake }
346    }
347    /// Consume this created2 cell and return its body.
348    pub fn into_body(self) -> Vec<u8> {
349        self.handshake
350    }
351}
352impl Body for Created2 {
353    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
354        let handshake_len = self
355            .handshake
356            .len()
357            .try_into()
358            .map_err(|_| EncodeError::BadLengthValue)?;
359        w.write_u16(handshake_len);
360        w.write_all(&self.handshake[..]);
361        Ok(())
362    }
363}
364impl Readable for Created2 {
365    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
366        let hlen = b.take_u16()?;
367        let handshake = b.take(hlen as usize)?.into();
368        Ok(Created2 { handshake })
369    }
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#[derive(Clone, Educe, derive_more::From, Deftly)]
383#[derive_deftly(HasMemoryCost)]
384#[educe(Debug)]
385pub 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}
396impl Relay {
397    /// Construct a Relay message from a slice containing its contents.
398    pub fn new<P>(body: P) -> Self
399    where
400        P: AsRef<[u8]>,
401    {
402        let body = body.as_ref();
403        let mut r = [0_u8; CELL_DATA_LEN];
404        // TODO: This will panic if body is too long, but that would be a
405        // programming error anyway.
406        r[..body.len()].copy_from_slice(body);
407        Relay { body: Box::new(r) }
408    }
409    /// Construct a Relay message from its body.
410    pub fn from_raw(body: RawCellBody) -> Self {
411        Relay {
412            body: Box::new(body),
413        }
414    }
415    /// Consume this Relay message and return a BoxedCellBody for
416    /// encryption/decryption.
417    pub fn into_relay_body(self) -> BoxedCellBody {
418        self.body
419    }
420    /// Wrap this Relay message into a RelayMsg as a RELAY_EARLY cell.
421    pub fn into_early(self) -> AnyChanMsg {
422        AnyChanMsg::RelayEarly(RelayEarly(self))
423    }
424}
425impl Body for Relay {
426    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
427        w.write_all(&self.body[..]);
428        Ok(())
429    }
430}
431impl Readable for Relay {
432    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
433        let mut body = Box::new([0_u8; CELL_DATA_LEN]);
434        body.copy_from_slice(b.take(CELL_DATA_LEN)?);
435        Ok(Relay { body })
436    }
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)]
444pub struct RelayEarly(Relay);
445impl Readable for RelayEarly {
446    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
447        Ok(RelayEarly(Relay::take_from(r)?))
448    }
449}
450impl Body for RelayEarly {
451    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
452        self.0.encode_onto(w)
453    }
454}
455impl 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    pub fn into_relay_body(self) -> BoxedCellBody {
462        self.0.body
463    }
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)]
473pub struct Destroy {
474    /// Reason code given for tearing down this circuit
475    reason: DestroyReason,
476}
477impl Destroy {
478    /// Create a new destroy cell.
479    pub fn new(reason: DestroyReason) -> Self {
480        Destroy { reason }
481    }
482    /// Return the provided reason for destroying the circuit.
483    pub fn reason(&self) -> DestroyReason {
484        self.reason
485    }
486}
487impl Body for Destroy {
488    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
489        w.write_u8(self.reason.into());
490        Ok(())
491    }
492}
493impl Readable for Destroy {
494    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
495        let reason = r.take_u8()?.into();
496        Ok(Destroy { reason })
497    }
498}
499
500caret_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
536impl DestroyReason {
537    /// Return a human-readable string for this reason.
538    pub fn human_str(&self) -> &'static str {
539        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            DestroyReason::HIBERNATING => "Relay is hibernating and not accepting requests",
545            DestroyReason::RESOURCELIMIT => "Relay ran out of resources",
546            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            _ => "Unrecognized reason",
554        }
555    }
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)]
567pub 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
580fn enc_one_netinfo_addr<W: Writer + ?Sized>(w: &mut W, addr: &IpAddr) {
581    match addr {
582        IpAddr::V4(ipv4) => {
583            w.write_u8(0x04); // type.
584            w.write_u8(4); // length.
585            w.write_all(&ipv4.octets()[..]);
586        }
587        IpAddr::V6(ipv6) => {
588            w.write_u8(0x06); // type.
589            w.write_u8(16); // length.
590            w.write_all(&ipv6.octets()[..]);
591        }
592    }
593}
594/// helper: take an address as encoded in a netinfo message
595fn take_one_netinfo_addr(r: &mut Reader<'_>) -> Result<Option<IpAddr>> {
596    let atype = r.take_u8()?;
597    let alen = r.take_u8()?;
598    let abody = r.take(alen as usize)?;
599    match (atype, alen) {
600        (0x04, 4) => {
601            let bytes = [abody[0], abody[1], abody[2], abody[3]];
602            Ok(Some(IpAddr::V4(bytes.into())))
603        }
604        (0x06, 16) => {
605            // TODO(nickm) is there a better way?
606            let mut bytes = [0_u8; 16];
607            bytes.copy_from_slice(abody);
608            Ok(Some(IpAddr::V6(bytes.into())))
609        }
610        (_, _) => Ok(None),
611    }
612}
613impl Netinfo {
614    /// Construct a new Netinfo to be sent by a client.
615    pub fn from_client(their_addr: Option<IpAddr>) -> Self {
616        Netinfo {
617            timestamp: 0, // clients don't report their timestamps.
618            their_addr,
619            my_addr: Vec::new(), // clients don't report their addrs.
620        }
621    }
622    /// Construct a new Netinfo to be sent by a relay
623    pub fn from_relay<V>(timestamp: u32, their_addr: Option<IpAddr>, my_addrs: V) -> Self
624    where
625        V: Into<Vec<IpAddr>>,
626    {
627        let my_addr = my_addrs.into();
628        Netinfo {
629            timestamp,
630            their_addr,
631            my_addr,
632        }
633    }
634    /// Return the time reported in this NETINFO cell.
635    pub fn timestamp(&self) -> Option<std::time::SystemTime> {
636        use std::time::{Duration, SystemTime};
637        if self.timestamp == 0 {
638            None
639        } else {
640            Some(SystemTime::UNIX_EPOCH + Duration::from_secs(self.timestamp.into()))
641        }
642    }
643}
644impl Body for Netinfo {
645    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
646        w.write_u32(self.timestamp);
647        let their_addr = self
648            .their_addr
649            .unwrap_or_else(|| Ipv4Addr::UNSPECIFIED.into());
650        enc_one_netinfo_addr(w, &their_addr);
651        let n_addrs: u8 = self
652            .my_addr
653            .len()
654            .try_into()
655            .map_err(|_| EncodeError::BadLengthValue)?;
656        w.write_u8(n_addrs);
657        for addr in &self.my_addr {
658            enc_one_netinfo_addr(w, addr);
659        }
660        Ok(())
661    }
662}
663impl Readable for Netinfo {
664    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
665        let timestamp = r.take_u32()?;
666        let their_addr = take_one_netinfo_addr(r)?.filter(|a| !a.is_unspecified());
667        let my_n_addrs = r.take_u8()?;
668        let mut my_addr = Vec::with_capacity(my_n_addrs as usize);
669        for _ in 0..my_n_addrs {
670            if let Some(a) = take_one_netinfo_addr(r)? {
671                my_addr.push(a);
672            }
673        }
674        Ok(Netinfo {
675            timestamp,
676            their_addr,
677            my_addr,
678        })
679    }
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)]
693pub struct Versions {
694    /// List of supported link protocol versions
695    versions: Vec<u16>,
696}
697impl 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    pub fn new<B>(vs: B) -> crate::Result<Self>
703    where
704        B: Into<Vec<u16>>,
705    {
706        let versions = vs.into();
707        if versions.len() < (u16::MAX / 2) as usize {
708            Ok(Self { versions })
709        } else {
710            Err(crate::Error::CantEncode("Too many versions"))
711        }
712    }
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    pub fn encode_for_handshake(self) -> EncodeResult<Vec<u8>> {
719        let mut v = Vec::new();
720        v.write_u16(0); // obsolete circuit ID length.
721        v.write_u8(ChanCmd::VERSIONS.into());
722        v.write_u16((self.versions.len() * 2) as u16); // message length.
723        self.encode_onto(&mut v)?;
724        Ok(v)
725    }
726    /// Return the best (numerically highest) link protocol that is
727    /// shared by this versions cell and my_protos.
728    pub fn best_shared_link_protocol(&self, my_protos: &[u16]) -> Option<u16> {
729        // NOTE: this implementation is quadratic, but it shouldn't matter
730        // much so long as my_protos is small.
731        let p = my_protos
732            .iter()
733            .filter(|p| self.versions.contains(p))
734            .fold(0_u16, |a, b| u16::max(a, *b));
735        if p == 0 {
736            None
737        } else {
738            Some(p)
739        }
740    }
741}
742impl Body for Versions {
743    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
744        for v in &self.versions {
745            w.write_u16(*v);
746        }
747        Ok(())
748    }
749}
750impl Readable for Versions {
751    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
752        let mut versions = Vec::new();
753        while r.remaining() > 0 {
754            versions.push(r.take_u16()?);
755        }
756        Ok(Versions { versions })
757    }
758}
759
760caret_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)]
787pub 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}
797impl 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    pub fn start_default() -> Self {
802        // Tor Spec section 7.3, padding-spec section 2.5.
803        Self {
804            command: PaddingNegotiateCmd::START,
805            ito_low_ms: 0,
806            ito_high_ms: 0,
807        }
808    }
809
810    /// Create a new PADDING_NEGOTIATE START message.
811    pub fn start(ito_low: IntegerMilliseconds<u16>, ito_high: IntegerMilliseconds<u16>) -> Self {
812        // Tor Spec section 7.3
813        Self {
814            command: PaddingNegotiateCmd::START,
815            ito_low_ms: ito_low.as_millis(),
816            ito_high_ms: ito_high.as_millis(),
817        }
818    }
819
820    /// Create a new PADDING_NEGOTIATE STOP message.
821    pub fn stop() -> Self {
822        // Tor Spec section 7.3
823        Self {
824            command: PaddingNegotiateCmd::STOP,
825            ito_low_ms: 0,
826            ito_high_ms: 0,
827        }
828    }
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    pub fn from_raw(command: PaddingNegotiateCmd, ito_low_ms: u16, ito_high_ms: u16) -> Self {
835        PaddingNegotiate {
836            command,
837            ito_low_ms,
838            ito_high_ms,
839        }
840    }
841}
842impl Default for PaddingNegotiate {
843    fn default() -> Self {
844        Self::start_default()
845    }
846}
847
848impl Body for PaddingNegotiate {
849    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
850        w.write_u8(0); // version
851        w.write_u8(self.command.get());
852        w.write_u16(self.ito_low_ms);
853        w.write_u16(self.ito_high_ms);
854        Ok(())
855    }
856}
857impl Readable for PaddingNegotiate {
858    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
859        let v = r.take_u8()?;
860        if v != 0 {
861            return Err(Error::InvalidMessage(
862                "Unrecognized padding negotiation version".into(),
863            ));
864        }
865        let command = r.take_u8()?.into();
866        let ito_low_ms = r.take_u16()?;
867        let ito_high_ms = r.take_u16()?;
868        Ok(PaddingNegotiate {
869            command,
870            ito_low_ms,
871            ito_high_ms,
872        })
873    }
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)]
882struct 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`.
889fn enc_one_tor_cert<W: Writer + ?Sized>(w: &mut W, c: &TorCert) -> EncodeResult<()> {
890    w.write_u8(c.certtype);
891    let cert_len: u16 = c
892        .cert
893        .len()
894        .try_into()
895        .map_err(|_| EncodeError::BadLengthValue)?;
896    w.write_u16(cert_len);
897    w.write_all(&c.cert[..]);
898    Ok(())
899}
900/// Try to extract a TorCert from the reader `r`.
901fn take_one_tor_cert(r: &mut Reader<'_>) -> Result<TorCert> {
902    let certtype = r.take_u8()?;
903    let certlen = r.take_u16()?;
904    let cert = r.take(certlen as usize)?;
905    Ok(TorCert {
906        certtype,
907        cert: cert.into(),
908    })
909}
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)]
921pub struct Certs {
922    /// The certificates in this cell
923    certs: Vec<TorCert>,
924}
925impl Certs {
926    /// Return a new empty certs cell.
927    pub fn new_empty() -> Self {
928        Certs { certs: Vec::new() }
929    }
930    /// Add a new encoded certificate to this cell.
931    ///
932    /// Does not check anything about the well-formedness of the certificate.
933    pub fn push_cert_body<B>(&mut self, certtype: tor_cert::CertType, cert: B)
934    where
935        B: Into<Vec<u8>>,
936    {
937        let certtype = certtype.into();
938        let cert = cert.into();
939        self.certs.push(TorCert { certtype, cert });
940    }
941
942    /// Return the body of the certificate tagged with 'tp', if any.
943    pub fn cert_body(&self, tp: tor_cert::CertType) -> Option<&[u8]> {
944        let tp: u8 = tp.into();
945        self.certs
946            .iter()
947            .find(|c| c.certtype == tp)
948            .map(|c| &c.cert[..])
949    }
950
951    /// Look for a certificate of type 'tp' in this cell; return it if
952    /// there is one.
953    pub fn parse_ed_cert(&self, tp: tor_cert::CertType) -> crate::Result<tor_cert::KeyUnknownCert> {
954        let body = self
955            .cert_body(tp)
956            .ok_or_else(|| crate::Error::ChanProto(format!("Missing {} certificate", tp)))?;
957
958        let cert = tor_cert::Ed25519Cert::decode(body).map_err(|be| crate::Error::BytesErr {
959            err: be,
960            parsed: "ed25519 certificate",
961        })?;
962        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        }
969
970        Ok(cert)
971    }
972}
973
974impl Body for Certs {
975    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
976        let n_certs: u8 = self
977            .certs
978            .len()
979            .try_into()
980            .map_err(|_| EncodeError::BadLengthValue)?;
981        w.write_u8(n_certs);
982        for c in &self.certs {
983            enc_one_tor_cert(w, c)?;
984        }
985        Ok(())
986    }
987}
988impl Readable for Certs {
989    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
990        let n = r.take_u8()?;
991        let mut certs = Vec::new();
992        for _ in 0..n {
993            certs.push(take_one_tor_cert(r)?);
994        }
995        Ok(Certs { certs })
996    }
997}
998
999/// Length of the body for an authentication challenge
1000const CHALLENGE_LEN: usize = 32;
1001
1002/// An AuthChallenge message is part of negotiation, sent by
1003/// responders to initiators.
1004///
1005/// The AuthChallenge cell is used to ensure that some unpredictable material
1006/// has been sent on the channel, and to tell the initiator what
1007/// authentication methods will be accepted.
1008///
1009/// Clients can safely ignore this message: they don't need to authenticate.
1010#[derive(Clone, Debug, Deftly)]
1011#[derive_deftly(HasMemoryCost)]
1012pub struct AuthChallenge {
1013    /// Random challenge to be used in generating response
1014    challenge: [u8; CHALLENGE_LEN],
1015    /// List of permitted authentication methods
1016    methods: Vec<u16>,
1017}
1018impl AuthChallenge {
1019    /// Construct a new AuthChallenge cell with a given challenge
1020    /// value (chosen randomly) and a set of acceptable authentication methods.
1021    pub fn new<B, M>(challenge: B, methods: M) -> Self
1022    where
1023        B: Into<[u8; CHALLENGE_LEN]>,
1024        M: Into<Vec<u16>>,
1025    {
1026        AuthChallenge {
1027            challenge: challenge.into(),
1028            methods: methods.into(),
1029        }
1030    }
1031}
1032
1033impl Body for AuthChallenge {
1034    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1035        w.write_all(&self.challenge[..]);
1036        let n_methods = self
1037            .methods
1038            .len()
1039            .try_into()
1040            .map_err(|_| EncodeError::BadLengthValue)?;
1041        w.write_u16(n_methods);
1042        for m in self.methods {
1043            w.write_u16(m);
1044        }
1045        Ok(())
1046    }
1047}
1048impl Readable for AuthChallenge {
1049    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
1050        //let challenge = r.take(CHALLENGE_LEN)?.into();
1051        let challenge = r.extract()?;
1052        let n_methods = r.take_u16()?;
1053        let mut methods = Vec::new();
1054        for _ in 0..n_methods {
1055            methods.push(r.take_u16()?);
1056        }
1057        Ok(AuthChallenge { challenge, methods })
1058    }
1059}
1060
1061/// Part of negotiation: sent by initiators to responders.
1062///
1063/// The Authenticate cell proves the initiator's identity to the
1064/// responder, even if TLS client authentication was not used.
1065///
1066/// Clients do not use this.
1067#[derive(Clone, Debug, Deftly)]
1068#[derive_deftly(HasMemoryCost)]
1069pub struct Authenticate {
1070    /// Authentication method in use
1071    authtype: u16,
1072    /// Encoded authentication object
1073    auth: Vec<u8>,
1074}
1075impl Authenticate {
1076    /// Create a new Authenticate message from a given type and body.
1077    pub fn new<B>(authtype: u16, body: B) -> Self
1078    where
1079        B: Into<Vec<u8>>,
1080    {
1081        Authenticate {
1082            authtype,
1083            auth: body.into(),
1084        }
1085    }
1086}
1087impl Body for Authenticate {
1088    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1089        w.write_u16(self.authtype);
1090        let authlen = self
1091            .auth
1092            .len()
1093            .try_into()
1094            .map_err(|_| EncodeError::BadLengthValue)?;
1095        w.write_u16(authlen);
1096        w.write_all(&self.auth[..]);
1097        Ok(())
1098    }
1099}
1100impl Readable for Authenticate {
1101    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
1102        let authtype = r.take_u16()?;
1103        let authlen = r.take_u16()?;
1104        let auth = r.take(authlen as usize)?.into();
1105        Ok(Authenticate { authtype, auth })
1106    }
1107}
1108
1109/// The Authorize message type is not yet used.
1110#[derive(Clone, Debug, Deftly)]
1111#[derive_deftly(HasMemoryCost)]
1112pub struct Authorize {
1113    /// The cell's content, which isn't really specified yet.
1114    content: Vec<u8>,
1115}
1116impl Authorize {
1117    /// Construct a new Authorize cell.
1118    pub fn new<B>(content: B) -> Self
1119    where
1120        B: Into<Vec<u8>>,
1121    {
1122        let content = content.into();
1123        Authorize { content }
1124    }
1125}
1126impl Body for Authorize {
1127    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1128        w.write_all(&self.content[..]);
1129        Ok(())
1130    }
1131}
1132impl Readable for Authorize {
1133    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
1134        Ok(Authorize {
1135            content: r.take(r.remaining())?.into(),
1136        })
1137    }
1138}
1139
1140/// Holds any message whose command we don't recognize.
1141///
1142/// Well-behaved Tor implementations are required to ignore commands
1143/// like this.
1144///
1145/// TODO: I believe that this is not a risky case of Postel's law,
1146/// since it is only for channels, but we should be careful here.
1147#[derive(Clone, Debug, Deftly)]
1148#[derive_deftly(HasMemoryCost)]
1149pub struct Unrecognized {
1150    /// The channel command that we got with this cell
1151    cmd: ChanCmd,
1152    /// The contents of the cell
1153    content: Vec<u8>,
1154}
1155impl Unrecognized {
1156    /// Construct a new cell of arbitrary or unrecognized type.
1157    pub fn new<B>(cmd: ChanCmd, content: B) -> Self
1158    where
1159        B: Into<Vec<u8>>,
1160    {
1161        let content = content.into();
1162        Unrecognized { cmd, content }
1163    }
1164    /// Return the command from this cell.
1165    pub fn cmd(&self) -> ChanCmd {
1166        self.cmd
1167    }
1168    /// Take an unrecognized cell's body from a reader `r`, and apply
1169    /// the given command to it.
1170    pub fn decode_with_cmd(cmd: ChanCmd, r: &mut Reader<'_>) -> Result<Unrecognized> {
1171        let mut u = Unrecognized::take_from(r)?;
1172        u.cmd = cmd;
1173        Ok(u)
1174    }
1175}
1176impl Body for Unrecognized {
1177    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1178        w.write_all(&self.content[..]);
1179        Ok(())
1180    }
1181}
1182impl Readable for Unrecognized {
1183    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
1184        Ok(Unrecognized {
1185            cmd: 0.into(),
1186            content: r.take(r.remaining())?.into(),
1187        })
1188    }
1189}
1190
1191/// Helper: declare a From<> implementation from message types for
1192/// cells that don't take a circid.
1193macro_rules! msg_into_cell {
1194    ($body:ident) => {
1195        impl From<$body> for super::AnyChanCell {
1196            fn from(body: $body) -> super::AnyChanCell {
1197                super::AnyChanCell {
1198                    circid: None,
1199                    msg: body.into(),
1200                }
1201            }
1202        }
1203    };
1204}
1205
1206msg_into_cell!(Padding);
1207msg_into_cell!(Vpadding);
1208msg_into_cell!(Netinfo);
1209msg_into_cell!(Versions);
1210msg_into_cell!(PaddingNegotiate);
1211msg_into_cell!(Certs);
1212msg_into_cell!(AuthChallenge);
1213msg_into_cell!(Authenticate);
1214msg_into_cell!(Authorize);
1215
1216/// Helper: declare a ChanMsg implementation for a message type that has a
1217/// fixed command.
1218//
1219// TODO: It might be better to merge Body with ChanMsg, but that is complex,
1220// since their needs are _slightly_ different.
1221//
1222// TODO: If we *do* make the change above, then perhaps we should also implement
1223// our restricted enums in terms of this, so that there is only one instance of
1224// [<$body:snake:upper>]
1225macro_rules! msg_impl_chanmsg {
1226    ($($body:ident,)*) =>
1227    {paste::paste!{
1228       $(impl crate::chancell::ChanMsg for $body {
1229            fn cmd(&self) -> crate::chancell::ChanCmd { crate::chancell::ChanCmd::[< $body:snake:upper >] }
1230            fn encode_onto<W: tor_bytes::Writer + ?Sized>(self, w: &mut W) -> tor_bytes::EncodeResult<()> {
1231                crate::chancell::msg::Body::encode_onto(self, w)
1232            }
1233            fn decode_from_reader(cmd: ChanCmd, r: &mut tor_bytes::Reader<'_>) -> tor_bytes::Result<Self> {
1234                if cmd != crate::chancell::ChanCmd::[< $body:snake:upper >] {
1235                    return Err(tor_bytes::Error::InvalidMessage(
1236                        format!("Expected {} command; got {cmd}", stringify!([< $body:snake:upper >])).into()
1237                    ));
1238                }
1239                crate::chancell::msg::Body::decode_from_reader(r)
1240            }
1241        })*
1242    }}
1243}
1244
1245// We implement ChanMsg for every body type, so that you can write code that does
1246// e.g. ChanCell<Relay>.
1247msg_impl_chanmsg!(
1248    Padding,
1249    Vpadding,
1250    Create,
1251    CreateFast,
1252    Create2,
1253    Created,
1254    CreatedFast,
1255    Created2,
1256    Relay,
1257    RelayEarly,
1258    Destroy,
1259    Netinfo,
1260    Versions,
1261    PaddingNegotiate,
1262    Certs,
1263    AuthChallenge,
1264    Authenticate,
1265    Authorize,
1266);
1267
1268#[cfg(test)]
1269mod test {
1270    // @@ begin test lint list maintained by maint/add_warning @@
1271    #![allow(clippy::bool_assert_comparison)]
1272    #![allow(clippy::clone_on_copy)]
1273    #![allow(clippy::dbg_macro)]
1274    #![allow(clippy::mixed_attributes_style)]
1275    #![allow(clippy::print_stderr)]
1276    #![allow(clippy::print_stdout)]
1277    #![allow(clippy::single_char_pattern)]
1278    #![allow(clippy::unwrap_used)]
1279    #![allow(clippy::unchecked_duration_subtraction)]
1280    #![allow(clippy::useless_vec)]
1281    #![allow(clippy::needless_pass_by_value)]
1282    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
1283    use super::*;
1284    #[test]
1285    fn destroy_reason() {
1286        let r1 = DestroyReason::CONNECTFAILED;
1287
1288        assert_eq!(r1.human_str(), "Couldn't connect to relay");
1289
1290        let r2 = DestroyReason::from(200); // not a specified number.
1291        assert_eq!(r2.human_str(), "Unrecognized reason");
1292    }
1293}