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 caret::caret_int;
13

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

            
21
/// A cell body considered as a raw array of bytes
22
pub type RawCellBody = [u8; CELL_DATA_LEN];
23

            
24
/// Channel-local identifier for a circuit.
25
///
26
/// A circuit ID can be 2 or 4 bytes long; on modern versions of the Tor
27
/// protocol, it's 4 bytes long.
28
19251
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
29
pub struct CircId(u32);
30

            
31
impl From<u32> for CircId {
32
65692
    fn from(item: u32) -> Self {
33
65692
        Self(item)
34
65692
    }
35
}
36
impl From<CircId> for u32 {
37
8800
    fn from(id: CircId) -> u32 {
38
8800
        id.0
39
8800
    }
40
}
41
impl std::fmt::Display for CircId {
42
44
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
43
44
        self.0.fmt(f)
44
44
    }
45
}
46
impl CircId {
47
    /// Return true if this is the zero CircId.
48
    ///
49
    /// A zero-valid circuit ID denotes a cell that is not related to
50
    /// any particular circuit, but which applies to the channel as a whole.
51
726
    pub fn is_zero(&self) -> bool {
52
726
        self.0 == 0
53
726
    }
54
}
55

            
56
caret_int! {
57
    /// A ChanCmd is the type of a channel cell.  The value of the ChanCmd
58
    /// indicates the meaning of the cell, and (possibly) its length.
59
    pub struct ChanCmd(u8) {
60
        /// A fixed-length cell that will be dropped.
61
        PADDING = 0,
62
        /// Create a new circuit (obsolete format)
63
        CREATE = 1,
64
        /// Finish circuit-creation handshake (obsolete format)
65
        CREATED = 2,
66
        /// Relay cell, transmitted over a circuit.
67
        RELAY = 3,
68
        /// Destroy a circuit
69
        DESTROY = 4,
70
        /// Create a new circuit (no public-key)
71
        CREATE_FAST = 5,
72
        /// Finish a circuit-creation handshake (no public-key)
73
        CREATED_FAST = 6,
74
        // note gap in numbering: 7 is grouped with the variable-length cells
75
        /// Finish a channel handshake with time and address information
76
        NETINFO = 8,
77
        /// Relay cell, transmitted over a circuit.  Limited.
78
        RELAY_EARLY = 9,
79
        /// Create a new circuit (current format)
80
        CREATE2 = 10,
81
        /// Finish a circuit-creation handshake (current format)
82
        CREATED2 = 11,
83
        /// Adjust channel-padding settings
84
        PADDING_NEGOTIATE = 12,
85

            
86
        /// Variable-length cell, despite its number: negotiate versions
87
        VERSIONS = 7,
88
        /// Variable-length channel-padding cell
89
        VPADDING = 128,
90
        /// Provide additional certificates beyond those given in the TLS
91
        /// handshake
92
        CERTS = 129,
93
        /// Challenge material used in relay-to-relay handshake.
94
        AUTH_CHALLENGE = 130,
95
        /// Response material used in relay-to-relay handshake.
96
        AUTHENTICATE = 131,
97
        /// Indicates client permission to use relay.  Not currently used.
98
        AUTHORIZE = 132,
99
    }
100
}
101

            
102
/// Possible requirements on circuit IDs for a channel command.
103
enum CircIdReq {
104
    /// indicates a command that only takes a zero-valued circuit ID
105
    WantZero,
106
    /// indicates a command that only takes a nonzero-valued circuit ID
107
    WantNonZero,
108
    /// indicates a command that can take any circuit ID
109
    Any,
110
}
111

            
112
impl ChanCmd {
113
    /// Return true if this command is for a cell using the the
114
    /// variable-length format.
115
1408
    pub fn is_var_cell(self) -> bool {
116
1408
        // Version 1 of the channel protocol had no variable-length
117
1408
        // cells, but that's obsolete.  In version 2, only the VERSIONS
118
1408
        // cell was variable-length.
119
1408
        self == ChanCmd::VERSIONS || self.0 >= 128_u8
120
1408
    }
121
    /// Return what kind of circuit ID this command expects.
122
726
    fn allows_circid(self) -> CircIdReq {
123
726
        match self {
124
            ChanCmd::PADDING
125
            | ChanCmd::NETINFO
126
            | ChanCmd::PADDING_NEGOTIATE
127
            | ChanCmd::VERSIONS
128
            | ChanCmd::VPADDING
129
            | ChanCmd::CERTS
130
            | ChanCmd::AUTH_CHALLENGE
131
484
            | ChanCmd::AUTHENTICATE => CircIdReq::WantZero,
132
            ChanCmd::CREATE
133
            | ChanCmd::CREATED
134
            | ChanCmd::RELAY
135
            | ChanCmd::DESTROY
136
            | ChanCmd::CREATE_FAST
137
            | ChanCmd::CREATED_FAST
138
            | ChanCmd::RELAY_EARLY
139
            | ChanCmd::CREATE2
140
198
            | ChanCmd::CREATED2 => CircIdReq::WantNonZero,
141
44
            _ => CircIdReq::Any,
142
        }
143
726
    }
144
    /// Return true if this command is one that accepts the particular
145
    /// circuit ID `id`.
146
726
    pub fn accepts_circid_val(self, id: CircId) -> bool {
147
726
        match (self.allows_circid(), id.is_zero()) {
148
22
            (CircIdReq::WantNonZero, true) => false,
149
22
            (CircIdReq::WantZero, false) => false,
150
682
            (_, _) => true,
151
        }
152
726
    }
153
}
154

            
155
/// A decoded channel cell, to be sent or received on a channel.
156
264
#[derive(Debug)]
157
pub struct ChanCell {
158
    /// Circuit ID associated with this cell
159
    circid: CircId,
160
    /// Underlying message in this cell
161
    msg: msg::ChanMsg,
162
}
163

            
164
impl ChanCell {
165
    /// Construct a new channel cell.
166
57970
    pub fn new(circid: CircId, msg: msg::ChanMsg) -> Self {
167
57970
        ChanCell { circid, msg }
168
57970
    }
169
    /// Return the circuit ID for this cell.
170
572
    pub fn circid(&self) -> CircId {
171
572
        self.circid
172
572
    }
173
    /// Return a reference to the underlying message of this cell.
174
108790
    pub fn msg(&self) -> &msg::ChanMsg {
175
108790
        &self.msg
176
108790
    }
177
    /// Consume this cell and return its components.
178
57200
    pub fn into_circid_and_msg(self) -> (CircId, msg::ChanMsg) {
179
57200
        (self.circid, self.msg)
180
57200
    }
181
}