Skip to main content

tor_cell/chancell/
msg.rs

1//! Different kinds of messages that can be encoded in channel cells.
2
3use super::{BoxedCellBody, CELL_DATA_LEN, ChanCmd, RawCellBody};
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    _ =>
77    /// Any cell whose command we don't recognize
78    Unrecognized,
79}
80}
81
82/// A Padding message is a fixed-length message on a channel that is
83/// ignored.
84///
85/// Padding message can be used to disguise the true amount of data on a
86/// channel, or as a "keep-alive".
87///
88/// The correct response to a padding cell is to drop it and do nothing.
89#[derive(Clone, Debug, Default, Deftly)]
90#[derive_deftly(HasMemoryCost)]
91#[non_exhaustive]
92pub struct Padding {}
93impl Padding {
94    /// Create a new fixed-length padding cell
95    pub fn new() -> Self {
96        Padding {}
97    }
98}
99impl Body for Padding {
100    fn encode_onto<W: Writer + ?Sized>(self, _w: &mut W) -> EncodeResult<()> {
101        Ok(())
102    }
103}
104impl Readable for Padding {
105    fn take_from(_b: &mut Reader<'_>) -> Result<Self> {
106        Ok(Padding {})
107    }
108}
109
110/// A VPadding message is a variable-length padding message.
111///
112/// The correct response to a padding cell is to drop it and do nothing.
113#[derive(Clone, Debug, Deftly)]
114#[derive_deftly(HasMemoryCost)]
115pub struct Vpadding {
116    /// How much padding to send in this cell's body.
117    len: u16,
118}
119impl Vpadding {
120    /// Return a new vpadding cell with given length.
121    pub fn new(len: u16) -> Self {
122        Vpadding { len }
123    }
124}
125impl Body for Vpadding {
126    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
127        w.write_zeros(self.len as usize);
128        Ok(())
129    }
130}
131impl Readable for Vpadding {
132    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
133        if b.remaining() > u16::MAX as usize {
134            return Err(Error::InvalidMessage(
135                "Too many bytes in VPADDING cell".into(),
136            ));
137        }
138        Ok(Vpadding {
139            len: b.remaining() as u16,
140        })
141    }
142}
143
144/// helper -- declare a fixed-width cell for handshake commands, in which
145/// a fixed number of bytes matter and the rest are ignored
146macro_rules! fixed_len_handshake {
147    {
148        $(#[$meta:meta])*
149        $name:ident , $cmd:ident, $len:ident
150    } => {
151        $(#[$meta])*
152        #[derive(Clone,Debug,Deftly)]
153        #[derive_deftly(HasMemoryCost)]
154        pub struct $name {
155            handshake: Vec<u8>
156        }
157        impl $name {
158            /// Create a new cell from a provided handshake.
159            pub fn new<B>(handshake: B) -> Self
160                where B: Into<Vec<u8>>
161            {
162                let handshake = handshake.into();
163                $name { handshake }
164            }
165        }
166        impl Body for $name {
167            fn encode_onto<W: Writer + ?Sized>(self, w: &mut W)  -> EncodeResult<()> {
168                w.write_all(&self.handshake[..]);
169                Ok(())
170            }
171        }
172        impl Readable for $name {
173            fn take_from(b: &mut Reader<'_>) -> Result<Self> {
174                Ok($name {
175                    handshake: b.take($len)?.into(),
176                })
177            }
178        }
179    }
180}
181
182/// Number of bytes used for a TAP handshake by the initiator.
183pub(crate) const TAP_C_HANDSHAKE_LEN: usize = 128 + 16 + 42;
184/// Number of bytes used for a TAP handshake response
185pub(crate) const TAP_S_HANDSHAKE_LEN: usize = 128 + 20;
186
187/// Number of bytes used for a CREATE_FAST handshake by the initiator
188const FAST_C_HANDSHAKE_LEN: usize = 20;
189/// Number of bytes used for a CREATE_FAST handshake response
190const FAST_S_HANDSHAKE_LEN: usize = 20 + 20;
191
192fixed_len_handshake! {
193    /// A Create message creates a circuit, using the TAP handshake.
194    ///
195    /// TAP is an obsolete handshake based on RSA-1024 and DH-1024.
196    /// Relays respond to Create message with a Created reply on
197    /// success, or a Destroy message on failure.
198    ///
199    /// In Tor today, Create is only used for the deprecated v2 onion
200    /// service protocol.
201    Create, CREATE, TAP_C_HANDSHAKE_LEN
202}
203fixed_len_handshake! {
204    /// A Created message responds to a Created message, using the TAP
205    /// handshake.
206    ///
207    /// TAP is an obsolete handshake based on RSA-1024 and DH-1024.
208    Created, CREATED, TAP_S_HANDSHAKE_LEN
209}
210fixed_len_handshake! {
211    /// A CreateFast message creates a circuit using no public-key crypto.
212    ///
213    /// CreateFast is safe only when used on an already-secure TLS
214    /// connection.  It can only be used for the first hop of a circuit.
215    ///
216    /// Relays reply to a CreateFast message with CreatedFast on
217    /// success, or a Destroy message on failure.
218    ///
219    /// This handshake was originally used for the first hop of every
220    /// circuit.  Nowadays it is used for creating one-hop circuits
221    /// when we don't know any onion key for the first hop.
222    CreateFast, CREATE_FAST, FAST_C_HANDSHAKE_LEN
223}
224impl CreateFast {
225    /// Return the content of this handshake
226    pub fn handshake(&self) -> &[u8] {
227        &self.handshake
228    }
229}
230fixed_len_handshake! {
231    /// A CreatedFast message responds to a CreateFast message
232    ///
233    /// Relays send this message back to indicate that the CrateFast handshake
234    /// is complete.
235    CreatedFast, CREATED_FAST, FAST_S_HANDSHAKE_LEN
236}
237impl CreatedFast {
238    /// Consume this message and return the content of this handshake
239    pub fn into_handshake(self) -> Vec<u8> {
240        self.handshake
241    }
242}
243
244caret_int! {
245    /// Handshake type, corresponding to [`HTYPE` in
246    /// tor-spec](https://spec.torproject.org/tor-spec/create-created-cells.html).
247    #[derive(Deftly)]
248    #[derive_deftly(HasMemoryCost)]
249    pub struct HandshakeType(u16) {
250        /// [TAP](https://spec.torproject.org/tor-spec/create-created-cells.html#TAP) -- the original Tor handshake.
251        TAP = 0,
252
253        // 1 is reserved
254
255        /// [ntor](https://spec.torproject.org/tor-spec/create-created-cells.html#ntor) -- the ntor+curve25519+sha256 handshake.
256        NTOR = 2,
257        /// [ntor-v3](https://spec.torproject.org/tor-spec/create-created-cells.html#ntor-v3) -- ntor extended with extra data.
258        NTOR_V3 = 3,
259    }
260}
261
262/// A Create2 message create a circuit on the current channel.
263///
264/// To create a circuit, the client sends a Create2 cell containing a
265/// handshake of a given type; the relay responds with a Created2 cell
266/// containing a reply.
267///
268/// Currently, most Create2 cells contain a client-side instance of the
269/// "ntor" handshake.
270#[derive(Clone, Debug, Deftly)]
271#[derive_deftly(HasMemoryCost)]
272pub struct Create2 {
273    /// Identifier for what kind of handshake this is.
274    handshake_type: HandshakeType,
275    /// Body of the handshake.
276    handshake: Vec<u8>,
277}
278impl Body for Create2 {
279    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
280        w.write_u16(self.handshake_type.into());
281        let handshake_len = self
282            .handshake
283            .len()
284            .try_into()
285            .map_err(|_| EncodeError::BadLengthValue)?;
286        w.write_u16(handshake_len);
287        w.write_all(&self.handshake[..]);
288        Ok(())
289    }
290}
291impl Readable for Create2 {
292    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
293        let handshake_type = HandshakeType::from(b.take_u16()?);
294        let hlen = b.take_u16()?;
295        let handshake = b.take(hlen as usize)?.into();
296        Ok(Create2 {
297            handshake_type,
298            handshake,
299        })
300    }
301}
302impl Create2 {
303    /// Wrap a typed handshake as a Create2 message
304    pub fn new<B>(handshake_type: HandshakeType, handshake: B) -> Self
305    where
306        B: Into<Vec<u8>>,
307    {
308        let handshake = handshake.into();
309        Create2 {
310            handshake_type,
311            handshake,
312        }
313    }
314
315    /// Return the type of this handshake.
316    pub fn handshake_type(&self) -> HandshakeType {
317        self.handshake_type
318    }
319
320    /// Return the body of this handshake.
321    pub fn body(&self) -> &[u8] {
322        &self.handshake[..]
323    }
324}
325
326/// A Created2 message completes a circuit-creation handshake.
327///
328/// When a relay receives a valid Create2 message that it can handle, it
329/// establishes the circuit and replies with a Created2.
330#[derive(Clone, Debug, Deftly)]
331#[derive_deftly(HasMemoryCost)]
332pub struct Created2 {
333    /// Body of the handshake reply
334    handshake: Vec<u8>,
335}
336impl Created2 {
337    /// Create a new Created2 to hold a given handshake.
338    pub fn new<B>(handshake: B) -> Self
339    where
340        B: Into<Vec<u8>>,
341    {
342        let handshake = handshake.into();
343        Created2 { handshake }
344    }
345    /// Consume this created2 cell and return its body.
346    pub fn into_body(self) -> Vec<u8> {
347        self.handshake
348    }
349}
350impl Body for Created2 {
351    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
352        let handshake_len = self
353            .handshake
354            .len()
355            .try_into()
356            .map_err(|_| EncodeError::BadLengthValue)?;
357        w.write_u16(handshake_len);
358        w.write_all(&self.handshake[..]);
359        Ok(())
360    }
361}
362impl Readable for Created2 {
363    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
364        let hlen = b.take_u16()?;
365        let handshake = b.take(hlen as usize)?.into();
366        Ok(Created2 { handshake })
367    }
368}
369
370/// A Relay cell - that is, one transmitted over a circuit.
371///
372/// Once a circuit has been established, relay cells can be sent over
373/// it.  Clients can send relay cells to any relay on the circuit. Any
374/// relay on the circuit can send relay cells to the client, either
375/// directly (if it is the first hop), or indirectly through the
376/// intermediate hops.
377///
378/// A different protocol is defined over the relay cells; it is implemented
379/// in the [crate::relaycell] module.
380#[derive(Clone, Educe, derive_more::From, Deftly)]
381#[derive_deftly(HasMemoryCost)]
382#[educe(Debug)]
383pub struct Relay {
384    /// The contents of the relay cell as encoded for transfer.
385    ///
386    /// TODO(nickm): It's nice that this is boxed, since we don't want to copy
387    /// cell data all over the place. But unfortunately, there are some other
388    /// places where we _don't_ Box things that we should, and more copies than
389    /// necessary happen. We should refactor our data handling until we're mostly
390    /// moving around pointers rather than copying data;  see ticket #7.
391    #[educe(Debug(method = "skip_fmt"))]
392    body: BoxedCellBody,
393}
394impl Relay {
395    /// Construct a Relay message from a slice containing its contents.
396    pub fn new<P>(body: P) -> Self
397    where
398        P: AsRef<[u8]>,
399    {
400        let body = body.as_ref();
401        let mut r = [0_u8; CELL_DATA_LEN];
402        // TODO: This will panic if body is too long, but that would be a
403        // programming error anyway.
404        r[..body.len()].copy_from_slice(body);
405        Relay { body: Box::new(r) }
406    }
407    /// Construct a Relay message from its body.
408    pub fn from_raw(body: RawCellBody) -> Self {
409        Relay {
410            body: Box::new(body),
411        }
412    }
413    /// Consume this Relay message and return a BoxedCellBody for
414    /// encryption/decryption.
415    pub fn into_relay_body(self) -> BoxedCellBody {
416        self.body
417    }
418    /// Wrap this Relay message into a RelayMsg as a RELAY_EARLY cell.
419    pub fn into_early(self) -> AnyChanMsg {
420        AnyChanMsg::RelayEarly(RelayEarly(self))
421    }
422}
423impl Body for Relay {
424    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
425        w.write_all(&self.body[..]);
426        Ok(())
427    }
428}
429impl Readable for Relay {
430    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
431        let mut body = Box::new([0_u8; CELL_DATA_LEN]);
432        body.copy_from_slice(b.take(CELL_DATA_LEN)?);
433        Ok(Relay { body })
434    }
435}
436
437/// A Relay cell that is allowed to contain a CREATE message.
438///
439/// Only a limited number of these may be sent on each circuit.
440#[derive(Clone, Debug, derive_more::Deref, derive_more::From, derive_more::Into, Deftly)]
441#[derive_deftly(HasMemoryCost)]
442pub struct RelayEarly(Relay);
443impl Readable for RelayEarly {
444    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
445        Ok(RelayEarly(Relay::take_from(r)?))
446    }
447}
448impl Body for RelayEarly {
449    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
450        self.0.encode_onto(w)
451    }
452}
453impl RelayEarly {
454    /// Consume this RelayEarly message and return a BoxedCellBody for
455    /// encryption/decryption.
456    //
457    // (Since this method takes `self` by value, we can't take advantage of
458    // Deref.)
459    pub fn into_relay_body(self) -> BoxedCellBody {
460        self.0.body
461    }
462}
463
464/// The Destroy message tears down a circuit.
465///
466/// On receiving a Destroy message, a Tor implementation should
467/// tear down the associated circuit, and pass the destroy message
468/// down the circuit to later/earlier hops on the circuit (if any).
469#[derive(Clone, Debug, Deftly)]
470#[derive_deftly(HasMemoryCost)]
471pub struct Destroy {
472    /// Reason code given for tearing down this circuit
473    reason: DestroyReason,
474}
475impl Destroy {
476    /// Create a new destroy cell.
477    pub fn new(reason: DestroyReason) -> Self {
478        Destroy { reason }
479    }
480    /// Return the provided reason for destroying the circuit.
481    pub fn reason(&self) -> DestroyReason {
482        self.reason
483    }
484}
485impl Body for Destroy {
486    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
487        w.write_u8(self.reason.into());
488        Ok(())
489    }
490}
491impl Readable for Destroy {
492    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
493        let reason = r.take_u8()?.into();
494        Ok(Destroy { reason })
495    }
496}
497
498caret_int! {
499    /// Declared reason for ending a circuit.
500    #[derive(Deftly)]
501    #[derive_deftly(HasMemoryCost)]
502    pub struct DestroyReason(u8) {
503        /// No reason given.
504        ///
505        /// This is the only reason that clients send.
506        NONE = 0,
507        /// Protocol violation
508        PROTOCOL = 1,
509        /// Internal error.
510        INTERNAL = 2,
511        /// Client sent a TRUNCATE command.
512        REQUESTED = 3,
513        /// Relay is hibernating and not accepting requests
514        HIBERNATING = 4,
515        /// Ran out of memory, sockets, or circuit IDs
516        RESOURCELIMIT = 5,
517        /// Couldn't connect to relay.
518        CONNECTFAILED = 6,
519        /// Connected to a relay, but its OR identity wasn't as requested.
520        OR_IDENTITY = 7,
521        /// One of the OR channels carrying this circuit died.
522        CHANNEL_CLOSED = 8,
523        /// Circuit expired for being too dirty or old
524        FINISHED = 9,
525        /// Circuit construction took too long
526        TIMEOUT = 10,
527        /// Circuit was destroyed w/o client truncate (?)
528        DESTROYED = 11,
529        /// Request for unknown onion service
530        NOSUCHSERVICE = 12
531    }
532}
533
534impl DestroyReason {
535    /// Return a human-readable string for this reason.
536    pub fn human_str(&self) -> &'static str {
537        match *self {
538            DestroyReason::NONE => "No reason",
539            DestroyReason::PROTOCOL => "Protocol violation",
540            DestroyReason::INTERNAL => "Internal error",
541            DestroyReason::REQUESTED => "Client sent a TRUNCATE command",
542            DestroyReason::HIBERNATING => "Relay is hibernating and not accepting requests",
543            DestroyReason::RESOURCELIMIT => "Relay ran out of resources",
544            DestroyReason::CONNECTFAILED => "Couldn't connect to relay",
545            DestroyReason::OR_IDENTITY => "Connected to relay with different OR identity",
546            DestroyReason::CHANNEL_CLOSED => "The OR channels carrying this circuit died",
547            DestroyReason::FINISHED => "Circuit expired for being too dirty or old",
548            DestroyReason::TIMEOUT => "Circuit construction took too long",
549            DestroyReason::DESTROYED => "Circuit was destroyed without client truncate",
550            DestroyReason::NOSUCHSERVICE => "No such onion service",
551            _ => "Unrecognized reason",
552        }
553    }
554}
555
556/// The netinfo message ends channel negotiation.
557///
558/// It tells the other party on the channel our view of the current time,
559/// our own list of public addresses, and our view of its address.
560///
561/// When we get a netinfo cell, we can start creating circuits on a
562/// channel and sending data.
563#[derive(Clone, Debug, Deftly)]
564#[derive_deftly(HasMemoryCost)]
565pub struct Netinfo {
566    /// Time when this cell was sent, or 0 if this cell is sent by a client.
567    ///
568    /// TODO-SPEC(nickm): Y2038 issue here.  Better add a new handshake version
569    /// to solve it.  See
570    /// [torspec#80](https://gitlab.torproject.org/tpo/core/torspec/-/issues/80).
571    timestamp: u32,
572    /// Observed address for party that did not send the netinfo cell.
573    their_addr: Option<IpAddr>,
574    /// Canonical addresses for the party that did send the netinfo cell.
575    my_addr: Vec<IpAddr>,
576}
577/// helper: encode a single address in the form that netinfo messages expect
578fn enc_one_netinfo_addr<W: Writer + ?Sized>(w: &mut W, addr: &IpAddr) {
579    match addr {
580        IpAddr::V4(ipv4) => {
581            w.write_u8(0x04); // type.
582            w.write_u8(4); // length.
583            w.write_all(&ipv4.octets()[..]);
584        }
585        IpAddr::V6(ipv6) => {
586            w.write_u8(0x06); // type.
587            w.write_u8(16); // length.
588            w.write_all(&ipv6.octets()[..]);
589        }
590    }
591}
592/// helper: take an address as encoded in a netinfo message
593fn take_one_netinfo_addr(r: &mut Reader<'_>) -> Result<Option<IpAddr>> {
594    let atype = r.take_u8()?;
595    let alen = r.take_u8()?;
596    let abody = r.take(alen as usize)?;
597    match (atype, alen) {
598        (0x04, 4) => {
599            let bytes = [abody[0], abody[1], abody[2], abody[3]];
600            Ok(Some(IpAddr::V4(bytes.into())))
601        }
602        (0x06, 16) => {
603            // TODO(nickm) is there a better way?
604            let mut bytes = [0_u8; 16];
605            bytes.copy_from_slice(abody);
606            Ok(Some(IpAddr::V6(bytes.into())))
607        }
608        (_, _) => Ok(None),
609    }
610}
611impl Netinfo {
612    /// Construct a new Netinfo to be sent by a client.
613    pub fn from_client(their_addr: Option<IpAddr>) -> Self {
614        Netinfo {
615            timestamp: 0, // clients don't report their timestamps.
616            their_addr,
617            my_addr: Vec::new(), // clients don't report their addrs.
618        }
619    }
620    /// Construct a new Netinfo to be sent by a relay
621    pub fn from_relay<V>(timestamp: u32, their_addr: Option<IpAddr>, my_addrs: V) -> Self
622    where
623        V: Into<Vec<IpAddr>>,
624    {
625        let my_addr = my_addrs.into();
626        Netinfo {
627            timestamp,
628            their_addr,
629            my_addr,
630        }
631    }
632    /// Return the time reported in this NETINFO cell.
633    pub fn timestamp(&self) -> Option<std::time::SystemTime> {
634        use std::time::{Duration, SystemTime};
635        if self.timestamp == 0 {
636            None
637        } else {
638            Some(SystemTime::UNIX_EPOCH + Duration::from_secs(self.timestamp.into()))
639        }
640    }
641
642    /// Return a reference to the their address field.
643    ///
644    /// None is returned if their address is 0.0.0.0/:: (unspecified).
645    pub fn their_addr(&self) -> Option<&IpAddr> {
646        self.their_addr.as_ref()
647    }
648
649    /// Return a reference to the my address field.
650    pub fn my_addrs(&self) -> &[IpAddr] {
651        &self.my_addr
652    }
653}
654impl Body for Netinfo {
655    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
656        w.write_u32(self.timestamp);
657        let their_addr = self
658            .their_addr
659            .unwrap_or_else(|| Ipv4Addr::UNSPECIFIED.into());
660        enc_one_netinfo_addr(w, &their_addr);
661        let n_addrs: u8 = self
662            .my_addr
663            .len()
664            .try_into()
665            .map_err(|_| EncodeError::BadLengthValue)?;
666        w.write_u8(n_addrs);
667        for addr in &self.my_addr {
668            enc_one_netinfo_addr(w, addr);
669        }
670        Ok(())
671    }
672}
673impl Readable for Netinfo {
674    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
675        let timestamp = r.take_u32()?;
676        let their_addr = take_one_netinfo_addr(r)?.filter(|a| !a.is_unspecified());
677        let my_n_addrs = r.take_u8()?;
678        let mut my_addr = Vec::with_capacity(my_n_addrs as usize);
679        for _ in 0..my_n_addrs {
680            if let Some(a) = take_one_netinfo_addr(r)? {
681                my_addr.push(a);
682            }
683        }
684        Ok(Netinfo {
685            timestamp,
686            their_addr,
687            my_addr,
688        })
689    }
690}
691
692/// A Versions message begins channel negotiation.
693///
694/// Every channel must begin by sending a Versions message.  This message
695/// lists the link protocol versions that this Tor implementation supports.
696///
697/// Note that we should never actually send Versions cells using the
698/// usual channel cell encoding: Versions cells _always_ use two-byte
699/// circuit IDs, whereas all the other cell types use four-byte
700/// circuit IDs [assuming a non-obsolete version is negotiated].
701#[derive(Clone, Debug, Deftly)]
702#[derive_deftly(HasMemoryCost)]
703pub struct Versions {
704    /// List of supported link protocol versions
705    versions: Vec<u16>,
706}
707impl Versions {
708    /// Construct a new Versions message using a provided list of link
709    /// protocols.
710    ///
711    /// Returns an error if the list of versions is too long.
712    pub fn new<B>(vs: B) -> crate::Result<Self>
713    where
714        B: Into<Vec<u16>>,
715    {
716        let versions = vs.into();
717        if versions.len() < (u16::MAX / 2) as usize {
718            Ok(Self { versions })
719        } else {
720            Err(crate::Error::CantEncode("Too many versions"))
721        }
722    }
723    /// Encode this VERSIONS cell in the manner expected for a handshake.
724    ///
725    /// (That's different from a standard cell encoding, since we
726    /// have not negotiated versions yet, and so our circuit-ID length
727    /// is an obsolete 2 bytes).
728    pub fn encode_for_handshake(self) -> EncodeResult<Vec<u8>> {
729        let mut v = Vec::new();
730        v.write_u16(0); // obsolete circuit ID length.
731        v.write_u8(ChanCmd::VERSIONS.into());
732        v.write_u16((self.versions.len() * 2) as u16); // message length.
733        self.encode_onto(&mut v)?;
734        Ok(v)
735    }
736    /// Return the best (numerically highest) link protocol that is
737    /// shared by this versions cell and my_protos.
738    pub fn best_shared_link_protocol(&self, my_protos: &[u16]) -> Option<u16> {
739        // NOTE: this implementation is quadratic, but it shouldn't matter
740        // much so long as my_protos is small.
741        let p = my_protos
742            .iter()
743            .filter(|p| self.versions.contains(p))
744            .fold(0_u16, |a, b| u16::max(a, *b));
745        if p == 0 { None } else { Some(p) }
746    }
747}
748impl Body for Versions {
749    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
750        for v in &self.versions {
751            w.write_u16(*v);
752        }
753        Ok(())
754    }
755}
756impl Readable for Versions {
757    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
758        let mut versions = Vec::new();
759        while r.remaining() > 0 {
760            versions.push(r.take_u16()?);
761        }
762        Ok(Versions { versions })
763    }
764}
765
766caret_int! {
767    /// A ChanCmd is the type of a channel cell.  The value of the ChanCmd
768    /// indicates the meaning of the cell, and (possibly) its length.
769    #[derive(Deftly)]
770    #[derive_deftly(HasMemoryCost)]
771    pub struct PaddingNegotiateCmd(u8) {
772        /// Start padding
773        START = 2,
774
775        /// Stop padding
776        STOP = 1,
777    }
778}
779
780/// A PaddingNegotiate message is used to negotiate channel padding.
781///
782/// Sent by a client to its guard node,
783/// to instruct the relay to enable/disable channel padding.
784/// (Not relevant for channels used only for directory lookups,
785/// nor inter-relay channels.)
786/// See `padding-spec.txt`, section 2.2.
787///
788/// This message is constructed in the channel manager and transmitted by the reactor.
789///
790/// The `Default` impl is the same as [`start_default()`](PaddingNegotiate::start_default`)
791#[derive(Clone, Debug, Eq, PartialEq, Deftly)]
792#[derive_deftly(HasMemoryCost)]
793pub struct PaddingNegotiate {
794    /// Whether to start or stop padding
795    command: PaddingNegotiateCmd,
796    /// Suggested lower-bound value for inter-packet timeout in msec.
797    // TODO(nickm) is that right?
798    ito_low_ms: u16,
799    /// Suggested upper-bound value for inter-packet timeout in msec.
800    // TODO(nickm) is that right?
801    ito_high_ms: u16,
802}
803impl PaddingNegotiate {
804    /// Create a new PADDING_NEGOTIATE START message requesting consensus timing parameters.
805    ///
806    /// This message restores the state to the one which exists at channel startup.
807    pub fn start_default() -> Self {
808        // Tor Spec section 7.3, padding-spec section 2.5.
809        Self {
810            command: PaddingNegotiateCmd::START,
811            ito_low_ms: 0,
812            ito_high_ms: 0,
813        }
814    }
815
816    /// Create a new PADDING_NEGOTIATE START message.
817    pub fn start(ito_low: IntegerMilliseconds<u16>, ito_high: IntegerMilliseconds<u16>) -> Self {
818        // Tor Spec section 7.3
819        Self {
820            command: PaddingNegotiateCmd::START,
821            ito_low_ms: ito_low.as_millis(),
822            ito_high_ms: ito_high.as_millis(),
823        }
824    }
825
826    /// Create a new PADDING_NEGOTIATE STOP message.
827    pub fn stop() -> Self {
828        // Tor Spec section 7.3
829        Self {
830            command: PaddingNegotiateCmd::STOP,
831            ito_low_ms: 0,
832            ito_high_ms: 0,
833        }
834    }
835
836    /// Construct from the three fields: command, low_ms, high_ms, as a tuple
837    ///
838    /// For testing only
839    #[cfg(feature = "testing")]
840    pub fn from_raw(command: PaddingNegotiateCmd, ito_low_ms: u16, ito_high_ms: u16) -> Self {
841        PaddingNegotiate {
842            command,
843            ito_low_ms,
844            ito_high_ms,
845        }
846    }
847}
848impl Default for PaddingNegotiate {
849    fn default() -> Self {
850        Self::start_default()
851    }
852}
853
854impl Body for PaddingNegotiate {
855    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
856        w.write_u8(0); // version
857        w.write_u8(self.command.get());
858        w.write_u16(self.ito_low_ms);
859        w.write_u16(self.ito_high_ms);
860        Ok(())
861    }
862}
863impl Readable for PaddingNegotiate {
864    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
865        let v = r.take_u8()?;
866        if v != 0 {
867            return Err(Error::InvalidMessage(
868                "Unrecognized padding negotiation version".into(),
869            ));
870        }
871        let command = r.take_u8()?.into();
872        let ito_low_ms = r.take_u16()?;
873        let ito_high_ms = r.take_u16()?;
874        Ok(PaddingNegotiate {
875            command,
876            ito_low_ms,
877            ito_high_ms,
878        })
879    }
880}
881
882/// A single certificate in a Certs cell.
883///
884/// The formats used here are implemented in tor-cert. Ed25519Cert is the
885/// most common.
886#[derive(Clone, Debug, Deftly)]
887#[derive_deftly(HasMemoryCost)]
888struct TorCert {
889    /// Type code for this certificate.
890    certtype: u8,
891    /// Encoded certificate
892    cert: Vec<u8>,
893}
894/// encode a single TorCert `c` onto a Writer `w`.
895fn enc_one_tor_cert<W: Writer + ?Sized>(w: &mut W, c: &TorCert) -> EncodeResult<()> {
896    w.write_u8(c.certtype);
897    let cert_len: u16 = c
898        .cert
899        .len()
900        .try_into()
901        .map_err(|_| EncodeError::BadLengthValue)?;
902    w.write_u16(cert_len);
903    w.write_all(&c.cert[..]);
904    Ok(())
905}
906/// Try to extract a TorCert from the reader `r`.
907fn take_one_tor_cert(r: &mut Reader<'_>) -> Result<TorCert> {
908    let certtype = r.take_u8()?;
909    let certlen = r.take_u16()?;
910    let cert = r.take(certlen as usize)?;
911    Ok(TorCert {
912        certtype,
913        cert: cert.into(),
914    })
915}
916/// A Certs message is used as part of the channel handshake to send
917/// additional certificates.
918///
919/// These certificates are not presented as part of the TLS handshake.
920/// Originally this was meant to make Tor TLS handshakes look "normal", but
921/// nowadays it serves less purpose, especially now that we have TLS 1.3.
922///
923/// Every relay sends this message as part of channel negotiation;
924/// clients do not send them.
925#[derive(Clone, Debug, Deftly)]
926#[derive_deftly(HasMemoryCost)]
927pub struct Certs {
928    /// The certificates in this cell
929    certs: Vec<TorCert>,
930}
931impl Certs {
932    /// Return a new empty certs cell.
933    pub fn new_empty() -> Self {
934        Certs { certs: Vec::new() }
935    }
936    /// Add a new encoded certificate to this cell.
937    ///
938    /// Does not check anything about the well-formedness of the certificate.
939    pub fn push_cert_body<B>(&mut self, certtype: tor_cert::CertType, cert: B)
940    where
941        B: Into<Vec<u8>>,
942    {
943        let certtype = certtype.into();
944        let cert = cert.into();
945        self.certs.push(TorCert { certtype, cert });
946    }
947
948    /// Return the body of the certificate tagged with 'tp', if any.
949    pub fn cert_body(&self, tp: tor_cert::CertType) -> Option<&[u8]> {
950        let tp: u8 = tp.into();
951        self.certs
952            .iter()
953            .find(|c| c.certtype == tp)
954            .map(|c| &c.cert[..])
955    }
956
957    /// Look for a certificate of type 'tp' in this cell; return it if
958    /// there is one.
959    pub fn parse_ed_cert(&self, tp: tor_cert::CertType) -> crate::Result<tor_cert::KeyUnknownCert> {
960        let body = self
961            .cert_body(tp)
962            .ok_or_else(|| crate::Error::ChanProto(format!("Missing {} certificate", tp)))?;
963
964        let cert = tor_cert::Ed25519Cert::decode(body).map_err(|be| crate::Error::BytesErr {
965            err: be,
966            parsed: "ed25519 certificate",
967        })?;
968        if cert.peek_cert_type() != tp {
969            return Err(crate::Error::ChanProto(format!(
970                "Found a {} certificate labeled as {}",
971                cert.peek_cert_type(),
972                tp
973            )));
974        }
975
976        Ok(cert)
977    }
978}
979
980impl Body for Certs {
981    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
982        let n_certs: u8 = self
983            .certs
984            .len()
985            .try_into()
986            .map_err(|_| EncodeError::BadLengthValue)?;
987        w.write_u8(n_certs);
988        for c in &self.certs {
989            enc_one_tor_cert(w, c)?;
990        }
991        Ok(())
992    }
993}
994impl Readable for Certs {
995    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
996        let n = r.take_u8()?;
997        let mut certs = Vec::new();
998        for _ in 0..n {
999            certs.push(take_one_tor_cert(r)?);
1000        }
1001        Ok(Certs { certs })
1002    }
1003}
1004
1005/// Length of the body for an authentication challenge
1006const CHALLENGE_LEN: usize = 32;
1007
1008/// An AuthChallenge message is part of negotiation, sent by
1009/// responders to initiators.
1010///
1011/// The AuthChallenge cell is used to ensure that some unpredictable material
1012/// has been sent on the channel, and to tell the initiator what
1013/// authentication methods will be accepted.
1014///
1015/// Clients can safely ignore this message: they don't need to authenticate.
1016#[derive(Clone, Debug, Deftly)]
1017#[derive_deftly(HasMemoryCost)]
1018pub struct AuthChallenge {
1019    /// Random challenge to be used in generating response
1020    challenge: [u8; CHALLENGE_LEN],
1021    /// List of permitted authentication methods
1022    methods: Vec<u16>,
1023}
1024impl AuthChallenge {
1025    /// Construct a new AuthChallenge cell with a given challenge
1026    /// value (chosen randomly) and a set of acceptable authentication methods.
1027    pub fn new<B, M>(challenge: B, methods: M) -> Self
1028    where
1029        B: Into<[u8; CHALLENGE_LEN]>,
1030        M: Into<Vec<u16>>,
1031    {
1032        AuthChallenge {
1033            challenge: challenge.into(),
1034            methods: methods.into(),
1035        }
1036    }
1037
1038    /// Return a reference to the list of methods.
1039    pub fn methods(&self) -> &[u16] {
1040        &self.methods
1041    }
1042}
1043
1044impl Body for AuthChallenge {
1045    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1046        w.write_all(&self.challenge[..]);
1047        let n_methods = self
1048            .methods
1049            .len()
1050            .try_into()
1051            .map_err(|_| EncodeError::BadLengthValue)?;
1052        w.write_u16(n_methods);
1053        for m in self.methods {
1054            w.write_u16(m);
1055        }
1056        Ok(())
1057    }
1058}
1059impl Readable for AuthChallenge {
1060    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
1061        //let challenge = r.take(CHALLENGE_LEN)?.into();
1062        let challenge = r.extract()?;
1063        let n_methods = r.take_u16()?;
1064        let mut methods = Vec::new();
1065        for _ in 0..n_methods {
1066            methods.push(r.take_u16()?);
1067        }
1068        Ok(AuthChallenge { challenge, methods })
1069    }
1070}
1071
1072/// Part of negotiation: sent by initiators to responders.
1073///
1074/// The Authenticate cell proves the initiator's identity to the
1075/// responder, even if TLS client authentication was not used.
1076///
1077/// Clients do not use this.
1078#[derive(Clone, Debug, Deftly, Eq, PartialEq)]
1079#[derive_deftly(HasMemoryCost)]
1080pub struct Authenticate {
1081    /// Authentication method in use
1082    authtype: u16,
1083    /// Encoded authentication object
1084    auth: Vec<u8>,
1085}
1086impl Authenticate {
1087    /// Create a new Authenticate message from a given type and body.
1088    pub fn new<B>(authtype: u16, body: B) -> Self
1089    where
1090        B: Into<Vec<u8>>,
1091    {
1092        Authenticate {
1093            authtype,
1094            auth: body.into(),
1095        }
1096    }
1097}
1098impl Body for Authenticate {
1099    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1100        w.write_u16(self.authtype);
1101        let authlen = self
1102            .auth
1103            .len()
1104            .try_into()
1105            .map_err(|_| EncodeError::BadLengthValue)?;
1106        w.write_u16(authlen);
1107        w.write_all(&self.auth[..]);
1108        Ok(())
1109    }
1110}
1111impl Readable for Authenticate {
1112    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
1113        let authtype = r.take_u16()?;
1114        let authlen = r.take_u16()?;
1115        let auth = r.take(authlen as usize)?.into();
1116        Ok(Authenticate { authtype, auth })
1117    }
1118}
1119
1120/// Holds any message whose command we don't recognize.
1121///
1122/// Well-behaved Tor implementations are required to ignore commands
1123/// like this.
1124///
1125/// TODO: I believe that this is not a risky case of Postel's law,
1126/// since it is only for channels, but we should be careful here.
1127#[derive(Clone, Debug, Deftly)]
1128#[derive_deftly(HasMemoryCost)]
1129pub struct Unrecognized {
1130    /// The channel command that we got with this cell
1131    cmd: ChanCmd,
1132    /// The contents of the cell
1133    content: Vec<u8>,
1134}
1135impl Unrecognized {
1136    /// Construct a new cell of arbitrary or unrecognized type.
1137    pub fn new<B>(cmd: ChanCmd, content: B) -> Self
1138    where
1139        B: Into<Vec<u8>>,
1140    {
1141        let content = content.into();
1142        Unrecognized { cmd, content }
1143    }
1144    /// Return the command from this cell.
1145    pub fn cmd(&self) -> ChanCmd {
1146        self.cmd
1147    }
1148    /// Take an unrecognized cell's body from a reader `r`, and apply
1149    /// the given command to it.
1150    pub fn decode_with_cmd(cmd: ChanCmd, r: &mut Reader<'_>) -> Result<Unrecognized> {
1151        let mut u = Unrecognized::take_from(r)?;
1152        u.cmd = cmd;
1153        Ok(u)
1154    }
1155}
1156impl Body for Unrecognized {
1157    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1158        w.write_all(&self.content[..]);
1159        Ok(())
1160    }
1161}
1162impl Readable for Unrecognized {
1163    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
1164        Ok(Unrecognized {
1165            cmd: 0.into(),
1166            content: r.take(r.remaining())?.into(),
1167        })
1168    }
1169}
1170
1171/// Helper: declare a From<> implementation from message types for
1172/// cells that don't take a circid.
1173macro_rules! msg_into_cell {
1174    ($body:ident) => {
1175        impl From<$body> for super::AnyChanCell {
1176            fn from(body: $body) -> super::AnyChanCell {
1177                super::AnyChanCell {
1178                    circid: None,
1179                    msg: body.into(),
1180                }
1181            }
1182        }
1183    };
1184}
1185
1186msg_into_cell!(Padding);
1187msg_into_cell!(Vpadding);
1188msg_into_cell!(Netinfo);
1189msg_into_cell!(Versions);
1190msg_into_cell!(PaddingNegotiate);
1191msg_into_cell!(Certs);
1192msg_into_cell!(AuthChallenge);
1193msg_into_cell!(Authenticate);
1194
1195/// Helper: declare a ChanMsg implementation for a message type that has a
1196/// fixed command.
1197//
1198// TODO: It might be better to merge Body with ChanMsg, but that is complex,
1199// since their needs are _slightly_ different.
1200//
1201// TODO: If we *do* make the change above, then perhaps we should also implement
1202// our restricted enums in terms of this, so that there is only one instance of
1203// [<$body:snake:upper>]
1204macro_rules! msg_impl_chanmsg {
1205    ($($body:ident,)*) =>
1206    {paste::paste!{
1207       $(impl crate::chancell::ChanMsg for $body {
1208            fn cmd(&self) -> crate::chancell::ChanCmd { crate::chancell::ChanCmd::[< $body:snake:upper >] }
1209            fn encode_onto<W: tor_bytes::Writer + ?Sized>(self, w: &mut W) -> tor_bytes::EncodeResult<()> {
1210                crate::chancell::msg::Body::encode_onto(self, w)
1211            }
1212            fn decode_from_reader(cmd: ChanCmd, r: &mut tor_bytes::Reader<'_>) -> tor_bytes::Result<Self> {
1213                if cmd != crate::chancell::ChanCmd::[< $body:snake:upper >] {
1214                    return Err(tor_bytes::Error::InvalidMessage(
1215                        format!("Expected {} command; got {cmd}", stringify!([< $body:snake:upper >])).into()
1216                    ));
1217                }
1218                crate::chancell::msg::Body::decode_from_reader(r)
1219            }
1220        })*
1221    }}
1222}
1223
1224// We implement ChanMsg for every body type, so that you can write code that does
1225// e.g. ChanCell<Relay>.
1226msg_impl_chanmsg!(
1227    Padding,
1228    Vpadding,
1229    Create,
1230    CreateFast,
1231    Create2,
1232    Created,
1233    CreatedFast,
1234    Created2,
1235    Relay,
1236    RelayEarly,
1237    Destroy,
1238    Netinfo,
1239    Versions,
1240    PaddingNegotiate,
1241    Certs,
1242    AuthChallenge,
1243    Authenticate,
1244);
1245
1246#[cfg(test)]
1247mod test {
1248    // @@ begin test lint list maintained by maint/add_warning @@
1249    #![allow(clippy::bool_assert_comparison)]
1250    #![allow(clippy::clone_on_copy)]
1251    #![allow(clippy::dbg_macro)]
1252    #![allow(clippy::mixed_attributes_style)]
1253    #![allow(clippy::print_stderr)]
1254    #![allow(clippy::print_stdout)]
1255    #![allow(clippy::single_char_pattern)]
1256    #![allow(clippy::unwrap_used)]
1257    #![allow(clippy::unchecked_time_subtraction)]
1258    #![allow(clippy::useless_vec)]
1259    #![allow(clippy::needless_pass_by_value)]
1260    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
1261    use super::*;
1262    #[test]
1263    fn destroy_reason() {
1264        let r1 = DestroyReason::CONNECTFAILED;
1265
1266        assert_eq!(r1.human_str(), "Couldn't connect to relay");
1267
1268        let r2 = DestroyReason::from(200); // not a specified number.
1269        assert_eq!(r2.human_str(), "Unrecognized reason");
1270    }
1271}