1
//! This contains restricted message sets namespaced by link protocol version.
2
//!
3
//! In other words, each protocol version define sets of possible messages depending on the channel
4
//! type as in client or relay and initiator or responder.
5
//!
6
//! This module also defines [`MessageFilter`] which can be used to filter messages based on
7
//! specific details of the message such as direction, command, channel type and channel stage.
8

            
9
use bytes::BytesMut;
10
use tor_cell::chancell::{AnyChanCell, ChanCell, ChanMsg, codec, msg::AnyChanMsg};
11

            
12
use crate::{Error, channel::ChannelType};
13

            
14
/// Subprotocol LINK version 4.
15
///
16
/// Increases circuit ID width to 4 bytes.
17
pub(super) mod linkv4 {
18
    use bytes::BytesMut;
19
    use tor_cell::{
20
        chancell::{AnyChanCell, codec},
21
        restricted_msg,
22
    };
23

            
24
    use super::MessageStage;
25
    use crate::{
26
        Error,
27
        channel::{
28
            ChannelType,
29
            msg::{decode_as_any, encode_as_any},
30
        },
31
    };
32

            
33
    restricted_msg! {
34
        /// Handshake messages of a relay that initiates a connection. They are sent by the
35
        /// initiator and thus received by the responder.
36
        #[derive(Clone, Debug)]
37
        pub(super) enum HandshakeRelayInitiatorMsg: ChanMsg {
38
            Authenticate,
39
            Certs,
40
            Netinfo,
41
            Vpadding,
42
        }
43
    }
44

            
45
    restricted_msg! {
46
        /// Handshake messages of a relay that responds to a connection. They are received by the
47
        /// initiator and thus sent by the responder.
48
        #[derive(Clone, Debug)]
49
        pub(super) enum HandshakeRelayResponderMsg: ChanMsg {
50
            AuthChallenge,
51
            Certs,
52
            Netinfo,
53
            Vpadding,
54
        }
55
    }
56

            
57
    restricted_msg! {
58
        /// Handshake messages of a client that initiates a connection to a relay.
59
        ///
60
        /// The Versions message is not in this set as it is a special case as the very first cell
61
        /// being negotiated in order to learn the link protocol version.
62
        ///
63
        /// This MUST be a subset of HandshakeRelayResponderMsg because the relay responder doesn't
64
        /// know what the other side will send depending if it wants to authenticate or not.
65
        #[derive(Clone, Debug)]
66
        pub(super) enum HandshakeClientInitiatorMsg: ChanMsg {
67
            Netinfo,
68
            Vpadding,
69
        }
70
    }
71

            
72
    // From this point on, the C is "Client" and the R is "Relay" and the name indicate the
73
    // direction of messages. For example, C2R means client -> (to) relay.
74

            
75
    restricted_msg! {
76
        /// A channel message that we allow to be sent from a Client to a Relay on
77
        /// an open channel.
78
        #[derive(Clone, Debug)]
79
        pub(super) enum OpenChanMsgC2R: ChanMsg {
80
            // No Create*, it is obsolete (TAP).
81
            Create2,
82
            CreateFast,
83
            Destroy,
84
            Padding,
85
            Vpadding,
86
            // No PaddingNegotiate, it is v5+ only.
87
            Relay,
88
            RelayEarly,
89
        }
90
    }
91

            
92
    restricted_msg! {
93
        /// A channel message that we allow to be sent from a Relay to a Client on
94
        /// an open channel.
95
        ///
96
        /// (An Open channel here is one on which we have received a NETINFO cell.)
97
        #[derive(Clone, Debug)]
98
        pub(super) enum OpenChanMsgR2C : ChanMsg {
99
            // No Create*, we are not a client and it is obsolete (TAP).
100
            // No Created*, it is obsolete (TAP).
101
            CreatedFast,
102
            Created2,
103
            Relay,
104
            // No RelayEarly, only for client.
105
            Destroy,
106
            Padding,
107
            Vpadding,
108
        }
109
    }
110

            
111
    restricted_msg! {
112
        /// A channel message that we allow to be sent (bidirectionally) from a Relay to a Relay on
113
        /// an open channel.
114
        #[derive(Clone, Debug)]
115
        pub(super) enum OpenChanMsgR2R : ChanMsg {
116
            // No Vpadding, only sent during handshake.
117
            // No Create/Created, it is obsolete (TAP).
118
            CreateFast,
119
            CreatedFast,
120
            Create2,
121
            Created2,
122
            Destroy,
123
            Padding,
124
            Vpadding,
125
            Relay,
126
            RelayEarly,
127
            // No PaddingNegotiate, only client sends this.
128
            // No Versions, Certs, AuthChallenge, Authenticate, Netinfo: they are for handshakes.
129
            // No Authorize: it is reserved, but unused.
130
        }
131
    }
132

            
133
    /// Decode cell using the given channel type, message stage, codec and byte source.
134
    pub(super) fn decode_cell(
135
        chan_type: ChannelType,
136
        stage: &MessageStage,
137
        codec: &mut codec::ChannelCodec,
138
        src: &mut BytesMut,
139
    ) -> Result<Option<AnyChanCell>, Error> {
140
        use ChannelType::*;
141
        use MessageStage::*;
142

            
143
        let decode_fn = match (chan_type, stage) {
144
            (ClientInitiator, Handshake) => decode_as_any::<HandshakeRelayResponderMsg>,
145
            (ClientInitiator, Open) => decode_as_any::<OpenChanMsgR2C>,
146
            (RelayInitiator, Handshake) => decode_as_any::<HandshakeRelayResponderMsg>,
147
            (RelayInitiator, Open) => decode_as_any::<OpenChanMsgR2R>,
148
            (RelayResponder { authenticated: _ }, Handshake) => {
149
                // We don't know if the other side is a client or relay.
150
                // However, the `HandshakeRelayInitiatorMsg` message set
151
                // is a superset of the `HandshakeClientInitiatorMsg` message set
152
                // and so we cover any client-sent messages as well.
153
                decode_as_any::<HandshakeRelayInitiatorMsg>
154
            }
155
            (RelayResponder { authenticated }, Open) => match authenticated {
156
                false => decode_as_any::<OpenChanMsgC2R>,
157
                true => decode_as_any::<OpenChanMsgR2R>,
158
            },
159
        };
160

            
161
        decode_fn(stage, codec, src)
162
    }
163

            
164
    /// Encode a given cell which can contains any type of messages. It is filtered through its
165
    /// restricted message set at encoding time.
166
    ///
167
    /// Return an error if encoding fails or if cell is disallowed.
168
    pub(super) fn encode_cell(
169
        chan_type: ChannelType,
170
        stage: &MessageStage,
171
        cell: AnyChanCell,
172
        codec: &mut codec::ChannelCodec,
173
        dst: &mut BytesMut,
174
    ) -> Result<(), Error> {
175
        use ChannelType::*;
176
        use MessageStage::*;
177

            
178
        let encode_fn = match (chan_type, stage) {
179
            (ClientInitiator, Handshake) => encode_as_any::<HandshakeClientInitiatorMsg>,
180
            (ClientInitiator, Open) => encode_as_any::<OpenChanMsgC2R>,
181
            (RelayInitiator, Handshake) => encode_as_any::<HandshakeRelayInitiatorMsg>,
182
            (RelayInitiator, Open) => encode_as_any::<OpenChanMsgR2R>,
183
            (RelayResponder { authenticated: _ }, Handshake) => {
184
                encode_as_any::<HandshakeRelayResponderMsg>
185
            }
186
            (RelayResponder { authenticated }, Open) => match authenticated {
187
                false => encode_as_any::<OpenChanMsgR2C>,
188
                true => encode_as_any::<OpenChanMsgR2R>,
189
            },
190
        };
191

            
192
        encode_fn(stage, cell, codec, dst)
193
    }
194
}
195

            
196
/// Subprotocol LINK version 5.
197
///
198
/// Adds support for padding and negotiation.
199
pub(super) mod linkv5 {
200
    use bytes::BytesMut;
201
    use tor_cell::{
202
        chancell::{AnyChanCell, codec},
203
        restricted_msg,
204
    };
205

            
206
    use super::MessageStage;
207
    use crate::{
208
        Error,
209
        channel::{
210
            ChannelType,
211
            msg::{decode_as_any, encode_as_any},
212
        },
213
    };
214

            
215
    restricted_msg! {
216
        /// Handshake messages of a relay that initiates a connection. They are sent by the
217
        /// initiator and thus received by the responder.
218
        #[derive(Clone,Debug)]
219
        pub(super) enum HandshakeRelayInitiatorMsg: ChanMsg {
220
            Authenticate,
221
            Certs,
222
            Netinfo,
223
            Vpadding,
224
        }
225
    }
226

            
227
    restricted_msg! {
228
        /// Handshake messages of a relay that responds to a connection. They are received by the
229
        /// initiator and thus sent by the responder.
230
        #[derive(Clone,Debug)]
231
        pub(super) enum HandshakeRelayResponderMsg: ChanMsg {
232
            AuthChallenge,
233
            Certs,
234
            Netinfo,
235
            Vpadding,
236
        }
237
    }
238

            
239
    restricted_msg! {
240
        /// Handshake messages of a client that initiates a connection to a relay.
241
        ///
242
        /// The Versions message is not in this set as it is a special case as the very first cell
243
        /// being negotiated in order to learn the link protocol version.
244
        #[derive(Clone,Debug)]
245
        pub(super) enum HandshakeClientInitiatorMsg: ChanMsg {
246
            Netinfo,
247
            Vpadding,
248
        }
249
    }
250

            
251
    // From this point on, the C is "Client" and the R is "Relay" and the name indicate the
252
    // direction of messages. For example, C2R means client -> (to) relay.
253

            
254
    restricted_msg! {
255
        /// A channel message that we allow to be sent from a Client to a Relay on
256
        /// an open channel.
257
        #[derive(Clone, Debug)]
258
        pub(super) enum OpenChanMsgC2R: ChanMsg {
259
            // No Create*, it is obsolete (TAP).
260
            Create2,
261
            CreateFast,
262
            Destroy,
263
            Padding,
264
            PaddingNegotiate,
265
            Vpadding,
266
            Relay,
267
            RelayEarly,
268
        }
269
    }
270

            
271
    restricted_msg! {
272
        /// A channel message that we allow to be sent from a Relay to a Client on
273
        /// an open channel.
274
        ///
275
        /// (An Open channel here is one on which we have received a NETINFO cell.)
276
        #[derive(Clone, Debug)]
277
        pub(super) enum OpenChanMsgR2C : ChanMsg {
278
            // No Create/d*, only clients and it is obsolete (TAP).
279
            CreatedFast,
280
            Created2,
281
            Destroy,
282
            Padding,
283
            Vpadding,
284
            Relay,
285
            // No PaddingNegotiate, only clients.
286
            // No Versions, Certs, AuthChallenge, Authenticate: they are for handshakes.
287
            // No Authorize: it is reserved, but unused.
288
        }
289
    }
290

            
291
    restricted_msg! {
292
        /// A channel message that we allow to be sent (bidirectionally) from a Relay to a Relay on
293
        /// an open channel.
294
        #[derive(Clone, Debug)]
295
        pub(super) enum OpenChanMsgR2R : ChanMsg {
296
            // No Create/Created, it is obsolete (TAP).
297
            CreateFast,
298
            CreatedFast,
299
            Create2,
300
            Created2,
301
            Destroy,
302
            Padding,
303
            Vpadding,
304
            // No Vpadding, only sent during handshake.
305
            Relay,
306
            RelayEarly,
307
            // No PaddingNegotiate, only client sends this.
308
            // No Versions, Certs, AuthChallenge, Authenticate, Netinfo: they are for handshakes.
309
            // No Authorize: it is reserved, but unused.
310
        }
311
    }
312

            
313
    /// Decode cell using the given channel type, message stage, codec and byte source.
314
960
    pub(super) fn decode_cell(
315
960
        chan_type: ChannelType,
316
960
        stage: &MessageStage,
317
960
        codec: &mut codec::ChannelCodec,
318
960
        src: &mut BytesMut,
319
960
    ) -> Result<Option<AnyChanCell>, Error> {
320
        use ChannelType::*;
321
        use MessageStage::*;
322

            
323
960
        let decode_fn = match (chan_type, stage) {
324
864
            (ClientInitiator, Handshake) => decode_as_any::<HandshakeRelayResponderMsg>,
325
24
            (ClientInitiator, Open) => decode_as_any::<OpenChanMsgR2C>,
326
72
            (RelayInitiator, Handshake) => decode_as_any::<HandshakeRelayResponderMsg>,
327
            (RelayInitiator, Open) => decode_as_any::<OpenChanMsgR2R>,
328
            (RelayResponder { authenticated: _ }, Handshake) => {
329
                // We don't know if the other side is a client or relay.
330
                // However, the `HandshakeRelayInitiatorMsg` message set
331
                // is a superset of the `HandshakeClientInitiatorMsg` message set
332
                // and so we cover any client-sent messages as well.
333
                decode_as_any::<HandshakeRelayInitiatorMsg>
334
            }
335
            (RelayResponder { authenticated }, Open) => match authenticated {
336
                false => decode_as_any::<OpenChanMsgC2R>,
337
                true => decode_as_any::<OpenChanMsgR2R>,
338
            },
339
        };
340

            
341
960
        decode_fn(stage, codec, src)
342
960
    }
343

            
344
    /// Encode a given cell which can contains any type of messages. It is filtered through its
345
    /// restricted message set at encoding time.
346
    ///
347
    /// Return an error if encoding fails or if cell is disallowed.
348
75
    pub(super) fn encode_cell(
349
75
        chan_type: ChannelType,
350
75
        stage: &MessageStage,
351
75
        cell: AnyChanCell,
352
75
        codec: &mut codec::ChannelCodec,
353
75
        dst: &mut BytesMut,
354
75
    ) -> Result<(), Error> {
355
        use ChannelType::*;
356
        use MessageStage::*;
357

            
358
75
        let encode_fn = match (chan_type, stage) {
359
51
            (ClientInitiator, Handshake) => encode_as_any::<HandshakeClientInitiatorMsg>,
360
12
            (ClientInitiator, Open) => encode_as_any::<OpenChanMsgC2R>,
361
12
            (RelayInitiator, Handshake) => encode_as_any::<HandshakeRelayInitiatorMsg>,
362
            (RelayInitiator, Open) => encode_as_any::<OpenChanMsgR2R>,
363
            (RelayResponder { authenticated: _ }, Handshake) => {
364
                encode_as_any::<HandshakeRelayResponderMsg>
365
            }
366
            (RelayResponder { authenticated }, Open) => match authenticated {
367
                false => encode_as_any::<OpenChanMsgR2C>,
368
                true => encode_as_any::<OpenChanMsgR2R>,
369
            },
370
        };
371

            
372
75
        encode_fn(stage, cell, codec, dst)
373
75
    }
374
}
375

            
376
/// Helper function to decode a cell within a restricted msg set into an AnyChanCell.
377
///
378
/// The given stage is used to know which error to return.
379
960
fn decode_as_any<R>(
380
960
    stage: &MessageStage,
381
960
    codec: &mut codec::ChannelCodec,
382
960
    src: &mut BytesMut,
383
960
) -> Result<Option<AnyChanCell>, Error>
384
960
where
385
960
    R: Into<AnyChanMsg> + ChanMsg,
