From 2f295c3fdc55a72763723f78ae7dce69b4e74618 Mon Sep 17 00:00:00 2001 From: "B. Blechschmidt" Date: Wed, 22 Mar 2023 12:18:41 +0100 Subject: [PATCH] Use Option type for credentials This commit applys the diff by @ssrlive from https://github.com/blechschmidt/tun2proxy/commit/3223ca4e22003fd87e90f89ce352d84d38227f2e#commitcomment-105521241. --- src/http.rs | 8 ++++---- src/lib.rs | 16 +++++++++++++++- src/main.rs | 21 ++++++++------------- src/socks5.rs | 17 +++++++++-------- src/tun2proxy.rs | 10 ++-------- tests/password.secret | 1 + tests/proxy.rs | 2 +- 7 files changed, 40 insertions(+), 35 deletions(-) create mode 100644 tests/password.secret diff --git a/src/http.rs b/src/http.rs index fe72044..31885b6 100644 --- a/src/http.rs +++ b/src/http.rs @@ -35,7 +35,7 @@ impl HttpConnection { server_outbuf.extend(b" HTTP/1.1\r\nHost: ".iter()); server_outbuf.extend(connection.dst.to_string().as_bytes()); server_outbuf.extend(b"\r\n".iter()); - if credentials.authenticate { + if let Some(credentials) = credentials { server_outbuf.extend(b"Proxy-Authorization: Basic "); let mut auth_plain = credentials.username.clone(); auth_plain.extend(b":".iter()); @@ -165,7 +165,7 @@ impl TcpProxy for HttpConnection { pub struct HttpManager { server: std::net::SocketAddr, - credentials: Credentials, + credentials: Option, } impl ConnectionManager for HttpManager { @@ -192,13 +192,13 @@ impl ConnectionManager for HttpManager { self.server } - fn get_credentials(&self) -> &Credentials { + fn get_credentials(&self) -> &Option { &self.credentials } } impl HttpManager { - pub fn new(server: SocketAddr, credentials: Credentials) -> std::rc::Rc { + pub fn new(server: SocketAddr, credentials: Option) -> std::rc::Rc { std::rc::Rc::new(Self { server, credentials, diff --git a/src/lib.rs b/src/lib.rs index c68e142..256586f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,7 +13,21 @@ pub enum ProxyType { Http, } -pub fn main_entry(tun: &str, addr: SocketAddr, proxy_type: ProxyType, credentials: Credentials) { +impl std::fmt::Display for ProxyType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ProxyType::Socks5 => write!(f, "socks5"), + ProxyType::Http => write!(f, "http"), + } + } +} + +pub fn main_entry( + tun: &str, + addr: SocketAddr, + proxy_type: ProxyType, + credentials: Option, +) { let mut ttp = TunToProxy::new(tun); match proxy_type { ProxyType::Socks5 => { diff --git a/src/main.rs b/src/main.rs index ff7dcec..521c978 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,7 +23,7 @@ struct Args { struct ArgProxy { proxy_type: ProxyType, addr: SocketAddr, - credentials: Credentials, + credentials: Option, } fn proxy_url_parser(s: &str) -> Result { @@ -46,12 +46,11 @@ fn proxy_url_parser(s: &str) -> Result { .ok_or(format!("`{host}` does not resolve to a usable IP address"))?; let credentials = if url.username() == "" && url.password().is_none() { - Credentials::none() + None } else { - Credentials::new( - String::from(url.username()), - String::from(url.password().unwrap_or("")), - ) + let username = String::from(url.username()); + let password = String::from(url.password().unwrap_or("")); + Some(Credentials::new(&username, &password)) }; let scheme = url.scheme(); @@ -75,12 +74,8 @@ fn main() { let args = Args::parse(); let addr = args.proxy.addr; - log::info!("Proxy server: {addr}"); + let proxy_type = args.proxy.proxy_type; + log::info!("Proxy {proxy_type} server: {addr}"); - main_entry( - &args.tun, - args.proxy.addr, - args.proxy.proxy_type, - args.proxy.credentials, - ); + main_entry(&args.tun, addr, proxy_type, args.proxy.credentials); } diff --git a/src/socks5.rs b/src/socks5.rs index 455cab1..76d5a90 100644 --- a/src/socks5.rs +++ b/src/socks5.rs @@ -82,7 +82,7 @@ impl SocksConnection { fn send_client_hello(&mut self) { let credentials = self.manager.get_credentials(); - if credentials.authenticate { + if credentials.is_some() { self.server_outbuf.extend(&[5u8, 1, 2]); } else { self.server_outbuf.extend(&[5u8, 1, 0]); @@ -100,8 +100,8 @@ impl SocksConnection { )); } - if self.server_inbuf[1] != 0 && !self.manager.get_credentials().authenticate - || self.server_inbuf[1] != 2 && self.manager.get_credentials().authenticate + if self.server_inbuf[1] != 0 && self.manager.get_credentials().is_none() + || self.server_inbuf[1] != 2 && self.manager.get_credentials().is_some() { return Err(ProxyError::new( "SOCKS server requires an unsupported authentication method.".into(), @@ -110,7 +110,7 @@ impl SocksConnection { self.server_inbuf.drain(0..2); - if self.manager.get_credentials().authenticate { + if self.manager.get_credentials().is_some() { self.state = SocksState::SendAuthData; } else { self.state = SocksState::SendRequest; @@ -119,7 +119,8 @@ impl SocksConnection { } fn send_auth_data(&mut self) -> Result<(), ProxyError> { - let credentials = self.manager.get_credentials(); + let tmp = Credentials::default(); + let credentials = self.manager.get_credentials().as_ref().unwrap_or(&tmp); self.server_outbuf .extend(&[1u8, credentials.username.len() as u8]); self.server_outbuf.extend(&credentials.username); @@ -285,7 +286,7 @@ impl TcpProxy for SocksConnection { pub struct Socks5Manager { server: std::net::SocketAddr, - credentials: Credentials, + credentials: Option, } impl ConnectionManager for Socks5Manager { @@ -312,13 +313,13 @@ impl ConnectionManager for Socks5Manager { self.server } - fn get_credentials(&self) -> &Credentials { + fn get_credentials(&self) -> &Option { &self.credentials } } impl Socks5Manager { - pub fn new(server: SocketAddr, credentials: Credentials) -> std::rc::Rc { + pub fn new(server: SocketAddr, credentials: Option) -> std::rc::Rc { std::rc::Rc::new(Self { server, credentials, diff --git a/src/tun2proxy.rs b/src/tun2proxy.rs index 6044c0f..a2940ec 100644 --- a/src/tun2proxy.rs +++ b/src/tun2proxy.rs @@ -164,23 +164,17 @@ struct ConnectionState { #[derive(Default, Clone)] pub struct Credentials { - pub(crate) authenticate: bool, pub(crate) username: Vec, pub(crate) password: Vec, } impl Credentials { - pub fn new(username: String, password: String) -> Self { + pub fn new(username: &str, password: &str) -> Self { Self { - authenticate: true, username: username.as_bytes().to_vec(), password: password.as_bytes().to_vec(), } } - - pub fn none() -> Self { - Default::default() - } } pub(crate) trait TcpProxy { @@ -199,7 +193,7 @@ pub(crate) trait ConnectionManager { ) -> Option>; fn close_connection(&self, connection: &Connection); fn get_server(&self) -> SocketAddr; - fn get_credentials(&self) -> &Credentials; + fn get_credentials(&self) -> &Option; } pub(crate) struct TunToProxy<'a> { diff --git a/tests/password.secret b/tests/password.secret new file mode 100644 index 0000000..6e4a57c --- /dev/null +++ b/tests/password.secret @@ -0,0 +1 @@ +JLFE$kz$wJf%&^StSH&D7D5s diff --git a/tests/proxy.rs b/tests/proxy.rs index 0fd4d32..3b7127b 100644 --- a/tests/proxy.rs +++ b/tests/proxy.rs @@ -140,7 +140,7 @@ mod tests { } Ok(Fork::Child) => { prctl::set_death_signal(signal::SIGKILL as isize).unwrap(); // 9 == SIGKILL - main_entry(TUN_TEST_DEVICE, address, ProxyType::Socks5); + main_entry(TUN_TEST_DEVICE, address, ProxyType::Socks5, None); } Err(_) => assert!(false), }