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
use derive_deftly::Deftly;
16
use tor_memquota::{derive_deftly_template_HasMemoryCost, HasMemoryCostStructural};
17

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

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

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

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

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

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

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

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

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

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

            
178
/// A decoded and parsed channel cell of unrestricted type.
179
pub type AnyChanCell = ChanCell<msg::AnyChanMsg>;
180

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

            
198
/// A decoded channel cell, to be sent or received on a channel.
199
#[derive(Debug, Deftly)]
200
#[derive_deftly(HasMemoryCost)]
201
#[deftly(has_memory_cost(bounds = "M: HasMemoryCostStructural"))]
202
pub struct ChanCell<M> {
203
    /// Circuit ID associated with this cell, if any.
204
    #[deftly(has_memory_cost(copy))]
205
    circid: Option<CircId>,
206
    /// Underlying message in this cell
207
    msg: M,
208
}
209

            
210
impl<M: ChanMsg> ChanCell<M> {
211
    /// Construct a new channel cell.
212
3294
    pub fn new(circid: Option<CircId>, msg: M) -> Self {
213
3294
        ChanCell { circid, msg }
214
3294
    }
215
    /// Return the circuit ID for this cell.
216
140
    pub fn circid(&self) -> Option<CircId> {
217
140
        self.circid
218
140
    }
219
    /// Return a reference to the underlying message of this cell.
220
5998
    pub fn msg(&self) -> &M {
221
5998
        &self.msg
222
5998
    }
223
    /// Consume this cell and return its components.
224
2996
    pub fn into_circid_and_msg(self) -> (Option<CircId>, M) {
225
2996
        (self.circid, self.msg)
226
2996
    }
227
}