1
//! Messages sent over Tor channels
2
//!
3
//! A 'channel' is a direct connection between a tor client and a
4
//! relay, or between two relays.  Current channels all use TLS.
5
//!
6
//! This module implements the [ChanCell] type, which is the encoding for
7
//! data sent over a channel.  It also encodes and decodes various
8
//! channel messages, which are the types of data conveyed over a
9
//! channel.
10
pub mod codec;
11
pub mod msg;
12
use std::num::NonZeroU32;
13

            
14
use caret::caret_int;
15

            
16
/// The amount of data sent in a fixed-length cell.
17
///
18
/// Historically, this was set at 509 bytes so that cells would be
19
/// 512 bytes long once commands and circuit IDs were added.  But since
20
/// protocol version 4, circuit IDs are 2 bytes longer, so cells are
21
/// now 514 bytes.
22
pub const CELL_DATA_LEN: usize = 509;
23

            
24
/// A cell body considered as a raw array of bytes
25
pub type RawCellBody = [u8; CELL_DATA_LEN];
26

            
27
/// A [`RawCellBody`] stored on the heap.
28
///
29
/// We use this often to avoid copying cell bodies around.
30
pub type BoxedCellBody = Box<RawCellBody>;
31

            
32
/// Channel-local identifier for a circuit.
33
///
34
/// A circuit ID can be 2 or 4 bytes long; since version 4 of the Tor
35
/// protocol, it's 4 bytes long.
36
///
37
/// Cannot be zero. For an "optional" circuit ID, use `Option<CircId>`.
38
40334
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
39
pub struct CircId(NonZeroU32);
40

            
41
impl From<NonZeroU32> for CircId {
42
    fn from(item: NonZeroU32) -> Self {
43
        Self(item)
44
    }
45
}
46
impl From<CircId> for u32 {
47
18048
    fn from(id: CircId) -> u32 {
48
18048
        id.0.get()
49
18048
    }
50
}
51
impl std::fmt::Display for CircId {
52
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
53
        self.0.fmt(f)
54
    }
