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::{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::{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
    ///
135
    /// Returns both the cell and the bytes that the cell were decoded from.
136
    pub(super) fn decode_cell(
137
        chan_type: ChannelType,
138
        stage: &MessageStage,
139
        codec: &mut codec::ChannelCodec,
140
        src: &mut BytesMut,
141
    ) -> Result<Option<(AnyChanCell, Bytes)>, Error> {
142
        use ChannelType::*;
143
        use MessageStage::*;
144

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

            
163
        decode_fn(stage, codec, src)
164
    }
165

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

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

            
194
        encode_fn(stage, cell, codec, dst)
195
    }
196
}
197

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

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

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

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

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

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

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

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

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

            
315
    /// Decode cell using the given channel type, message stage, codec and byte source.
316
    ///
317
    /// Returns both the cell and the bytes that the cell were decoded from.
318
872
    pub(super) fn decode_cell(
319
872
        chan_type: ChannelType,
320
872
        stage: &MessageStage,
321
872
        codec: &mut codec::ChannelCodec,
322
872
        src: &mut BytesMut,
323
872
    ) -> Result<Option<(AnyChanCell, Bytes)>, Error> {
324
        use ChannelType::*;
325
        use MessageStage::*;
326

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

            
345
872
        decode_fn(stage, codec, src)
346
872
    }
347

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

            
362
62
        let encode_fn = match (chan_type, stage) {
363
50
            (ClientInitiator, Handshake) => encode_as_any::<HandshakeClientInitiatorMsg>,
364
6
            (ClientInitiator, Open) => encode_as_any::<OpenChanMsgC2R>,
365
6
            (RelayInitiator, Handshake) => encode_as_any::<HandshakeRelayInitiatorMsg>,
366
            (RelayInitiator, Open) => encode_as_any::<OpenChanMsgR2R>,
367
            (RelayResponder { authenticated: _ }, Handshake) => {
368
                encode_as_any::<HandshakeRelayResponderMsg>
369
            }
370
            (RelayResponder { authenticated }, Open) => match authenticated {
371
                false => encode_as_any::<OpenChanMsgR2C>,
372
                true => encode_as_any::<OpenChanMsgR2R>,
373
            },
374
        };
375

            
376
62
        encode_fn(stage, cell, codec, dst)
377
62
    }
378
}
379

            
380
/// Helper function to decode a cell within a restricted msg set into an AnyChanCell.
381
///
382
/// The given stage is used to know which error to return.
383
///
384
/// Returns both the cell and the bytes that the cell were decoded from.
385
872
fn decode_as_any<R>(
386
872
    stage: &MessageStage,
387
872
    codec: &mut codec::ChannelCodec,
388
872
    src: &mut BytesMut,
389
872
) -> Result<Option<(AnyChanCell, Bytes)>, Error>
390
872
where
391
872
    R: Into<AnyChanMsg> + ChanMsg,
392
{
393
872
    codec
394
872
        .decode_cell::<R>(src)
395
872
        .map(|opt| {
396
868
            opt.map(|(cell, cell_bytes)| {
397
202
                let (circid, msg) = cell.into_circid_and_msg();
398
202
                (ChanCell::new(circid, msg.into()), cell_bytes)
399
202
            })
400
868
        })
401
872
        .map_err(|e| stage.to_err(format!("Decoding cell error: {e}")))
402
872
}
403

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

            
418
62
    match R::try_from(any_msg) {
419
62
        Ok(rmsg) => {
420
62
            let rcell: ChanCell<R> = ChanCell::new(circ_id, rmsg);
421
62
            codec
422
62
                .write_cell(rcell, dst)
423
62
                .map_err(|e| stage.to_err(format!("Encoding cell error: {e}")))
424
        }
425
        Err(m) => Err(stage.to_err(format!("Disallowed cell command {}", m.cmd(),))),
426
    }
