1
//! This contains restricted message sets namespaced by link protocol version.
2
//!
3
//! In other words, each protocl 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. However, this message set
150
                // is a superset of the HandshakeClientInitiatorMsg and so we cover the client as
151
                // well.
152
                decode_as_any::<HandshakeRelayInitiatorMsg>
153
            }
154
            (RelayResponder { authenticated }, Open) => match authenticated {
155
                false => decode_as_any::<OpenChanMsgC2R>,
156
                true => decode_as_any::<OpenChanMsgR2R>,
157
            },
158
        };
159

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
322
864
        match (chan_type, stage) {
323
            (ClientInitiator, Handshake) => {
324
816
                decode_as_any::<HandshakeRelayResponderMsg>(stage, codec, src)
325
            }
326
24
            (ClientInitiator, Open) => decode_as_any::<OpenChanMsgR2C>(stage, codec, src),
327
            (RelayInitiator, Handshake) => {
328
24
                decode_as_any::<HandshakeRelayResponderMsg>(stage, codec, src)
329
            }
330
            (RelayInitiator, Open) => decode_as_any::<OpenChanMsgR2R>(stage, codec, src),
331
            (RelayResponder { authenticated: _ }, Handshake) => {
332
                decode_as_any::<HandshakeRelayInitiatorMsg>(stage, codec, src)
333
            }
334
            (
335
                RelayResponder {
336
                    authenticated: false,
337
                },
338
                Open,
339
            ) => decode_as_any::<OpenChanMsgC2R>(stage, codec, src),
340
            (
341
                RelayResponder {
342
                    authenticated: true,
343
                },
344
                Open,
345
            ) => decode_as_any::<OpenChanMsgR2R>(stage, codec, src),
346
        }
347
864
    }
348

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

            
363
72
        match (chan_type, stage) {
364
            (ClientInitiator, Handshake) => {
365
48
                encode_as_any::<HandshakeClientInitiatorMsg>(stage, cell, codec, dst)
366
            }
367
12
            (ClientInitiator, Open) => encode_as_any::<OpenChanMsgC2R>(stage, cell, codec, dst),
368
            (RelayInitiator, Handshake) => {
369
12
                encode_as_any::<HandshakeRelayInitiatorMsg>(stage, cell, codec, dst)
370
                // We don't know if the other side is a client or relay. However, this message set
371
                // is a superset of the HandshakeClientInitiatorMsg and so we cover the client as
372
                // well.
373
            }
374
            (RelayInitiator, Open) => encode_as_any::<OpenChanMsgR2R>(stage, cell, codec, dst),
375
            (RelayResponder { authenticated: _ }, Handshake) => {
376
                encode_as_any::<HandshakeRelayResponderMsg>(stage, cell, codec, dst)
377
            }
378
            (
379
                RelayResponder {
380
                    authenticated: false,
381
                },
382
                Open,
383
            ) => encode_as_any::<OpenChanMsgR2C>(stage, cell, codec, dst),
384
            (
385
                RelayResponder {
386
                    authenticated: true,
387
                },
388
                Open,
389
            ) => encode_as_any::<OpenChanMsgR2R>(stage, cell, codec, dst),
390
        }
391
72
    }
392
}
393

            
394
/// Helper function to decode a cell within a restricted msg set into an AnyChanCell.
395
///
396
/// The given stage is used to know which error to return.
397
864
fn decode_as_any<R>(
398
864
    stage: &MessageStage,
399
864
    codec: &mut codec::ChannelCodec,
400
864
    src: &mut BytesMut,
401
864
) -> Result<Option<AnyChanCell>, Error>
402
864
where
403
864
    R: Into<AnyChanMsg> + ChanMsg,
404
{
405
864
    codec
406
864
        .decode_cell::<R>(src)
407
864
        .map(|opt| {
408
860
            opt.map(|cell| {
409
208
                let (circid, msg) = cell.into_circid_and_msg();
410
208
                ChanCell::new(circid, msg.into())
411
208
            })
412
860
        })
413
864
        .map_err(|e| stage.to_err(format!("Decoding cell error: {e}")))
414
864
}
415

            
416
/// Helper function to encode an AnyChanCell cell that is within a restricted msg set R.
417
///
418
/// The given stage is used to know which error to return.
419
72
fn encode_as_any<R>(
420
72
    stage: &MessageStage,
421
72
    cell: AnyChanCell,
422
72
    codec: &mut codec::ChannelCodec,
423
72
    dst: &mut BytesMut,
424
72
) -> Result<(), Error>
425
72
where
426
72
    R: ChanMsg + TryFrom<AnyChanMsg, Error = AnyChanMsg>,