55
}
56
impl CircId {
57
    /// Creates a `CircId` for non-zero `val`.
58
    ///
59
    /// Returns `None` when `val` is zero. Messages with a zero/None circuit ID
60
    /// apply to the channel as a whole.
61
141857
    pub fn new(val: u32) -> Option<Self> {
62
141857
        NonZeroU32::new(val).map(Self)
63
141857
    }
64

            
65
    /// Convenience function to convert to a `u32`; `None` is mapped to 0.
66
1245
    pub fn get_or_zero(circ_id: Option<Self>) -> u32 {
67
1245
        match circ_id {
68
780
            Some(circ_id) => circ_id.0.get(),
69
465
            None => 0,
70
        }
71
1245
    }
72
}
73

            
74
caret_int! {
75
    /// A ChanCmd is the type of a channel cell.  The value of the ChanCmd
76
    /// indicates the meaning of the cell, and (possibly) its length.
77
    pub struct ChanCmd(u8) {
78
        /// A fixed-length cell that will be dropped.
79
        PADDING = 0,
80
        /// Create a new circuit (obsolete format)
81
        CREATE = 1,
82
        /// Finish circuit-creation handshake (obsolete format)
83
        CREATED = 2,
84
        /// Relay cell, transmitted over a circuit.
85
        RELAY = 3,
86
        /// Destroy a circuit
87
        DESTROY = 4,
88
        /// Create a new circuit (no public-key)
89
        CREATE_FAST = 5,
90
        /// Finish a circuit-creation handshake (no public-key)
91
        CREATED_FAST = 6,
92
        // note gap in numbering: 7 is grouped with the variable-length cells
93
        /// Finish a channel handshake with time and address information
94
        NETINFO = 8,
95
        /// Relay cell, transmitted over a circuit.  Limited.
96
        RELAY_EARLY = 9,
97
        /// Create a new circuit (current format)
98
        CREATE2 = 10,
99
        /// Finish a circuit-creation handshake (current format)
100
        CREATED2 = 11,
101
        /// Adjust channel-padding settings
102
        PADDING_NEGOTIATE = 12,
103

            
104
        /// Variable-length cell, despite its number: negotiate versions
105
        VERSIONS = 7,
106
        /// Variable-length channel-padding cell
107
        VPADDING = 128,
108
        /// Provide additional certificates beyond those given in the TLS
109
        /// handshake
110
        CERTS = 129,
111
        /// Challenge material used in relay-to-relay handshake.
112
        AUTH_CHALLENGE = 130,
113
        /// Response material used in relay-to-relay handshake.
114
        AUTHENTICATE = 131,
115
        /// Indicates client permission to use relay.  Not currently used.
116
        AUTHORIZE = 132,
117
    }
118
}
119

            
120
/// Possible requirements on circuit IDs for a channel command.
121
enum CircIdReq {
122
    /// indicates a command that only takes a zero-valued circuit ID
123
    WantNone,
124
    /// indicates a command that only takes a nonzero-valued circuit ID
125
    WantSome,
126
    /// indicates a command that can take any circuit ID
127
    Any,
128
}
129

            
130
impl ChanCmd {
131
    /// Return true if this command is for a cell using the the
132
    /// variable-length format.
133
4718
    pub fn is_var_cell(self) -> bool {
134
4718
        // Version 1 of the channel protocol had no variable-length
135
4718
        // cells, but that's obsolete.  In version 2, only the VERSIONS
136
4718
        // cell was variable-length.  Since version 3, all cells having
137
4718
        // a command value >= 128 are variable-length.
138
4718
        self == ChanCmd::VERSIONS || self.0 >= 128_u8
139
4718
    }
140
    /// Return what kind of circuit ID this command expects.
141
2773
    fn allows_circid(self) -> CircIdReq {
142
2773
        match self {
143
            ChanCmd::PADDING
144
            | ChanCmd::NETINFO
145
            | ChanCmd::PADDING_NEGOTIATE
146
            | ChanCmd::VERSIONS
147
            | ChanCmd::VPADDING
148
            | ChanCmd::CERTS
149
            | ChanCmd::AUTH_CHALLENGE
150
1442
            | ChanCmd::AUTHENTICATE => CircIdReq::WantNone,
151
            ChanCmd::CREATE
152
            | ChanCmd::CREATED
153
            | ChanCmd::RELAY
154
            | ChanCmd::DESTROY
155
            | ChanCmd::CREATE_FAST
156
            | ChanCmd::CREATED_FAST
157
            | ChanCmd::RELAY_EARLY
158
            | ChanCmd::CREATE2
159
1237
            | ChanCmd::CREATED2 => CircIdReq::WantSome,
160
94
            _ => CircIdReq::Any,
161
        }
162
2773
    }
163
    /// Return true if this command is one that accepts the particular
164
    /// circuit ID `id`.
165
2773
    pub fn accepts_circid_val(self, id: Option<CircId>) -> bool {
166
2773
        match self.allows_circid() {
167
1442
            CircIdReq::WantNone => id.is_none(),
168
1237
            CircIdReq::WantSome => id.is_some(),
169
94
            CircIdReq::Any => true,
170
        }
171
2773
    }
172
}
173

            
174
/// A decoded and parsed channel cell of unrestricted type.
175
pub type AnyChanCell = ChanCell<msg::AnyChanMsg>;
176

            
177
/// Trait implemented by anything that can serve as a channel message.
178
///
179
/// Typically, this will be [`AnyChanMsg`](msg::AnyChanMsg) (to represent an unrestricted relay
180
/// message), or some restricted subset of those messages.
181
pub trait ChanMsg {
182
    /// Return the [`ChanCmd`] for this message.
183
    fn cmd(&self) -> ChanCmd;
184
    /// Write the body of this message (not including length or command).
185
    fn encode_onto<W: tor_bytes::Writer + ?Sized>(self, w: &mut W) -> tor_bytes::EncodeResult<()>;
186
    /// Decode this message from a given reader, according to a specified
187
    /// command value. The reader must be truncated to the exact length
188
    /// of the body.
189
    fn decode_from_reader(cmd: ChanCmd, r: &mut tor_bytes::Reader<'_>) -> tor_bytes::Result<Self>
190
    where
191
        Self: Sized;
192
}
193

            
194
/// A decoded channel cell, to be sent or received on a channel.
195
24
#[derive(Debug)]
196
pub struct ChanCell<M> {
197
    /// Circuit ID associated with this cell, if any.
198
    circid: Option<CircId>,
199
    /// Underlying message in this cell
200
    msg: M,
201
}
202

            
203
impl<M: ChanMsg> ChanCell<M> {
204
    /// Construct a new channel cell.
205
5705
    pub fn new(circid: Option<CircId>, msg: M) -> Self {
206
5705
        ChanCell { circid, msg }
207
5705
    }
208
    /// Return the circuit ID for this cell.
209
60
    pub fn circid(&self) -> Option<CircId> {
210
60
        self.circid
211
60
    }
212
    /// Return a reference to the underlying message of this cell.
213
10688
    pub fn msg(&self) -> &M {
214
10688
        &self.msg
215
10688
    }
216
    /// Consume this cell and return its components.
217
5525
    pub fn into_circid_and_msg(self) -> (Option<CircId>, M) {
218
5525
        (self.circid, self.msg)
219
5525
    }
220
}