427
62
}
428

            
429
/// Channel protocol version negotiated.
430
#[derive(Copy, Clone, Debug)]
431
pub(super) enum LinkVersion {
432
    /// Version 4 that need to use linkv4:: messages.
433
    V4,
434
    /// Version 5 that need to use linkv5:: messages.
435
    V5,
436
}
437

            
438
impl LinkVersion {
439
    /// Return the value of this link version as a u16. Useful for lower level crates that require
440
    /// the value for which we can't export this enum.
441
168
    pub(super) fn value(&self) -> u16 {
442
168
        match self {
443
24
            Self::V4 => 4,
444
144
            Self::V5 => 5,
445
        }
446
168
    }
447
}
448

            
449
impl TryFrom<u16> for LinkVersion {
450
    type Error = Error;
451

            
452
156
    fn try_from(value: u16) -> Result<Self, Self::Error> {
453
156
        Ok(match value {
454
24
            4 => Self::V4,
455
132
            5 => Self::V5,
456
            _ => {
457
                return Err(Error::HandshakeProto(format!(
458
                    "Unknown link version {value}"
459
                )));
460
            }
461
        })
462
156
    }
463
}
464

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

            
477
impl MessageStage {
478
    /// Return an error using the given message for the right stage.
479
    ///
480
    /// Very useful helper that just select the right error type for the stage.
481
4
    fn to_err(&self, msg: String) -> Error {
482
4
        match self {
483
4
            Self::Handshake => Error::HandshakeProto(msg),
484
            Self::Open => Error::ChanProto(msg),
485
        }
486
4
    }
487
}
488

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

            
502
impl MessageFilter {
503
    /// Constructor
504
168
    pub(super) fn new(
505
168
        link_version: LinkVersion,
506
168
        channel_type: ChannelType,
507
168
        stage: MessageStage,
508
168
    ) -> Self {
509
168
        Self {
510
168
            link_version,
511
168
            channel_type,
512
168
            stage,
513
168
        }
514
168
    }
515

            
516
    /// Return the [`ChannelType`] of this filter.
517
114
    pub(super) fn channel_type(&self) -> ChannelType {
518
114
        self.channel_type
519
114
    }
520

            
521
    /// Return the [`ChannelType`] of this filter as a mutable.
522
    pub(super) fn channel_type_mut(&mut self) -> &mut ChannelType {
523
        &mut self.channel_type
524
    }
525

            
526
    /// Decode a cell from the given bytes for the right link version, channel type and message
527
    /// stage using the codec given.
528
    ///
529
    /// Returns both the cell and the bytes that the cell were decoded from.
530
872
    pub(super) fn decode_cell(
531
872
        &self,
532
872
        codec: &mut codec::ChannelCodec,
533
872
        src: &mut BytesMut,
534
872
    ) -> Result<Option<(AnyChanCell, Bytes)>, Error> {
535
872
        match self.link_version {
536
            LinkVersion::V4 => linkv4::decode_cell(self.channel_type, &self.stage, codec, src),
537
872
            LinkVersion::V5 => linkv5::decode_cell(self.channel_type, &self.stage, codec, src),
538
        }
539
872
    }
540

            
541
    /// Decode a cell from the given bytes for the right link version, channel type and message
542
    /// stage using the codec given.
543
62
    pub(super) fn encode_cell(
544
62
        &self,
545
62
        cell: AnyChanCell,
546
62
        codec: &mut codec::ChannelCodec,
547
62
        dst: &mut BytesMut,
548
62
    ) -> Result<(), Error> {
549
62
        match self.link_version {
550
            LinkVersion::V4 => {
551
                linkv4::encode_cell(self.channel_type, &self.stage, cell, codec, dst)
552
            }
553
            LinkVersion::V5 => {
554
62
                linkv5::encode_cell(self.channel_type, &self.stage, cell, codec, dst)
555
            }
556
        }
557
62
    }
558
}