427
{
428
72
    let (circ_id, any_msg) = cell.into_circid_and_msg();
429

            
430
72
    match R::try_from(any_msg) {
431
72
        Ok(rmsg) => {
432
72
            let rcell: ChanCell<R> = ChanCell::new(circ_id, rmsg);
433
72
            codec
434
72
                .write_cell(rcell, dst)
435
72
                .map_err(|e| stage.to_err(format!("Encoding cell error: {e}")))
436
        }
437
        Err(m) => Err(stage.to_err(format!("Disallowed cell command {}", m.cmd(),))),
438
    }
439
72
}
440

            
441
/// Channel protocol version negotiated.
442
#[derive(Copy, Clone, Debug)]
443
pub(super) enum LinkVersion {
444
    /// Version 4 that need to use linkv4:: messages.
445
    V4,
446
    /// Version 5 that need to use linkv5:: messages.
447
    V5,
448
}
449

            
450
impl LinkVersion {
451
    /// Return the value of this link version as a u16. Useful for lower level crates that require
452
    /// the value for which we can't export this enum.
453
214
    pub(super) fn value(&self) -> u16 {
454
214
        match self {
455
48
            Self::V4 => 4,
456
166
            Self::V5 => 5,
457
        }
458
214
    }
459
}
460

            
461
impl TryFrom<u16> for LinkVersion {
462
    type Error = Error;
463

            
464
190
    fn try_from(value: u16) -> Result<Self, Self::Error> {
465
190
        Ok(match value {
466
48
            4 => Self::V4,
467
142
            5 => Self::V5,
468
            _ => {
469
                return Err(Error::HandshakeProto(format!(
470
                    "Unknown link version {value}"
471
                )));
472
            }
473
        })
474
190
    }
475
}
476

            
477
/// What stage a channel can be of a negotiation. This is used in order to learn which restricted
478
/// message set we should be looking at.
479
///
480
/// Notice that we don't have the "New" stage and this is because we only learn the link protocol
481
/// version once we enter the Handshake stage.
482
pub(super) enum MessageStage {
483
    /// Handshaking as in the channel is working to become open.
484
    Handshake,
485
    /// Open as the channel is now open.
486
    Open,
487
}
488

            
489
impl MessageStage {
490
    /// Return an error using the given message for the right stage.
491
    ///
492
    /// Very useful helper that just select the right error type for the stage.
493
4
    fn to_err(&self, msg: String) -> Error {
494
4
        match self {
495
4
            Self::Handshake => Error::HandshakeProto(msg),
496
            Self::Open => Error::ChanProto(msg),
497
        }
498
4
    }
499
}
500

            
501
/// A message filter object which is used to learn if a certain message is allowed or not on a
502
/// channel.
503
///
504
/// It is pinned to a link protocol version, a channel type and a channel message stage.
505
pub(super) struct MessageFilter {
506
    /// For what link protocol version this filter applies for.
507
    link_version: LinkVersion,
508
    /// For which channel type this filter applies for.
509
    channel_type: ChannelType,
510
    /// At which stage this filter applies for.
511
    stage: MessageStage,
512
}
513

            
514
impl MessageFilter {
515
    /// Constructor
516
214
    pub(super) fn new(
517
214
        link_version: LinkVersion,
518
214
        channel_type: ChannelType,
519
214
        stage: MessageStage,
520
214
    ) -> Self {
521
214
        Self {
522
214
            link_version,
523
214
            channel_type,
524
214
            stage,
525
214
        }
526
214
    }
527

            
528
    /// Return the [`ChannelType`] of this filter.
529
124
    pub(super) fn channel_type(&self) -> ChannelType {
530
124
        self.channel_type
531
124
    }
532

            
533
    /// Return the [`ChannelType`] of this filter as a mutable.
534
    pub(super) fn channel_type_mut(&mut self) -> &mut ChannelType {
535
        &mut self.channel_type
536
    }
537

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

            
551
    /// Decode a cell from the given bytes for the right link version, channel type and message
552
    /// stage using the codec given.
553
72
    pub(super) fn encode_cell(
554
72
        &self,
555
72
        cell: AnyChanCell,
556
72
        codec: &mut codec::ChannelCodec,
557
72
        dst: &mut BytesMut,
558
72
    ) -> Result<(), Error> {
559
72
        match self.link_version {
560
            LinkVersion::V4 => {
561
                linkv4::encode_cell(self.channel_type, &self.stage, cell, codec, dst)
562
            }
563
            LinkVersion::V5 => {
564
72
                linkv5::encode_cell(self.channel_type, &self.stage, cell, codec, dst)
565
            }
566
        }
567
72
    }
568
}