386
{
387
960
    codec
388
960
        .decode_cell::<R>(src)
389
960
        .map(|opt| {
390
952
            opt.map(|cell| {
391
257
                let (circid, msg) = cell.into_circid_and_msg();
392
257
                ChanCell::new(circid, msg.into())
393
257
            })
394
952
        })
395
960
        .map_err(|e| stage.to_err(format!("Decoding cell error: {e}")))
396
960
}
397

            
398
/// Helper function to encode an AnyChanCell cell that is within a restricted msg set R.
399
///
400
/// The given stage is used to know which error to return.
401
75
fn encode_as_any<R>(
402
75
    stage: &MessageStage,
403
75
    cell: AnyChanCell,
404
75
    codec: &mut codec::ChannelCodec,
405
75
    dst: &mut BytesMut,
406
75
) -> Result<(), Error>
407
75
where
408
75
    R: ChanMsg + TryFrom<AnyChanMsg, Error = AnyChanMsg>,
409
{
410
75
    let (circ_id, any_msg) = cell.into_circid_and_msg();
411

            
412
75
    match R::try_from(any_msg) {
413
75
        Ok(rmsg) => {
414
75
            let rcell: ChanCell<R> = ChanCell::new(circ_id, rmsg);
415
75
            codec
416
75
                .write_cell(rcell, dst)
417
75
                .map_err(|e| stage.to_err(format!("Encoding cell error: {e}")))
418
        }
419
        Err(m) => Err(stage.to_err(format!("Disallowed cell command {}", m.cmd(),))),
420
    }
421
75
}
422

            
423
/// Channel protocol version negotiated.
424
#[derive(Copy, Clone, Debug)]
425
pub(super) enum LinkVersion {
426
    /// Version 4 that need to use linkv4:: messages.
427
    V4,
428
    /// Version 5 that need to use linkv5:: messages.
429
    V5,
430
}
431

            
432
impl LinkVersion {
433
    /// Return the value of this link version as a u16. Useful for lower level crates that require
434
    /// the value for which we can't export this enum.
435
238
    pub(super) fn value(&self) -> u16 {
436
238
        match self {
437
48
            Self::V4 => 4,
438
190
            Self::V5 => 5,
439
        }
440
238
    }
441
}
442

            
443
impl TryFrom<u16> for LinkVersion {
444
    type Error = Error;
445

            
446
214
    fn try_from(value: u16) -> Result<Self, Self::Error> {
447
214
        Ok(match value {
448
48
            4 => Self::V4,
449
166
            5 => Self::V5,
450
            _ => {
451
                return Err(Error::HandshakeProto(format!(
452
                    "Unknown link version {value}"
453
                )));
454
            }
455
        })
456
214
    }
457
}
458

            
459
/// What stage a channel can be of a negotiation. This is used in order to learn which restricted
460
/// message set we should be looking at.
461
///
462
/// Notice that we don't have the "New" stage and this is because we only learn the link protocol
463
/// version once we enter the Handshake stage.
464
pub(super) enum MessageStage {
465
    /// Handshaking as in the channel is working to become open.
466
    Handshake,
467
    /// Open as the channel is now open.
468
    Open,
469
}
470

            
471
impl MessageStage {
472
    /// Return an error using the given message for the right stage.
473
    ///
474
    /// Very useful helper that just select the right error type for the stage.
475
8
    fn to_err(&self, msg: String) -> Error {
476
8
        match self {
477
8
            Self::Handshake => Error::HandshakeProto(msg),
478
            Self::Open => Error::ChanProto(msg),
479
        }
480
8
    }
481
}
482

            
483
/// A message filter object which is used to learn if a certain message is allowed or not on a
484
/// channel.
485
///
486
/// It is pinned to a link protocol version, a channel type and a channel message stage.
487
pub(super) struct MessageFilter {
488
    /// For what link protocol version this filter applies for.
489
    link_version: LinkVersion,
490
    /// For which channel type this filter applies for.
491
    channel_type: ChannelType,
492
    /// At which stage this filter applies for.
493
    stage: MessageStage,
494
}
495

            
496
impl MessageFilter {
497
    /// Constructor
498
238
    pub(super) fn new(
499
238
        link_version: LinkVersion,
500
238
        channel_type: ChannelType,
501
238
        stage: MessageStage,
502
238
    ) -> Self {
503
238
        Self {
504
238
            link_version,
505
238
            channel_type,
506
238
            stage,
507
238
        }
508
238
    }
509

            
510
    /// Return the [`ChannelType`] of this filter.
511
130
    pub(super) fn channel_type(&self) -> ChannelType {
512
130
        self.channel_type
513
130
    }
514

            
515
    /// Return the [`ChannelType`] of this filter as a mutable.
516
    pub(super) fn channel_type_mut(&mut self) -> &mut ChannelType {
517
        &mut self.channel_type
518
    }
519

            
520
    /// Decode a cell from the given bytes for the right link version, channel type and message
521
    /// stage using the codec given.
522
960
    pub(super) fn decode_cell(
523
960
        &self,
524
960
        codec: &mut codec::ChannelCodec,
525
960
        src: &mut BytesMut,
526
960
    ) -> Result<Option<AnyChanCell>, Error> {
527
960
        match self.link_version {
528
            LinkVersion::V4 => linkv4::decode_cell(self.channel_type, &self.stage, codec, src),
529
960
            LinkVersion::V5 => linkv5::decode_cell(self.channel_type, &self.stage, codec, src),
530
        }
531
960
    }
532

            
533
    /// Decode a cell from the given bytes for the right link version, channel type and message
534
    /// stage using the codec given.
535
75
    pub(super) fn encode_cell(
536
75
        &self,
537
75
        cell: AnyChanCell,
538
75
        codec: &mut codec::ChannelCodec,
539
75
        dst: &mut BytesMut,
540
75
    ) -> Result<(), Error> {
541
75
        match self.link_version {
542
            LinkVersion::V4 => {
543
                linkv4::encode_cell(self.channel_type, &self.stage, cell, codec, dst)
544
            }
545
            LinkVersion::V5 => {
546
75
                linkv5::encode_cell(self.channel_type, &self.stage, cell, codec, dst)
547
            }
548
        }
549
75
    }
550
}