Code Upload

This commit is contained in:
PinkP4nther 2021-08-18 00:08:06 -07:00
commit a879755865
9 changed files with 949 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

180
Cargo.lock generated Normal file
View file

@ -0,0 +1,180 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chunked_transfer"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e"
[[package]]
name = "crc32fast"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
dependencies = [
"cfg-if",
]
[[package]]
name = "flate2"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0"
dependencies = [
"cfg-if",
"crc32fast",
"libc",
"libz-sys",
"miniz_oxide",
]
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "httparse"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68"
[[package]]
name = "libc"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765"
[[package]]
name = "libz-sys"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66"
dependencies = [
"cc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "miniz_oxide"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
dependencies = [
"adler",
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]]
name = "openssl"
version = "0.10.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d9facdb76fec0b73c406f125d44d86fdad818d66fef0531eec9233ca425ff4a"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-sys",
]
[[package]]
name = "openssl-sys"
version = "0.9.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1996d2d305e561b70d1ee0c53f1542833f4e1ac6ce9a6708b6ff2738ca67dc82"
dependencies = [
"autocfg",
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "pkg-config"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "serde"
version = "1.0.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8"
[[package]]
name = "sslrelay"
version = "0.1.0"
dependencies = [
"chunked_transfer",
"flate2",
"httparse",
"openssl",
"toml",
]
[[package]]
name = "toml"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
dependencies = [
"serde",
]
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"

14
Cargo.toml Normal file
View file

@ -0,0 +1,14 @@
[package]
name = "sslrelay"
version = "0.1.0"
authors = ["PinkP4nther <pinkp4nther@protonmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
openssl = "0.10.34"
httparse = "1.4.1"
chunked_transfer = "1.4.0"
flate2 = { version = "1.0.17", features = ["zlib"], default-features = false }
toml = "0.5.8"

7
README.md Normal file
View file

@ -0,0 +1,7 @@
# SSLRelay
A relay I wrote to help with intercepting/modifying TLS encrypted network traffic from an application.
The idea is to generate a certificate and a private key (You may need to generate a CA for your certificate, so that you can tell your system or the application to trust the generated certificate).
Then use this library to continuously rewrite or display encrypted network traffic.
Right now this library is mostly written to target the HTTP over TLS however I would like to make it work seamlessly with any data over TLS/SSL.

View file

@ -0,0 +1,9 @@
[package]
name = "basic"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
sslrelay = {path = "../SSLRelay-lib"}

44
examples/basic/main.rs Normal file
View file

@ -0,0 +1,44 @@
use sslrelay::{self, ConfigType, HandlerCallbacks};
// Handler object
struct Handler;
/*
Callback traits that can be used to read or inject data
into data upstream or downstream.
*/
impl HandlerCallbacks for Handler {
// Request non blocking callback
fn req_nb_callback(&self, _in_data: Vec<u8>) {
println!("[+] Request Non Blocking CallBack!");
}
// Request blocking callback
fn req_b_callback(&self, _in_data: &mut Vec<u8>) {
println!("[+] Request Blocking CallBack!");
}
// Response non blocking callback
fn res_nb_callback(&self, _in_data: Vec<u8>) {
println!("[+] Response Non Blocking CallBack!");
}
// Response blocking callback
fn res_b_callback(&self, _in_data: &mut Vec<u8>) {
println!("[+] Response Blocking CallBack!");
}
}
fn main() {
// Create new SSLRelay object
let mut relay = sslrelay::SSLRelay::new(Handler);
// Load Configuration
relay.load_config(ConfigType::Default);
// Start listening
relay.start();
}

View file

@ -0,0 +1,7 @@
bind_host = "0.0.0.0"
bind_port = "443"
ssl_private_key_path = "./remote.com.key"
ssl_cert_path = "./remote.com.crt"
remote_host = "remote.com"
remote_port = "443"
verbose_level = "2"

View file

@ -0,0 +1,7 @@
bind_host = "0.0.0.0"
bind_port = "443"
ssl_private_key_path = "./ssl.key"
ssl_cert_path = "./ssl.crt"
remote_host = "remote.com"
remote_port = "443"
verbose_level = "2"

680
src/lib.rs Normal file
View file

@ -0,0 +1,680 @@
use openssl::ssl::{SslAcceptor, SslConnector, SslFiletype, SslMethod, SslStream, SslVerifyMode};
use std::io::{self, Read, Write};
use std::net::{TcpListener, TcpStream};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use std::env;
use std::fs;
use toml::Value as TValue;
use chunked_transfer::Decoder;
use flate2::read::GzDecoder;
use httparse::{self, Header};
struct RelayedResponse<'a> {
http_version: Option<u8>,
http_code: Option<u16>,
http_reason: Option<String>,
http_headers: Option<Vec<Header<'a>>>,
http_body: Option<String>,
}
struct RelayRequest<'a> {
http_method: Option<String>,
http_path: Option<String>,
http_version: Option<u8>,
http_headers: Option<Vec<Header<'a>>>,
http_body: Option<String>,
}
#[derive(Clone)]
struct RelayConfig {
bind_host: String,
bind_port: String,
remote_host: String,
remote_port: String,
ssl_private_key_path: String,
ssl_cert_path: String,
verbose_level: i8,
}
pub trait HandlerCallbacks {
fn req_b_callback(&self, _in_data: &mut Vec<u8>){}
fn req_nb_callback(&self, _in_data: Vec<u8>){}
fn res_b_callback(&self, _in_data: &mut Vec<u8>){}
fn res_nb_callback(&self, _in_data: Vec<u8>){}
}
pub enum ConfigType<T> {
Env,
Path(T),
Default,
}
#[derive(Clone)]
pub struct SSLRelay<H>
where
H: HandlerCallbacks + std::marker::Sync + std::marker::Send + 'static,
{
config: Option<RelayConfig>,
handlers: Option<H>,
}
impl<H: HandlerCallbacks + std::marker::Sync + std::marker::Send + 'static> SSLRelay<H> {
pub fn new(handlers: H) -> Self {
SSLRelay {
config: None,
handlers: Some(handlers),
}
}
pub fn load_config(&mut self, config_path: ConfigType<String>) {
self.config = Some(self.load_relay_config(config_path));
}
pub fn start(&mut self) {
let rc_pointer = Arc::new(Mutex::new(self.config.as_ref().unwrap().clone()));
let handler_pointer = Arc::new(Mutex::new(self.handlers.take().unwrap()));
let acceptor = self.setup_ssl_config(self.config.as_ref().unwrap().ssl_private_key_path.clone(), self.config.as_ref().unwrap().ssl_cert_path.clone());
let listener = TcpListener::bind(format!("{}:{}", self.config.as_ref().unwrap().bind_host.clone(), self.config.as_ref().unwrap().bind_port.clone())).unwrap();
for stream in listener.incoming() {
match stream {
Ok(stream) => {
let acceptor = acceptor.clone();
let rc_config = rc_pointer.clone();
let handler = handler_pointer.clone();
thread::spawn(move || {
match acceptor.accept(stream) {
Ok(stream) => {
handle_stream(stream, rc_config, handler);
return 0;
},
Err(e) => {
println!("[Error] {}", e);
return -1;
}
}
});
/*let stream = acceptor.accept(stream).unwrap();
handle_stream(stream, rc_config, handler);*/
},
Err(e) => {println!("[Error] Tcp Connection Failed: {}", e)}
}
}
}
fn load_relay_config(&self, config_path: ConfigType<String>) -> RelayConfig {
let mut resolved_path = String::from("./relay_config.toml");
match config_path {
ConfigType::Path(path) => {
resolved_path = path.clone();
},
ConfigType::Env => {
resolved_path = match env::var("SSLRELAY_CONFIG") {
Ok(p) => p.clone(),
Err(_e) => {
println!("[-] Environmental variable SSLRELAY_CONFIG does not exist.");
std::process::exit(-1);
}
};
},
ConfigType::Default => {}
}
let bytes = fs::read(resolved_path).unwrap();
let config_file = String::from_utf8_lossy(&bytes);
let config_parsed = config_file.parse::<TValue>().unwrap();
let bind_host = config_parsed["bind_host"].to_string().replace("\"", "");
let bind_port = config_parsed["bind_port"].to_string().replace("\"", "");
let ssl_private_key_path = config_parsed["ssl_private_key_path"].to_string().replace("\"", "");
let ssl_cert_path = config_parsed["ssl_cert_path"].to_string().replace("\"", "");
let remote_host = config_parsed["remote_host"].to_string().replace("\"", "");
let remote_port = config_parsed["remote_port"].to_string().replace("\"", "");
let verbose_level = config_parsed["verbose_level"].to_string().replace("\"", "").parse().unwrap();
RelayConfig {
bind_host: bind_host.clone(),
bind_port: bind_port.clone(),
ssl_private_key_path: ssl_private_key_path.clone(),
ssl_cert_path: ssl_cert_path.clone(),
remote_host: remote_host.clone(),
remote_port: remote_port.clone(),
verbose_level: verbose_level,
}
}
fn setup_ssl_config(&self, priv_key: String, cert: String) -> Arc<SslAcceptor> {
let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
acceptor.set_private_key_file(priv_key, SslFiletype::PEM).unwrap();
acceptor.set_certificate_chain_file(cert).unwrap();
acceptor.check_private_key().unwrap();
Arc::new(acceptor.build())
}
}// SSLRelay
#[derive(PartialEq)]
enum StreamDirection {
Upstream,// Data coming from remote host
DownStream,// Data coming from origin host
}
struct DataHandler {
tcp_stream: Option<SslStream<TcpStream>>,
relay_stream: Option<SslStream<TcpStream>>,
remote_host: String,
stream_direction: StreamDirection,
}
impl DataHandler {
fn new(tcp_stream: SslStream<TcpStream>, remote_host: String) -> Self {
let _ = tcp_stream.get_ref().set_read_timeout(Some(Duration::from_millis(100)));
DataHandler {
tcp_stream: Some(tcp_stream),
relay_stream: None,
remote_host,
stream_direction: StreamDirection::DownStream,
}
}
fn get_data_stream(&mut self, data: &mut Vec<u8>) -> usize {
let mut data_length: usize = 0;
if self.stream_direction == StreamDirection::DownStream {
loop {
let mut r_buf = [0; 1024];
match self.tcp_stream.as_mut().unwrap().read(&mut r_buf) {
Ok(bytes_read) => {
if bytes_read == 0 {
break;
} else if bytes_read != 0 && bytes_read <= 1024 {
let mut tmp_buf = r_buf.to_vec();
tmp_buf.truncate(bytes_read);
let _bw = data.write(&tmp_buf).unwrap();
data_length += bytes_read;
} else {
println!("[+] Else hit!!!!!!!!!!!!!!!!!!!!!!");
}
},
Err(e) => {
match e.kind() {
io::ErrorKind::WouldBlock => {
break;
},
_ => {println!("[!!!] Got error: {}",e);}
}
},
}
}
} else if self.stream_direction == StreamDirection::Upstream {
loop {
let mut r_buf = [0; 1024];
match self.relay_stream.as_mut().unwrap().read(&mut r_buf) {
Ok(bytes_read) => {
if bytes_read == 0 {
break;
} else if bytes_read != 0 && bytes_read <= 1024 {
let mut tmp_buf = r_buf.to_vec();
tmp_buf.truncate(bytes_read);
let _bw = data.write(&tmp_buf).unwrap();
data_length += bytes_read;
} else {
println!("[+] Else hit!!!!!!!!!!!!!!!!!!!!!!");
}
},
Err(e) => {
match e.kind() {
io::ErrorKind::WouldBlock => {
break;
},
_ => {println!("[!!!] Got error: {}",e);}
}
},
}
}
}
return data_length;
}
fn http_req_verbose(&self, data: &Vec<u8>, mode: u8) {
let req_info = self.get_request(&data);
let req_header_list = req_info.http_headers.unwrap();
let mut req_header_string = String::new();
for header in req_header_list {
if header.value.to_vec().len() == 0 {continue;}
req_header_string.push_str(format!("[-->] {}: {}\n", header.name, String::from_utf8(header.value.to_vec()).unwrap()).as_str());
}
if mode == 1 {
println!("================================\n[-->] HTTP Version: {}\n[-->] HTTP Method: {} {}\n[-->] HTTP Headers:\n{}\n[-->] HTTP Body:\n{}\n"
,req_info.http_version.unwrap()
,req_info.http_method.unwrap()
,req_info.http_path.unwrap()
,req_header_string
,req_info.http_body.unwrap()
);
} else if mode == 2 {
println!("[Req] {} {}", req_info.http_method.unwrap(), req_info.http_path.unwrap());
}
}
fn http_res_verbose(&self, response_data: &Vec<u8>, mode: u8) {
let res_info = self.get_response(&response_data);
let header_list = res_info.http_headers.unwrap();
let mut header_string = String::new();
for header in header_list {
if header.value.to_vec().len() == 0 {continue;}
header_string.push_str(format!("[<--] {}: {}\n", header.name, String::from_utf8(header.value.to_vec()).unwrap()).as_str());
}
if mode == 1 {
println!("\n[<--] HTTP Version: {}\n[<--] HTTP Code: {} {}\n[<--] HTTP Headers:\n{}\n[<--] HTTP Body:\n{}\n================================\n"
,res_info.http_version.unwrap()
,res_info.http_code.unwrap()
,res_info.http_reason.unwrap()
,header_string
,res_info.http_body.unwrap()
);
} else if mode == 2 {
println!("[Res] {} {}", res_info.http_code.unwrap(), res_info.http_reason.unwrap());
}
}
fn relay_data(&mut self, data: &Vec<u8>) -> Option<i8> {
let mut retries = 3;
loop {
let mut sslbuild = SslConnector::builder(SslMethod::tls()).unwrap();
sslbuild.set_verify(SslVerifyMode::NONE);
let connector = sslbuild.build();
let stream = TcpStream::connect(&self.remote_host).unwrap();
let _ = stream.set_read_timeout(Some(Duration::from_millis(500)));
let mut stream = match connector.connect(&self.remote_host, stream) {
Ok(s) => s,
Err(e) => {
println!("[Error] {}", e);
if retries == 0 {
println!("[!] Request relay retries: 0");
return None;
}
retries -= 1;
continue;
}
};
stream.write_all(&data).unwrap();
let _ = stream.flush();
//println!("[+] Relayed -> {}", host);
//return Some(stream); Instead of returning we will now set stream object
self.relay_stream = Some(stream);
return Some(0);
}
}
/*
fn get_req_headers<'a>(&self, data: &'a Vec<u8>) -> Option<Vec<Header<'a>>> {
let mut headers = [httparse::EMPTY_HEADER; 128];
let mut request = httparse::Request::new(&mut headers);
let req = request.parse(data).unwrap();
if req.is_complete() {
return Some(headers.to_vec());
}
None
}
fn get_res_headers(data: &Vec<u8>) -> Option<Vec<Header>> {
let mut headers = [httparse::EMPTY_HEADER; 128];
let mut response = httparse::Response::new(&mut headers);
let res = response.parse(data).unwrap();
if res.is_complete() {
return Some(headers.to_vec());
}
None
}
fn get_host(&self, data: &Vec<u8>) -> Option<String> {
return Some("137.220.37.67".to_string());
let mut headers = [httparse::EMPTY_HEADER; 128];
let mut request = httparse::Request::new(&mut headers);
let req = request.parse(data).unwrap();
if req.is_complete() {
for header in headers.iter() {
if header.name == "Host" || header.name == "host" {
//println!("Host -> {}", String::from_utf8(header.value.to_vec()).unwrap());
return Some(String::from_utf8(header.value.to_vec()).unwrap());
}
}
None
} else if req.is_partial() {
for header in headers.iter() {
if header.name == "Host" || header.name == "host" {
//println!("Host -> {}", String::from_utf8(header.value.to_vec()).unwrap());
return Some(String::from_utf8(header.value.to_vec()).unwrap());
}
}
None
} else {
None
}
}
fn get_cookie(&self, data: &Vec<u8>) -> Option<String> {
let mut headers = [httparse::EMPTY_HEADER; 128];
let mut request = httparse::Request::new(&mut headers);
let req = request.parse(data).unwrap();
if req.is_complete() {
for header in headers.iter() {
if header.name == "Cookie" || header.name == "cookie" {
//println!("Host -> {}", String::from_utf8(header.value.to_vec()).unwrap());
return Some(String::from_utf8(header.value.to_vec()).unwrap());
}
}
None
} else if req.is_partial() {
for header in headers.iter() {
if header.name == "Cookie" || header.name == "cookie" {
//println!("Host -> {}", String::from_utf8(header.value.to_vec()).unwrap());
return Some(String::from_utf8(header.value.to_vec()).unwrap());
}
}
None
} else {
None
}
}
*/
fn get_response<'a>(&self, data: &'a Vec<u8>) -> RelayedResponse<'a> {
let mut headers = [httparse::EMPTY_HEADER; 128];
let mut res = httparse::Response::new(&mut headers);
let res_chk = res.parse(data);
loop {
if !res_chk.unwrap().is_complete() {
thread::sleep(Duration::from_millis(100));
continue;
}
let reason = match res.reason {
Some(r) => Some(r.to_string()),
None => None,
};
let header_vec = res.headers.to_vec();
let body = self.get_http_body(&data, header_vec).unwrap_or(String::from("[-] Failed to get http response body!").into_bytes());
let string_body = String::from_utf8(body).unwrap();
return RelayedResponse {
http_version: res.version,
http_code: res.code,
http_reason: reason,
http_headers: Some(headers.to_vec()),
http_body: Some(string_body),
};
}
}
fn get_request<'a>(&self, data: &'a Vec<u8>) -> RelayRequest<'a> {
let mut headers = [httparse::EMPTY_HEADER; 128];
let mut req = httparse::Request::new(&mut headers);
let req_chk = req.parse(data);
loop {
if !req_chk.unwrap().is_complete() {
thread::sleep(Duration::from_millis(100));
continue;
}
let method = match req.method {
Some(r) => Some(r.to_string()),
None => None,
};
let path = match req.path {
Some(p) => Some(p.to_string()),
None => None,
};
let header_vec = req.headers.to_vec();
let body = self.get_http_body(&data, header_vec).unwrap_or(String::from("[-] Failed to get http request body!").into_bytes());
let string_body = String::from_utf8(body).unwrap();
return RelayRequest {
http_method: method,
http_path: path,
http_version: req.version,
http_headers: Some(headers.to_vec()),
http_body: Some(string_body),
};
}
}
fn get_http_body(&self, data: &Vec<u8>, headers: Vec<Header>) -> Option<Vec<u8>> {
let mut cl: u64 = 0;
let encoding_check = headers.clone();
for header in headers {
if header.name == "Content-Length" || header.name == "content-length" {
let length = match String::from_utf8(header.value.to_vec()) {
Ok(s) => s,
Err(e) => {
println!("[!] ERROR: {}",e);
return None;
},
};
cl += length.parse::<u64>().unwrap();
let mut r_body = data.to_vec();
r_body.reverse();
r_body.truncate(cl as usize);
r_body.reverse();
return Some(r_body);
} else if header.name == "Transfer-Encoding" || header.name == "transfer-encoding" {
let te_string = String::from_utf8(header.value.to_vec()).unwrap();
if te_string == "chunked" {
let mut new_vec = data.to_vec();
let new_vec_iter = new_vec.to_vec();
let mut new_vec_iter = new_vec_iter.iter();
let mut i = 0;
loop {
if let Some(&0x0d) = new_vec_iter.next() {
i += 1;
if let Some(&0x0a) = new_vec_iter.next() {
i += 1;
if let Some(&0x0d) = new_vec_iter.next() {
i += 1;
if let Some(&0x0a) = new_vec_iter.next() {
i += 1;
break;
} else {i += 1;}
} else {i += 1;}
} else {i += 1;}
} else {i += 1;}
}
new_vec.reverse();
new_vec.truncate(data.len() - i);
new_vec.reverse();
let mut decoder = Decoder::new(new_vec.as_slice());
let mut blob = Vec::new();
let _ = decoder.read_to_end(&mut blob);
let mut g_encoded = false;
for header in encoding_check {
if header.name == "Content-Encoding" || header.name == "content-encoding" {
let s = String::from_utf8(header.value.to_vec()).unwrap();
if s == "gzip" {
g_encoded = true;
}
}
}
if g_encoded {
let mut gzd = GzDecoder::new(&blob[..]);
let mut unzipped = Vec::new();
match gzd.read_to_end(&mut unzipped) {
Ok(_) => {},
Err(_) => return None,
}
return Some(unzipped);
} else {
return Some(blob);
}
}
}
}
return Some(String::from("None").into_bytes());
}
} // DataHandler
/* Rewrite this to handle TCP connections until TCP connection is dropped instead of dropping it */
fn handle_stream<H: HandlerCallbacks + std::marker::Sync + std::marker::Send + 'static>(tcp_stream: SslStream<TcpStream>, rc_config: Arc<Mutex<RelayConfig>>, handlers: Arc<Mutex<H>>) {
let conf_lock = rc_config.lock().unwrap();
let remote_host = format!("{}:{}", conf_lock.remote_host, conf_lock.remote_port);
let verbose_mode = conf_lock.verbose_level;
drop(conf_lock);
let mut datahandler = DataHandler::new(tcp_stream, remote_host);
let mut data = Vec::<u8>::new();
let mut response_data = Vec::<u8>::new();
let data_size = datahandler.get_data_stream(&mut data);
if data_size == 0 {
println!("[!] Got 0 bytes closing tcp stream!");
return;
}
if verbose_mode == 1 {
datahandler.http_req_verbose(&data, 1);
} else if verbose_mode == 2 {
datahandler.http_req_verbose(&data, 2);
}
let handlers_p = handlers.clone();
let d = data.clone();
thread::spawn(move || {
let handlers_lock = handlers_p.lock().unwrap();
handlers_lock.req_nb_callback(d);
drop(handlers_lock);
});
let handlers_p = handlers.clone();
let handlers_lock = handlers_p.lock().unwrap();
handlers_lock.req_b_callback(&mut data);
drop(handlers_lock);
match datahandler.relay_data(&data) {
Some(_relay_success) => {},
None => {
println!("[-] relay_data failed!");
return;
}
}
// Get Upstream Data
datahandler.stream_direction = StreamDirection::Upstream;
let _response_size = datahandler.get_data_stream(&mut response_data);
if verbose_mode == 1 {
datahandler.http_res_verbose(&response_data, 1);
} else if verbose_mode == 2 {
datahandler.http_res_verbose(&response_data, 2);
}
// Switch back to DownStream mode to relay data from remote host back to origin host
datahandler.stream_direction = StreamDirection::DownStream;
let handlers_p = handlers.clone();
let d = response_data.clone();
thread::spawn(move || {
let handlers_lock = handlers_p.lock().unwrap();
handlers_lock.res_nb_callback(d);
drop(handlers_lock);
});
let handlers_p = handlers.clone();
let handlers_lock = handlers_p.lock().unwrap();
handlers_lock.res_b_callback(&mut response_data);
drop(handlers_lock);
datahandler.tcp_stream.as_mut().unwrap().write_all(&response_data).unwrap();
let _ = datahandler.tcp_stream.as_mut().unwrap().flush();
}