Skip to main content

socks5_impl/server/
auth.rs

1use crate::protocol::{AsyncStreamOperation, AuthMethod, UserKey, handshake::password_method};
2use std::sync::Arc;
3use tokio::net::TcpStream;
4
5/// This trait is for defining the socks5 authentication method.
6///
7/// Pre-defined authentication methods can be found in the [`auth`](crate::server::auth) module.
8///
9/// You can create your own authentication method by implementing this trait. Since GAT is not stabled yet,
10/// [async_trait](https://docs.rs/async-trait/latest/async_trait/index.html) needs to be used.
11///
12/// # Example
13/// ```rust
14/// use socks5_impl::protocol::AuthMethod;
15/// use socks5_impl::server::AuthExecutor;
16/// use tokio::net::TcpStream;
17///
18/// pub struct MyAuth;
19///
20/// #[async_trait::async_trait]
21/// impl AuthExecutor for MyAuth {
22///     fn auth_method(&self) -> AuthMethod {
23///         AuthMethod::from(0x80)
24///     }
25///
26///     async fn execute(&self, stream: &mut TcpStream) -> std::io::Result<bool> {
27///         // do something
28///         Ok(true)
29///     }
30/// }
31/// ```
32#[async_trait::async_trait]
33pub trait AuthExecutor {
34    fn auth_method(&self) -> AuthMethod;
35    async fn execute(&self, stream: &mut TcpStream) -> std::io::Result<bool>;
36}
37
38pub type AuthAdaptor = Arc<dyn AuthExecutor + Send + Sync>;
39
40/// No authentication as the socks5 handshake method.
41#[derive(Debug, Default)]
42pub struct NoAuth;
43
44#[async_trait::async_trait]
45impl AuthExecutor for NoAuth {
46    fn auth_method(&self) -> AuthMethod {
47        AuthMethod::NoAuth
48    }
49
50    async fn execute(&self, _: &mut TcpStream) -> std::io::Result<bool> {
51        Ok(true)
52    }
53}
54
55/// Username and password as the socks5 handshake method.
56#[derive(Debug, Clone)]
57pub struct UserKeyAuth {
58    user_key: UserKey,
59}
60
61impl From<UserKey> for UserKeyAuth {
62    fn from(user_key: UserKey) -> Self {
63        Self { user_key }
64    }
65}
66
67impl From<&UserKey> for UserKeyAuth {
68    fn from(value: &UserKey) -> Self {
69        Self { user_key: value.clone() }
70    }
71}
72
73impl From<(&str, &str)> for UserKeyAuth {
74    fn from(value: (&str, &str)) -> Self {
75        Self::new(value.0, value.1)
76    }
77}
78
79impl UserKeyAuth {
80    pub fn new(username: &str, password: &str) -> Self {
81        let user_key = UserKey::new(username, password);
82        Self { user_key }
83    }
84}
85
86#[async_trait::async_trait]
87impl AuthExecutor for UserKeyAuth {
88    fn auth_method(&self) -> AuthMethod {
89        AuthMethod::UserPass
90    }
91
92    async fn execute(&self, stream: &mut TcpStream) -> std::io::Result<bool> {
93        use password_method::{Request, Response, Status::*};
94        let req = Request::retrieve_from_async_stream(stream).await?;
95
96        let is_equal = req.user_key == self.user_key;
97        let resp = Response::new(if is_equal { Succeeded } else { Failed });
98        resp.write_to_async_stream(stream).await?;
99        if is_equal {
100            Ok(true)
101        } else {
102            Err(std::io::Error::other("username or password is incorrect"))
103        }
104    }
105}