1
//! Types to implement the SOCKS handshake.
2

            
3
use crate::msg::{SocksAddr, SocksAuth, SocksCmd, SocksRequest, SocksStatus, SocksVersion};
4
use crate::{Error, Result, TResult, Truncated};
5

            
6
use tor_bytes::Error as BytesError;
7
use tor_bytes::Result as BytesResult;
8
use tor_bytes::{Readable, Reader, Writeable, Writer};
9
use tor_error::internal;
10

            
11
use std::convert::TryInto;
12
use std::net::IpAddr;
13

            
14
/// An ongoing SOCKS handshake.
15
///
16
/// To perform a handshake, call the [SocksHandshake::handshake]
17
/// method repeatedly with new inputs, until the resulting [Action]
18
/// has `finished` set to true.
19
#[derive(Clone, Debug)]
20
pub struct SocksHandshake {
21
    /// Current state of the handshake. Each completed message
22
    /// advances the state.
23
    state: State,
24
    /// SOCKS5 authentication that has been received (but not yet put
25
    /// in a SocksRequest object.)
26
    socks5_auth: Option<SocksAuth>,
27
    /// Completed SOCKS handshake.
28
    handshake: Option<SocksRequest>,
29
}
30

            
31
/// Possible state for a Socks connection.
32
///
33
/// Each completed message advances the state.
34
8
#[derive(Clone, Debug, Copy, PartialEq)]
35
enum State {
36
    /// Starting state: no messages have been handled yet.
37
    Initial,
38
    /// SOCKS5: we've negotiated Username/Password authentication, and
39
    /// are waiting for the client to send it.
40
    Socks5Username,
41
    /// SOCKS5: we've finished the authentication (if any), and
42
    /// we're waiting for the actual request.
43
    Socks5Wait,
44
    /// Ending (successful) state: the client has sent all its messages.
45
    ///
46
    /// (Note that we still need to send a reply.)
47
    Done,
48
    /// Ending (failed) state: the handshake has failed and cannot continue.
49
    Failed,
50
}
51

            
52
/// An action to take in response to a SOCKS handshake message.
53
#[derive(Clone, Debug)]
54
#[non_exhaustive]
55
pub struct Action {
56
    /// If nonzero, this many bytes should be drained from the
57
    /// client's inputs.
58
    pub drain: usize,
59
    /// If nonempty, this reply should be sent to the client.
60
    pub reply: Vec<u8>,
61
    /// If true, then this handshake is over, either successfully or not.
62
    pub finished: bool,
63
}
64

            
65
impl SocksHandshake {
66
    /// Construct a new SocksHandshake in its initial state
67
14
    pub fn new() -> Self {
68
14
        SocksHandshake {
69
14
            state: State::Initial,
70
14
            socks5_auth: None,
71
14
            handshake: None,
72
14
        }
73
14
    }
74

            
75
    /// Try to advance a SocksHandshake, given some client input in
76
    /// `input`.
77
    ///
78
    /// If there isn't enough input, gives a [`Truncated`].  Other
79
    /// errors indicate a failure.
80
    ///
81
    /// On success, return an Action describing what to tell the client,
82
    /// and how much of its input to consume.
83
21
    pub fn handshake(&mut self, input: &[u8]) -> TResult<Action> {
84
21
        if input.is_empty() {
85
1
            return Err(Truncated::new());
86
20
        }
87
20
        let rv = match (self.state, input[0]) {
88
3
            (State::Initial, 4) => self.s4(input),
89
8
            (State::Initial, 5) => self.s5_initial(input),
90
2
            (State::Initial, v) => Err(Error::BadProtocol(v)),
91
1
            (State::Socks5Username, 1) => self.s5_uname(input),
92
3
            (State::Socks5Wait, 5) => self.s5(input),
93
1
            (State::Done, _) => Err(Error::AlreadyFinished(internal!(
94
1
                "called handshake() after handshaking was done"
95
1
            ))),
96
1
            (State::Failed, _) => Err(Error::AlreadyFinished(internal!(
97
1
                "called handshake() after handshaking failed"
98
1
            ))),
99
1
            (_, _) => Err(Error::Syntax),
100
        };
101
        match rv {
102
            Err(Error::Decode(tor_bytes::Error::Truncated)) => Err(Truncated::new()),
103
6
            Err(e) => {
104
6
                self.state = State::Failed;
105
6
                Ok(Err(e))
106
            }
107
14
            Ok(a) => Ok(Ok(a)),
108
        }
109
21
    }
110

            
111
    /// Complete a socks4 or socks4a handshake.
112
3
    fn s4(&mut self, input: &[u8]) -> Result<Action> {
113
3
        let mut r = Reader::from_slice(input);
114
3
        let version = r.take_u8()?.try_into()?;
115
3
        if version != SocksVersion::V4 {
116
            return Err(internal!("called s4 on wrong type {:?}", version).into());
117
3
        }
118

            
119
3
        let cmd: SocksCmd = r.take_u8()?.into();
120
3
        let port = r.take_u16()?;
121
3
        let ip = r.take_u32()?;
122
3
        let username = r.take_until(0)?.into();
123
3
        let auth = SocksAuth::Socks4(username);
124

            
125
3
        let addr = if ip != 0 && (ip >> 8) == 0 {
126
            // Socks4a; a hostname is given.
127
1
            let hostname = r.take_until(0)?;
128
1
            let hostname = std::str::from_utf8(hostname)
129
1
                .map_err(|_| Error::Syntax)?
130
1
                .to_string();
131
1
            let hostname = hostname
132
1
                .try_into()
133
1
                .map_err(|_| BytesError::BadMessage("hostname too long"))?;
134
1
            SocksAddr::Hostname(hostname)
135
        } else {
136
2
            let ip4: std::net::Ipv4Addr = ip.into();
137
2
            SocksAddr::Ip(ip4.into())
138
        };
139

            
140
3
        let request = SocksRequest::new(version, cmd, addr, port, auth)?;
141

            
142
3
        self.state = State::Done;
143
3
        self.handshake = Some(request);
144
3

            
145
3
        Ok(Action {
146
3
            drain: r.consumed(),
147
3
            reply: Vec::new(),
148
3
            finished: true,
149
3
        })
150
3
    }
151

            
152
    /// Socks5: initial handshake to negotiate authentication method.
153
8
    fn s5_initial(&mut self, input: &[u8]) -> Result<Action> {
154
8
        let mut r = Reader::from_slice(input);
155
8
        let version: SocksVersion = r.take_u8()?.try_into()?;
156
8
        if version != SocksVersion::V5 {
157
            return Err(internal!("called on wrong handshake type {:?}", version).into());
158
8
        }
159

            
160
        /// Constant for Username/Password-style authentication.
161
        /// (See RFC 1929)
162
        const USERNAME_PASSWORD: u8 = 0x02;
163
        /// Constant for "no authentication".
164
        const NO_AUTHENTICATION: u8 = 0x00;
165

            
166
8
        let nmethods = r.take_u8()?;
167
8
        let methods = r.take(nmethods as usize)?;
168

            
169
        // Prefer username/password, then none.
170
8
        let (next, reply) = if methods.contains(&USERNAME_PASSWORD) {
171
2
            (State::Socks5Username, [5, USERNAME_PASSWORD])
172
6
        } else if methods.contains(&NO_AUTHENTICATION) {
173
5
            self.socks5_auth = Some(SocksAuth::NoAuth);
174
5
            (State::Socks5Wait, [5, NO_AUTHENTICATION])
175
        } else {
176
            // In theory we should reply with "NO ACCEPTABLE METHODS".
177
1
            return Err(Error::NotImplemented);
178
        };
179

            
180
7
        self.state = next;
181
7
        Ok(Action {
182
7
            drain: r.consumed(),
183
7
            reply: reply.into(),
184
7
            finished: false,
185
7
        })
186
8
    }
187

            
188
    /// Socks5: second step for username/password authentication.
189
1
    fn s5_uname(&mut self, input: &[u8]) -> Result<Action> {
190
1
        let mut r = Reader::from_slice(input);
191

            
192
1
        let ver = r.take_u8()?;
193
1
        if ver != 1 {
194
            return Err(Error::NotImplemented);
195
1
        }
196

            
197
1
        let ulen = r.take_u8()?;
198
1
        let username = r.take(ulen as usize)?;
199
1
        let plen = r.take_u8()?;
200
1
        let passwd = r.take(plen as usize)?;
201

            
202
1
        self.socks5_auth = Some(SocksAuth::Username(username.into(), passwd.into()));
203
1
        self.state = State::Socks5Wait;
204
1
        Ok(Action {
205
1
            drain: r.consumed(),
206
1
            reply: vec![1, 0],
207
1
            finished: false,
208
1
        })
209
1
    }
210

            
211
    /// Socks5: final step, to receive client's request.
212
3
    fn s5(&mut self, input: &[u8]) -> Result<Action> {
213
3
        let mut r = Reader::from_slice(input);
214

            
215
3
        let version: SocksVersion = r.take_u8()?.try_into()?;
216
3
        if version != SocksVersion::V5 {
217
            return Err(
218
                internal!("called s5 on non socks5 handshake with type {:?}", version).into(),
219
            );
220
3
        }
221
3
        let cmd = r.take_u8()?.into();
222
3
        let _ignore = r.take_u8()?;
223
3
        let addr = r.extract()?;
224
3
        let port = r.take_u16()?;
225

            
226
3
        let auth = self
227
3
            .socks5_auth
228
3
            .take()
229
3
            .ok_or_else(|| internal!("called s5 without negotiating auth"))?;
230

            
231
3
        let request = SocksRequest::new(version, cmd, addr, port, auth)?;
232

            
233
3
        self.state = State::Done;
234
3
        self.handshake = Some(request);
235
3

            
236
3
        Ok(Action {
237
3
            drain: r.consumed(),
238
3
            reply: Vec::new(),
239
3
            finished: true,
240
3
        })
241
3
    }
242

            
243
    /// Return true if this handshake is finished.
244
2
    pub fn finished(&self) -> bool {
245
2
        self.state == State::Done
246
2
    }
247

            
248
    /// Consume this handshake's state; if it finished successfully,
249
    /// return a SocksRequest.
250
5
    pub fn into_request(self) -> Option<SocksRequest> {
251
5
        self.handshake
252
5
    }
253
}
254

            
255
impl Default for SocksHandshake {
256
1
    fn default() -> Self {
257
1
        Self::new()
258
1
    }
259
}
260

            
261
impl SocksRequest {
262
    /// Format a reply to this request, indicating success or failure.
263
    ///
264
    /// Note that an address should be provided only when the request
265
    /// was for a RESOLVE.
266
5
    pub fn reply(&self, status: SocksStatus, addr: Option<&SocksAddr>) -> Vec<u8> {
267
5
        match self.version() {
268
2
            SocksVersion::V4 => self.s4(status, addr),
269
3
            SocksVersion::V5 => self.s5(status, addr),
270
        }
271
5
    }
272

            
273
    /// Format a SOCKS4 reply.
274
2
    fn s4(&self, status: SocksStatus, addr: Option<&SocksAddr>) -> Vec<u8> {
275
2
        let mut w = Vec::new();
276
2
        w.write_u8(0);
277
2
        w.write_u8(status.into_socks4_status());
278
1
        match addr {
279
1
            Some(SocksAddr::Ip(IpAddr::V4(ip))) => {
280
1
                w.write_u16(self.port());
281
1
                w.write(ip);
282
1
            }
283
1
            _ => {
284
1
                w.write_u16(0);
285
1
                w.write_u32(0);
286
1
            }
287
        }
288
2
        w
289
2
    }
290

            
291
    /// Format a SOCKS5 reply.
292
3
    pub fn s5(&self, status: SocksStatus, addr: Option<&SocksAddr>) -> Vec<u8> {
293
3
        let mut w = Vec::new();
294
3
        w.write_u8(5);
295
3
        w.write_u8(status.into());
296
3
        w.write_u8(0); // reserved.
297
3
        if let Some(a) = addr {
298
2
            w.write(a);
299
2
            w.write_u16(self.port());
300
2
        } else {
301
1
            // TODO: sometimes I think we want to answer with ::, not 0.0.0.0
302
1
            w.write(&SocksAddr::Ip(std::net::Ipv4Addr::UNSPECIFIED.into()));
303
1
            w.write_u16(0);
304
1
        }
305
3
        w
306
3
    }
307
}
308

            
309
impl Readable for SocksAddr {
310
3
    fn take_from(r: &mut Reader<'_>) -> BytesResult<SocksAddr> {
311
3
        let atype = r.take_u8()?;
312
3
        match atype {
313
            1 => {
314
1
                let ip4: std::net::Ipv4Addr = r.extract()?;
315
1
                Ok(SocksAddr::Ip(ip4.into()))
316
            }
317
            3 => {
318
1
                let hlen = r.take_u8()?;
319
1
                let hostname = r.take(hlen as usize)?;
320
1
                let hostname = std::str::from_utf8(hostname)
321
1
                    .map_err(|_| BytesError::BadMessage("bad utf8 on hostname"))?
322
1
                    .to_string();
323
1
                let hostname = hostname
324
1
                    .try_into()
325
1
                    .map_err(|_| BytesError::BadMessage("hostname too long"))?;
326
1
                Ok(SocksAddr::Hostname(hostname))
327
            }
328
            4 => {
329
1
                let ip6: std::net::Ipv6Addr = r.extract()?;
330
1
                Ok(SocksAddr::Ip(ip6.into()))
331
            }
332
            _ => Err(BytesError::BadMessage("unrecognized address type.")),
333
        }
334
3
    }
335
}
336

            
337
impl Writeable for SocksAddr {
338
3
    fn write_onto<W: Writer + ?Sized>(&self, w: &mut W) {
339
2
        match self {
340
1
            SocksAddr::Ip(IpAddr::V4(ip)) => {
341
1
                w.write_u8(1);
342
1
                w.write(ip);
343
1
            }
344
1
            SocksAddr::Ip(IpAddr::V6(ip)) => {
345
1
                w.write_u8(4);
346
1
                w.write(ip);
347
1
            }
348
1
            SocksAddr::Hostname(h) => {
349
1
                let h = h.as_ref();
350
1
                assert!(h.len() < 256);
351
1
                let hlen = h.len() as u8;
352
1
                w.write_u8(3);
353
1
                w.write_u8(hlen);
354
1
                w.write(h.as_bytes());
355
            }
356
        }
357
3
    }
358
}
359

            
360
#[cfg(test)]
361
mod test {
362
    #![allow(clippy::unwrap_used)]
363
    use super::*;
364
    use hex_literal::hex;
365

            
366
    #[test]
367
    fn socks4_good() {
368
        let mut h = SocksHandshake::default();
369
        let a = h
370
            .handshake(&hex!("04 01 0050 CB007107 00")[..])
371
            .unwrap()
372
            .unwrap();
373
        assert!(a.finished);
374
        assert!(h.finished());
375
        assert_eq!(a.drain, 9);
376
        assert!(a.reply.is_empty()); // no reply -- waiting to see how it goes
377

            
378
        let req = h.into_request().unwrap();
379
        assert_eq!(req.port(), 80);
380
        assert_eq!(req.addr().to_string(), "203.0.113.7");
381
        assert_eq!(req.command(), SocksCmd::CONNECT);
382

            
383
        assert_eq!(
384
            req.reply(
385
                SocksStatus::GENERAL_FAILURE,
386
                Some(&SocksAddr::Ip("127.0.0.1".parse().unwrap()))
387
            ),
388
            hex!("00 5B 0050 7f000001")
389
        );
390
    }
391

            
392
    #[test]
393
    fn socks4a_good() {
394
        let mut h = SocksHandshake::new();
395
        let msg = hex!(
396
            "04 01 01BB 00000001 73776f72646669736800
397
                        7777772e6578616d706c652e636f6d00 99"
398
        );
399
        let a = h.handshake(&msg[..]).unwrap().unwrap();
400
        assert!(a.finished);
401
        assert!(h.finished());
402
        assert_eq!(a.drain, msg.len() - 1);
403
        assert!(a.reply.is_empty()); // no reply -- waiting to see how it goes
404

            
405
        let req = h.into_request().unwrap();
406
        assert_eq!(req.port(), 443);
407
        assert_eq!(req.addr().to_string(), "www.example.com");
408
        assert_eq!(req.auth(), &SocksAuth::Socks4(b"swordfish".to_vec()));
409
        assert_eq!(req.command(), SocksCmd::CONNECT);
410

            
411
        assert_eq!(
412
            req.reply(SocksStatus::SUCCEEDED, None),
413
            hex!("00 5A 0000 00000000")
414
        );
415
    }
416

            
417
    #[test]
418
    fn socks5_init_noauth() {
419
        let mut h = SocksHandshake::new();
420
        let a = h.handshake(&hex!("05 01 00")[..]).unwrap().unwrap();
421
        assert!(!a.finished);
422
        assert_eq!(a.drain, 3);
423
        assert_eq!(a.reply, &[5, 0]);
424
        assert_eq!(h.state, State::Socks5Wait);
425
    }
426

            
427
    #[test]
428
    fn socks5_init_username() {
429
        let mut h = SocksHandshake::new();
430
        let a = h.handshake(&hex!("05 04 00023031")[..]).unwrap().unwrap();
431
        assert!(!a.finished);
432
        assert_eq!(a.drain, 6);
433
        assert_eq!(a.reply, &[5, 2]);
434
        assert_eq!(h.state, State::Socks5Username);
435
    }
436

            
437
    #[test]
438
    fn socks5_init_nothing_works() {
439
        let mut h = SocksHandshake::new();
440
        let a = h.handshake(&hex!("05 02 9988")[..]);
441
        assert!(matches!(a, Ok(Err(Error::NotImplemented))));
442
    }
443

            
444
    #[test]
445
    fn socks5_username_ok() {
446
        let mut h = SocksHandshake::new();
447
        let _a = h.handshake(&hex!("05 02 9902")).unwrap().unwrap();
448
        let a = h
449
            .handshake(&hex!("01 08 5761677374616666 09 24776f726466693568"))
450
            .unwrap()
451
            .unwrap();
452
        assert_eq!(a.drain, 20);
453
        assert_eq!(a.reply, &[1, 0]);
454
        assert_eq!(h.state, State::Socks5Wait);
455
        assert_eq!(
456
            h.socks5_auth.unwrap(),
457
            // _Horse Feathers_, 1932
458
            SocksAuth::Username(b"Wagstaff".to_vec(), b"$wordfi5h".to_vec())
459
        );
460
    }
461

            
462
    #[test]
463
    fn socks5_request_ok_ipv4() {
464
        let mut h = SocksHandshake::new();
465
        let _a = h.handshake(&hex!("05 01 00")).unwrap().unwrap();
466
        let a = h
467
            .handshake(&hex!("05 01 00 01 7f000007 1f90"))
468
            .unwrap()
469
            .unwrap();
470
        assert_eq!(a.drain, 10);
471
        assert!(a.finished);
472
        assert!(a.reply.is_empty());
473
        assert_eq!(h.state, State::Done);
474

            
475
        let req = h.into_request().unwrap();
476
        assert_eq!(req.version(), SocksVersion::V5);
477
        assert_eq!(req.command(), SocksCmd::CONNECT);
478
        assert_eq!(req.addr().to_string(), "127.0.0.7");
479
        assert_eq!(req.port(), 8080);
480
        assert_eq!(req.auth(), &SocksAuth::NoAuth);
481

            
482
        assert_eq!(
483
            req.reply(
484
                SocksStatus::HOST_UNREACHABLE,
485
                Some(&SocksAddr::Hostname(
486
                    "foo.example.com".to_string().try_into().unwrap()
487
                ))
488
            ),
489
            hex!("05 04 00 03 0f 666f6f2e6578616d706c652e636f6d 1f90")
490
        );
491
    }
492

            
493
    #[test]
494
    fn socks5_request_ok_ipv6() {
495
        let mut h = SocksHandshake::new();
496
        let _a = h.handshake(&hex!("05 01 00")).unwrap().unwrap();
497
        let a = h
498
            .handshake(&hex!(
499
                "05 01 00 04 f000 0000 0000 0000 0000 0000 0000 ff11 1f90"
500
            ))
501
            .unwrap()
502
            .unwrap();
503
        assert_eq!(a.drain, 22);
504
        assert!(a.finished);
505
        assert!(a.reply.is_empty());
506
        assert_eq!(h.state, State::Done);
507

            
508
        let req = h.into_request().unwrap();
509
        assert_eq!(req.version(), SocksVersion::V5);
510
        assert_eq!(req.command(), SocksCmd::CONNECT);
511
        assert_eq!(req.addr().to_string(), "f000::ff11");
512
        assert_eq!(req.port(), 8080);
513
        assert_eq!(req.auth(), &SocksAuth::NoAuth);
514

            
515
        assert_eq!(
516
            req.reply(SocksStatus::GENERAL_FAILURE, Some(req.addr())),
517
            hex!("05 01 00 04 f000 0000 0000 0000 0000 0000 0000 ff11 1f90")
518
        );
519
    }
520

            
521
    #[test]
522
    fn socks5_request_ok_hostname() {
523
        let mut h = SocksHandshake::new();
524
        let _a = h.handshake(&hex!("05 01 00")).unwrap().unwrap();
525
        let a = h
526
            .handshake(&hex!("05 01 00 03 0f 666f6f2e6578616d706c652e636f6d 1f90"))
527
            .unwrap()
528
            .unwrap();
529
        assert_eq!(a.drain, 22);
530
        assert!(a.finished);
531
        assert!(a.reply.is_empty());
532
        assert_eq!(h.state, State::Done);
533

            
534
        let req = h.into_request().unwrap();
535
        assert_eq!(req.version(), SocksVersion::V5);
536
        assert_eq!(req.command(), SocksCmd::CONNECT);
537
        assert_eq!(req.addr().to_string(), "foo.example.com");
538
        assert_eq!(req.port(), 8080);
539
        assert_eq!(req.auth(), &SocksAuth::NoAuth);
540

            
541
        assert_eq!(
542
            req.reply(SocksStatus::SUCCEEDED, None),
543
            hex!("05 00 00 01 00000000 0000")
544
        );
545
    }
546

            
547
    #[test]
548
    fn empty_handshake() {
549
        let r = SocksHandshake::new().handshake(&[]);
550
        assert!(matches!(r, Err(Truncated { .. })));
551
    }
552

            
553
    #[test]
554
    fn bad_version() {
555
        let mut h = SocksHandshake::new();
556
        let r = h.handshake(&hex!("06 01 00"));
557
        assert!(matches!(r, Ok(Err(Error::BadProtocol(6)))));
558

            
559
        let mut h = SocksHandshake::new();
560
        let _a = h.handshake(&hex!("05 01 00")).unwrap();
561
        let r = h.handshake(&hex!("06 01 00"));
562
        assert!(r.unwrap().is_err());
563
    }
564

            
565
    #[test]
566
    fn fused_result() {
567
        let good_socks4a = &hex!("04 01 0050 CB007107 00")[..];
568

            
569
        // Can't try again after failure.
570
        let mut h = SocksHandshake::new();
571
        let r = h.handshake(&hex!("06 01 00"));
572
        assert!(r.unwrap().is_err());
573
        let r = h.handshake(good_socks4a);
574
        assert!(matches!(r, Ok(Err(Error::AlreadyFinished(_)))));
575

            
576
        // Can't try again after success
577
        let mut h = SocksHandshake::new();
578
        let r = h.handshake(good_socks4a);
579
        assert!(r.is_ok());
580
        let r = h.handshake(good_socks4a);
581
        assert!(matches!(r, Ok(Err(Error::AlreadyFinished(_)))));
582
    }
583
}