Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: Support for GSSApi Authentication for SOCKS5 #41

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
8 changes: 6 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ readme = "README.md"
categories = ["asynchronous", "network-programming"]
keywords = ["tokio", "async", "proxy", "socks", "socks5"]
license = "MIT"
version = "0.5.2"
version = "0.5.3"
authors = ["Yilin Chen <[email protected]>"]
edition = "2018"


[features]
default = ["tokio"]
default = ["tokio", "async-trait"]
tor = []
gssapi = ["async-trait"]

[[example]]
name = "chainproxy"
Expand All @@ -34,10 +36,12 @@ futures-io = { version = "0.3", optional = true }
tokio = { version = "1.0", features = ["io-util", "net"], optional = true }
either = "1"
thiserror = "1.0"
async-trait = { version = "0.1.81", optional = true}

[dev-dependencies]
futures-executor = "0.3"
futures-util = { version = "0.3", default-features = false, features = ["io"] }
tokio = { version = "1.0", features = ["io-util", "rt-multi-thread", "net"] }
once_cell = "1.2.0"
hyper = "0.14"
smol = "2.0.0"
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Asynchronous SOCKS proxy support for Rust.
- [x] `BIND` command
- [ ] `ASSOCIATE` command
- [x] Username/password authentication
- [ ] GSSAPI authentication
- [x] GSSAPI authentication
- [ ] Asynchronous DNS resolution
- [X] Chain proxies ([see example](examples/chainproxy.rs))
- [X] SOCKS4
Expand Down
3 changes: 3 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ pub enum Error {

#[error("Request rejected because the client program and identd report different user-ids")]
InvalidUserIdAuthFailure,

#[error("Gssapi auth failure, code: {0}")]
GssapiAuthFailure(u8),
}

///// Result type of `tokio-socks`
Expand Down
50 changes: 48 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#[cfg(feature = "gssapi")]
use async_trait::async_trait;
use std::{
borrow::Cow,
fmt,
fmt::{self, Debug},
io::Result as IoResult,
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs},
pin::Pin,
Expand Down Expand Up @@ -257,19 +259,63 @@ where
/// Authentication methods
#[derive(Debug)]
enum Authentication<'a> {
Password { username: &'a str, password: &'a str },
Password {
username: &'a str,
password: &'a str,
},
#[cfg(feature = "gssapi")]
Gssapi {
gssapi_authenticator: GssapiAuthenticator<'a>,
},
None,
}

#[cfg(feature = "gssapi")]
pub struct GssapiAuthenticator<'a> {
gssapi_authenticator: &'a dyn GssapiAuthentication,
renegotiate_sec_token: bool,
}

#[cfg(feature = "gssapi")]
impl<'a> GssapiAuthenticator<'a> {
pub fn new(gssapi_authenticator: &'a dyn GssapiAuthentication, renegotiate_sec_token: bool) -> Self {
GssapiAuthenticator {
gssapi_authenticator,
renegotiate_sec_token,
}
}
}

#[cfg(feature = "gssapi")]
impl Debug for GssapiAuthenticator<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "GssapiAuthenticator")
}
}

impl Authentication<'_> {
fn id(&self) -> u8 {
match self {
Authentication::Password { .. } => 0x02,
#[cfg(feature = "gssapi")]
Authentication::Gssapi { .. } => 0x01,
Authentication::None => 0x00,
}
}
}

#[cfg(feature = "gssapi")]
#[async_trait]
pub trait GssapiAuthentication: Send + Sync {
// This method retrieves the security context token,
// server_challenge as None: means return the first init_sec token
// server_challenge as Some(x): means return the resp for the servers challenge
async fn get_security_context(&self, server_challenge: Option<&[u8]>) -> std::result::Result<Vec<u8>, Error>;

// This method performs the subnegotiation step
async fn get_protection_level(&self) -> std::result::Result<Vec<u8>, Error>;
}

mod error;
pub mod io;
pub mod tcp;
Expand Down
Loading