From 752c4819def8582aa06958535c058dc4fb4417f3 Mon Sep 17 00:00:00 2001 From: Raphael Arias Date: Sun, 1 Nov 2015 14:49:16 +0100 Subject: [PATCH 1/3] compiles socks5 in rustc 1.5.0-dev --- src/lib.rs | 17 +++--- src/socks4.rs | 2 +- src/socks4a.rs | 6 +-- src/socks5.rs | 141 ++++++++++++++++++++++++++++++++----------------- 4 files changed, 106 insertions(+), 60 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2ac7bf6..7e28211 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,18 +1,21 @@ #![crate_name = "rustsocks"] #![crate_type = "rlib"] +#![feature(slice_patterns)] +#![feature(ip_addr)] +#![feature(read_exact)] -pub use socks4a::Socks4a; -pub use socks4::Socks4; +//pub use socks4a::Socks4a; +//pub use socks4::Socks4; pub use socks5::Socks5; -pub mod socks4a; -pub mod socks4; +//pub mod socks4a; +//pub mod socks4; pub mod socks5; mod util { - use std::io::{IoResult, IoError, IoErrorKind}; + use std::io::{Result, Error, ErrorKind}; - pub fn io_err(kind: IoErrorKind, desc: &'static str) -> IoResult { - Err(IoError { kind: kind, desc: desc, detail: None }) + pub fn io_err(kind: ErrorKind, desc: &'static str) -> Result { + Err(Error::new(kind, desc)) } } diff --git a/src/socks4.rs b/src/socks4.rs index cea1b22..3e5bca0 100644 --- a/src/socks4.rs +++ b/src/socks4.rs @@ -45,7 +45,7 @@ impl<'a> Socks4<'a> { // request failed because client's identd could not confirm the user ID // string in the request 0x5d => io_err(ConnectionRefused, "Unknown user"), - x => fail!("Unexpected status byte: {}", x) + x => { return io_err(OtherIoError, format!("Unexpected status byte: {}", x)); } } } } diff --git a/src/socks4a.rs b/src/socks4a.rs index 2fe7779..4cb7ce2 100644 --- a/src/socks4a.rs +++ b/src/socks4a.rs @@ -1,6 +1,6 @@ use util::io_err; -use std::io::{IoResult, TcpStream, ConnectionRefused, ConnectionFailed, - OtherIoError}; +use std::io::{Result, OtherIoError}; +use std::net::{TcpStream, ConnectionFailed, ConnectionRefused}; pub struct Socks4a<'a> { socks_host: &'a str, @@ -42,7 +42,7 @@ impl<'a> Socks4a<'a> { // request failed because client's identd could not confirm the user ID // string in the request 0x5d => io_err(ConnectionRefused, "Unknown user"), - x => fail!("Unexpected status byte: {}", x) + x => io_err(OtherIoError, format!("Unexpected status byte: {}", x)) } } } diff --git a/src/socks5.rs b/src/socks5.rs index 9a0e497..4eab234 100644 --- a/src/socks5.rs +++ b/src/socks5.rs @@ -1,13 +1,40 @@ use util::io_err; -use std::io::{IoResult, TcpStream, ConnectionRefused, ConnectionFailed, - OtherIoError}; -use std::io::net::ip::{IpAddr, Ipv4Addr, Ipv6Addr}; +use std::io::{Write, Read, ErrorKind}; +use std::io::Result as IoResult; +use std::net::{IpAddr, TcpStream}; +use std::mem; enum AuthMethod<'s> { NoAuth, UPass(&'s str, &'s str) } +pub trait ReadU8 { + fn read_u8(&mut self) -> IoResult; +} + +impl ReadU8 for TcpStream { + #[inline] + fn read_u8(&mut self) -> IoResult { + let mut buf = [0u8]; + try!(self.read_exact(&mut buf)); + Ok(buf[0]) + } +} + +//pub trait WriteU8 { +// fn read_u8(&mut self) -> IoResult; +//} +// +//impl ReadU8 for TcpStream { +// #[inline] +// fn read_u8(&mut self) -> IoResult { +// let mut buf = [0u8]; +// try!(self.read_exact(&mut buf)); +// Ok(buf[0]) +// } +//} + pub trait Socks5Destination { fn write_destination(&self, &mut TcpStream) -> IoResult<()>; } @@ -15,11 +42,11 @@ pub trait Socks5Destination { impl<'a> Socks5Destination for &'a str { fn write_destination(&self, stream: &mut TcpStream) -> IoResult<()> { if self.len() > 255 { - return io_err(OtherIoError, "Domain length is too long"); + return io_err(ErrorKind::Other, "Domain length is too long"); } - try!(stream.write([0x03, self.len() as u8])); - try!(stream.write_str(*self)); + try!(stream.write(&[0x03, self.len() as u8])); + try!(stream.write(&self.as_bytes())); Ok(()) } } @@ -27,11 +54,19 @@ impl<'a> Socks5Destination for &'a str { impl<'a> Socks5Destination for IpAddr { fn write_destination(&self, stream: &mut TcpStream) -> IoResult<()> { match *self { - Ipv4Addr(a, b, c, d) => try!(stream.write([0x01, a, b, c, d])), - Ipv6Addr(a, b, c, d, e, f, g, h) => { - try!(stream.write_u8(0x04)); - for &pair in [a, b, c, d, e, f, g, h].iter() { - try!(stream.write_be_u16(pair)); + //IpAddr::V4(a, b, c, d) => try!(stream.write_all(&[0x01, a, b, c, d])), + IpAddr::V4(addr) => match addr.octets() { + [a,b,c,d] => try!(stream.write_all(&[0x01, a, b, c, d])) + }, + IpAddr::V6(addr) => match addr.segments() { + [a,b,c,d,e,f,g,h] => { + try!(stream.write_all(&[0x04])); + for &pair in [a, b, c, d, e, f, g, h].iter() { + let mut aux : u16 = pair; + aux = aux.to_be(); + let array : [u8; 2] = unsafe { mem::transmute(aux) }; + try!(stream.write_all(&array)); + } } } } @@ -51,69 +86,73 @@ impl<'a> Socks5<'a> { Socks5 { socks_host: host, socks_port: port, - socks_auth: NoAuth + socks_auth: AuthMethod::NoAuth } } pub fn login(&mut self, uname: &'a str, passwd: &'a str) { - self.socks_auth = UPass(uname, passwd); + self.socks_auth = AuthMethod::UPass(uname, passwd); } pub fn connect(&mut self, destination: T, port: u16) -> IoResult { - let mut stream = try!(TcpStream::connect(self.socks_host, self.socks_port)); - try!(stream.write([0x05u8])); + let mut stream = try!(TcpStream::connect((self.socks_host, self.socks_port))); + try!(stream.write(&[0x05u8])); match self.socks_auth { - NoAuth => { try!(stream.write([0x01u8, 0x00])); }, - UPass(..) => { try!(stream.write([0x01u8, 0x02])); } + AuthMethod::NoAuth => { try!(stream.write(&[0x01u8, 0x00])); }, + AuthMethod::UPass(..) => { try!(stream.write(&[0x01u8, 0x02])); } } if try!(stream.read_u8()) != 0x05 { - return io_err(OtherIoError, "Unexpected SOCKS version number"); + return io_err(ErrorKind::Other, "Unexpected SOCKS version number"); } match try!(stream.read_u8()) { 0x00 => { match self.socks_auth { - NoAuth => { /* Continue */ }, - _ => return io_err(OtherIoError, + AuthMethod::NoAuth => { /* Continue */ }, + _ => return io_err(ErrorKind::Other, "Wrong authentication method from server") } } 0x02 => { match self.socks_auth { - UPass(uname, passwd) => { - try!(stream.write([0x01u8, uname.len() as u8])); - try!(stream.write_str(uname)); - try!(stream.write([passwd.len() as u8])); - try!(stream.write_str(passwd)); + AuthMethod::UPass(uname, passwd) => { + try!(stream.write_all(&[0x01u8, uname.len() as u8])); + //try!(stream.write_str(uname)); + try!(write!(stream, "{}", uname)); + try!(stream.write_all(&[passwd.len() as u8])); + try!(write!(stream, "{}", passwd)); + //try!(stream.write_str(passwd)); if try!(stream.read_u8()) != 0x01 { - return io_err(OtherIoError, + return io_err(ErrorKind::Other, "Invalid authentication version"); } if try!(stream.read_u8()) != 0x00 { - return io_err(ConnectionRefused, "Authentication failed"); + return io_err(ErrorKind::ConnectionRefused, "Authentication failed"); } } - _ => { return io_err(OtherIoError, + _ => { return io_err(ErrorKind::Other, "Wrong authentication method from server"); } } } - 0xFF => { return io_err(ConnectionRefused, + 0xFF => { return io_err(ErrorKind::ConnectionRefused, "Server refused authentication methods"); } - _ => { return io_err(OtherIoError, + _ => { return io_err(ErrorKind::Other, "Wrong authentication method from server"); } } - try!(stream.write([0x05u8, 0x01, 0x00])); + try!(stream.write(&[0x05u8, 0x01, 0x00])); try!(destination.write_destination(&mut stream)); - try!(stream.write_be_u16(port)); + let be_port = port.to_be(); + let array : [u8; 2] = unsafe { mem::transmute(be_port) }; + try!(stream.write_all(&array)); if try!(stream.read_u8()) != 0x05 { - return io_err(OtherIoError, "Invalid SOCKS version number"); + return io_err(ErrorKind::Other, "Invalid SOCKS version number"); } match try!(stream.read_u8()) { @@ -122,32 +161,36 @@ impl<'a> Socks5<'a> { match try!(stream.read_u8()) { 0x01 => { - let mut _ipv4 = [0,.. 4]; - try!(stream.read_at_least(4, &mut _ipv4)); + let mut _ipv4 = [0; 4]; + try!(stream.read_exact(&mut _ipv4)); } 0x03 => { let addrlen = try!(stream.read_u8()); - let _domain = try!(stream.read_exact(addrlen as uint)); + let mut _domain = Vec::with_capacity(addrlen as usize); + try!(stream.read_exact(&mut _domain)); } 0x04 => { - let mut _ipv6 = [0,.. 16]; - try!(stream.read_at_least(16, &mut _ipv6)); + let mut _ipv6 = [0; 16]; + try!(stream.read_exact(&mut _ipv6)); } - _ => return io_err(OtherIoError, "Invalid address type"), + _ => return io_err(ErrorKind::Other, "Invalid address type"), } - let _port = try!(stream.read_be_u16()); + let mut _port_slice : [u8; 2] = [0u8; 2]; + try!(stream.read_exact(&mut _port_slice)); + let _port_be : u16 = unsafe { mem::transmute(_port_slice) }; + let _port = u16::from_be(_port_be); Ok(stream) } - 0x01 => io_err(OtherIoError, "General failure"), - 0x02 => io_err(OtherIoError, "Connection not allowed by ruleset"), - 0x03 => io_err(ConnectionFailed, "Network unreachable"), - 0x04 => io_err(ConnectionFailed, "Host unreachable"), - 0x05 => io_err(ConnectionRefused, "Connection refused by destination"), - 0x06 => io_err(ConnectionFailed, "TTL expired"), - 0x07 => io_err(OtherIoError, "Protocol Error"), - 0x08 => io_err(OtherIoError, "Address type not supported"), - _ => io_err(OtherIoError, "Unknown error") + 0x01 => io_err(ErrorKind::Other, "General failure"), + 0x02 => io_err(ErrorKind::Other, "Connection not allowed by ruleset"), + 0x03 => io_err(ErrorKind::NotConnected, "Network unreachable"), + 0x04 => io_err(ErrorKind::Other, "Host unreachable"), + 0x05 => io_err(ErrorKind::ConnectionRefused, "Connection refused by destination"), + 0x06 => io_err(ErrorKind::Other, "TTL expired"), + 0x07 => io_err(ErrorKind::Other, "Protocol Error"), + 0x08 => io_err(ErrorKind::Other, "Address type not supported"), + _ => io_err(ErrorKind::Other, "Unknown error") } } } From 8f217e709cac2c94774a088e712f473f449049b0 Mon Sep 17 00:00:00 2001 From: Raphael Arias Date: Sun, 1 Nov 2015 16:41:52 +0100 Subject: [PATCH 2/3] minor aesthetic improvements --- src/socks5.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/socks5.rs b/src/socks5.rs index 4eab234..e8696c7 100644 --- a/src/socks5.rs +++ b/src/socks5.rs @@ -55,18 +55,18 @@ impl<'a> Socks5Destination for IpAddr { fn write_destination(&self, stream: &mut TcpStream) -> IoResult<()> { match *self { //IpAddr::V4(a, b, c, d) => try!(stream.write_all(&[0x01, a, b, c, d])), - IpAddr::V4(addr) => match addr.octets() { - [a,b,c,d] => try!(stream.write_all(&[0x01, a, b, c, d])) + IpAddr::V4(addr) => { + try!(stream.write_all(&[0x01])); + try!(stream.write_all(&addr.octets())); }, - IpAddr::V6(addr) => match addr.segments() { - [a,b,c,d,e,f,g,h] => { - try!(stream.write_all(&[0x04])); - for &pair in [a, b, c, d, e, f, g, h].iter() { - let mut aux : u16 = pair; - aux = aux.to_be(); - let array : [u8; 2] = unsafe { mem::transmute(aux) }; - try!(stream.write_all(&array)); - } + IpAddr::V6(addr) => { + let segments = addr.segments(); + try!(stream.write_all(&[0x04])); + for &pair in segments.iter() { + let array : [u8; 2] = unsafe { + mem::transmute(pair.to_be()) + }; + try!(stream.write_all(&array)); } } } From 88c93338a37c7130244c967f472c0f6793944d72 Mon Sep 17 00:00:00 2001 From: Raphael Arias Date: Mon, 2 Nov 2015 00:15:01 +0100 Subject: [PATCH 3/3] remove commented-out code, sorry... --- src/socks5.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/socks5.rs b/src/socks5.rs index e8696c7..894938a 100644 --- a/src/socks5.rs +++ b/src/socks5.rs @@ -22,19 +22,6 @@ impl ReadU8 for TcpStream { } } -//pub trait WriteU8 { -// fn read_u8(&mut self) -> IoResult; -//} -// -//impl ReadU8 for TcpStream { -// #[inline] -// fn read_u8(&mut self) -> IoResult { -// let mut buf = [0u8]; -// try!(self.read_exact(&mut buf)); -// Ok(buf[0]) -// } -//} - pub trait Socks5Destination { fn write_destination(&self, &mut TcpStream) -> IoResult<()>; } @@ -54,7 +41,6 @@ impl<'a> Socks5Destination for &'a str { impl<'a> Socks5Destination for IpAddr { fn write_destination(&self, stream: &mut TcpStream) -> IoResult<()> { match *self { - //IpAddr::V4(a, b, c, d) => try!(stream.write_all(&[0x01, a, b, c, d])), IpAddr::V4(addr) => { try!(stream.write_all(&[0x01])); try!(stream.write_all(&addr.octets()));