From 1589f9977d554fd8087e90bc67eb2f6f5bec04d7 Mon Sep 17 00:00:00 2001 From: meltyness <86126050+meltyness@users.noreply.github.com> Date: Mon, 21 Oct 2024 14:55:17 -0500 Subject: [PATCH 1/7] Refactor error packet to session-associated procedure --- src/lib.rs | 50 ++++++++++++++++++++++++++++++++++++++++-- src/main.rs | 63 +++++++++++++++++++++++++---------------------------- 2 files changed, 78 insertions(+), 35 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 025d57c..ebcaab3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ // (C) 2024 - T.J. Hampton // -use std::{fmt, io::Read, net::TcpStream}; +use std::{fmt, io::Read, io::Write, net::TcpStream}; const TACP_HEADER_MAX_LENGTH: usize = 12; // 12 bytes. /// This macro generates a fn, from_byte for @@ -668,9 +668,55 @@ pub struct RTAcctPacket { } -struct RTAuthenSess { +pub struct RTAuthenSess<'a> { rt_curr_seqno : u8, // 1-255, always rx odd tx even, session ends if a wrap occurs rt_my_sessid : u32, + rt_key : &'a str, +} + +impl<'a> RTAuthenSess<'a> { + pub fn from_header(r: &RTHeader, key: &'a str) -> Self { + Self { rt_curr_seqno: r.tacp_hdr_seqno, + rt_my_sessid: r.tacp_hdr_sesid, + rt_key: key, + } + } + + pub fn next_header(&mut self, reply: &RTAuthenReplyPacket) -> RTHeader { + return RTHeader::get_resp_header(self.rt_my_sessid, &reply, self.rt_curr_seqno) + } + + pub fn send_error_packet(&mut self, stream: &mut TcpStream) -> Result { + let generic_error = RTAuthenReplyPacket::get_error_packet(); + let generic_error_header: RTHeader = self.next_header(&generic_error); + + let pad = generic_error_header.compute_md5_pad( self.rt_key ); + let mut payload = md5_xor(&generic_error.serialize(), &pad); + let mut msg = generic_error_header.serialize(); + msg.append(&mut payload); + + // It's just a header, it shouldn't reveal anything interesting. + match stream.write(&msg) { + Ok(v) => { + println!("Ratchet Debug: Sent {} bytes", v); + self.inc_seqno(); + Ok(true) + }, + Err(e) => { + println!("Ratchet Error: TCP Error, {}", e); + Err("Bad TCP Session") + }, + } + } + + fn inc_seqno(&mut self) -> Result { + if self.rt_curr_seqno == 255 { + return Err("Session restart"); + } else { + self.rt_curr_seqno += 1; + return Ok(true); + } + } } #[allow(clippy::indexing_slicing)] diff --git a/src/main.rs b/src/main.rs index ace76bb..462775f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,6 +22,7 @@ use std::time::Instant; use precis_profiles::precis_core::profile::Profile; use precis_profiles::UsernameCasePreserved; +use ratchet::RTAuthenSess; use ratchet::RTHeader; use ratchet::RTTACType; use ratchet::RTAuthenPacket; @@ -128,7 +129,6 @@ pub fn main() { } } - let generic_error = RTAuthenReplyPacket::get_error_packet().serialize(); println!("Ratchet Info: NOWLISTENING bound to some port 49"); @@ -200,22 +200,24 @@ pub fn main() { }, Err(e) => { println!("Ratchet Error: {}", e); - rt_send_error_packet(&generic_error, &mut stream); + //authen_sess.send_error_packet( &mut stream); continue; }, }; + let mut authen_sess = RTAuthenSess::from_header(&hdr, SECRET_KEY); + // Stage 2: Parse packet, perform appropriate treatment let contents = match hdr.tacp_hdr_type { RTTACType::TAC_PLUS_AUTHEN => hdr.parse_authen_packet(&mut stream, SECRET_KEY), RTTACType::TAC_PLUS_AUTHOR => { println!("Ratchet Debug: Not Implemented"); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; }, RTTACType::TAC_PLUS_ACCT => { println!("Ratchet Debug: Not Implemented"); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; }, }; @@ -223,7 +225,7 @@ pub fn main() { let decoded: RTDecodedPacket = match contents { Err(e) => { println!("Ratchet Error: {}", e); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; } Ok(d) => { @@ -245,6 +247,8 @@ pub fn main() { println!("Ratchet Info: Decoded: {}", asp); // (sort of) Authenticate the server before putting a cred on the line let mut retries = 0; + + // Stage 1: Fetch the Username let obtained_username; if asp.user.len() == 0 { // have to fetch username let get_user_packet = RTAuthenReplyPacket::get_getuser_packet(); @@ -279,7 +283,7 @@ pub fn main() { }, Err(e) => { println!("Ratchet Error: {}", e); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; }, }; @@ -288,12 +292,12 @@ pub fn main() { RTTACType::TAC_PLUS_AUTHEN => user_hdr.parse_authen_packet(&mut stream, SECRET_KEY), RTTACType::TAC_PLUS_AUTHOR => { println!("Ratchet Debug: Not Implemented"); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; }, RTTACType::TAC_PLUS_ACCT => { println!("Ratchet Debug: Not Implemented"); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; }, }; @@ -301,7 +305,7 @@ pub fn main() { let decoded_user: RTDecodedPacket = match user_contents { Err(e) => { println!("Ratchet Error: {}", e); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; } Ok(d) => { @@ -320,7 +324,7 @@ pub fn main() { }, _ => { println!("Ratchet Error: Unexpected packet type in ASCII Authentication sequence"); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; }, } @@ -328,7 +332,7 @@ pub fn main() { _ => { println!("Ratchet Error: Non authen packet in Authen sequence"); println!("Ratchet Error: Unexpected packet type in ASCII Authentication sequence"); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; }, } @@ -336,7 +340,9 @@ pub fn main() { obtained_username = asp.user; } + // Stage 2: Fetch the Password // TODO: Everybody gets one + let get_password_packet = RTAuthenReplyPacket::get_getpass_packet(); // TODO: Refactor this mantra into a neatly architected thingamajig @@ -371,7 +377,7 @@ pub fn main() { }, Err(e) => { println!("Ratchet Error: {}", e); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; }, }; @@ -380,12 +386,12 @@ pub fn main() { RTTACType::TAC_PLUS_AUTHEN => pass_hdr.parse_authen_packet(&mut stream, SECRET_KEY), RTTACType::TAC_PLUS_AUTHOR => { println!("Ratchet Debug: Not Implemented"); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; }, RTTACType::TAC_PLUS_ACCT => { println!("Ratchet Debug: Not Implemented"); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; }, }; @@ -393,7 +399,7 @@ pub fn main() { let decoded_pass: RTDecodedPacket = match pass_contents { Err(e) => { println!("Ratchet Error: {}", e); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; } Ok(d) => { @@ -411,18 +417,19 @@ pub fn main() { }, _ => { println!("Ratchet Error: Unexpected packet type in ASCII Authentication sequence"); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; }, } }, _ => { println!("Ratchet Error: Unexpected packet type in ASCII Authentication sequence"); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; }, } - + + // TODO: BIG CODE DUPLICATION // TODO: BIG CODE DUPLICATION // TODO: BIG CODE DUPLICATION @@ -443,7 +450,7 @@ pub fn main() { }, Err(e) => { println!("Ratchet Error: Invalid username passed, {}", e); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; }, } @@ -517,7 +524,7 @@ pub fn main() { }, Err(e) => { println!("Ratchet Error: Invalid username passed, {}", e); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; }, } @@ -582,19 +589,19 @@ pub fn main() { }, RTAuthenPacket::RTAuthenReplyPacket(rtauthen_reply_packet) => { println!("Ratchet Error: umm... no, I'M the server."); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; }, RTAuthenPacket::RTAuthenContinuePacket(rtauthen_continue_packet) => { println!("Ratchet Error: Unexpected continue packet!!"); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; }, // _ => println!("Unknown Authen Packet Format"), } _ => { println!("Unknown Packet Format"); - rt_send_error_packet(&generic_error, &mut stream); + authen_sess.send_error_packet( &mut stream); continue; }, } @@ -658,16 +665,6 @@ unsafe fn rt_get_runs() -> f64 { return RUNS; } -fn rt_send_error_packet(msg: &[u8], stream: &mut TcpStream) { - // It's just a header, it shouldn't reveal anything interesting. - match stream.write(msg) { - Ok(v) => println!("Ratchet Debug: Sent {} bytes", v), - Err(e) => //{ - println!("Ratchet Error: TCP Error, {}", e), - //}, - } -} - fn rt_get_user_name() -> String { return match if cfg!(target_os = "windows") { Command::new("cmd") From fad241b214ab040ba50b72b44b90c4fc5d555714 Mon Sep 17 00:00:00 2001 From: meltyness <86126050+meltyness@users.noreply.github.com> Date: Mon, 21 Oct 2024 15:56:16 -0500 Subject: [PATCH 2/7] Refactor session-handling code mostly --- src/lib.rs | 126 ++++++++++++++++++++-- src/main.rs | 293 ++++++++-------------------------------------------- 2 files changed, 160 insertions(+), 259 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ebcaab3..2da9130 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,12 +73,12 @@ impl RTHeader { /// TOOD: Do we want to abstract the session beyond the behaviors specified /// in the main loop? why? /// - pub fn get_resp_header(ses : u32, r : &RTAuthenReplyPacket, cur_seq: u8) -> Self { + pub fn get_resp_header(ses : u32, r : &RTAuthenReplyPacket, cur_seq: u8, version: u8) -> Self { #[allow(clippy::cast_possible_truncation)] let lt = r.serialize().len() as u32; let seq_no = cur_seq + 1; Self { - tacp_hdr_version: RTTACVersion::TAC_PLUS_MINOR_VER_ONE, + tacp_hdr_version: RTTACVersion::from_byte(version).expect("We only ingest valid versions"), tacp_hdr_type: RTTACType::TAC_PLUS_AUTHEN, tacp_hdr_seqno: seq_no, tacp_hdr_flags: 0, @@ -127,7 +127,7 @@ impl RTHeader { let ret = Self { tacp_hdr_version: RTTACVersion::from_byte(hdr_buf[0])?, tacp_hdr_type: RTTACType::from_byte(hdr_buf[1])?, - tacp_hdr_seqno: match hdr_buf[2] { exp_seq => Ok(exp_seq), _ => Err("Invalid initial sequence number")}?, + tacp_hdr_seqno: (if hdr_buf[2] == exp_seq { Ok(exp_seq) } else {Err("Invalid initial sequence number")})?, tacp_hdr_flags: match hdr_buf[3] { TAC_PLUS_NULL_FLAG => Ok(0), _ => Err("Single-session Mode Not Implemented, must be encrypted.")}?, tacp_hdr_sesid: read_be_u32(&mut &hdr_buf[4..8]).map_or(Err("read_be_u32 can only process 4-slices"), Ok)?, tacp_hdr_length: read_be_u32(&mut &hdr_buf[8..12]).map_or(Err("read_be_u32 can only process 4-slices"), Ok)?, @@ -671,6 +671,7 @@ pub struct RTAcctPacket { pub struct RTAuthenSess<'a> { rt_curr_seqno : u8, // 1-255, always rx odd tx even, session ends if a wrap occurs rt_my_sessid : u32, + rt_my_version : u8, rt_key : &'a str, } @@ -678,16 +679,104 @@ impl<'a> RTAuthenSess<'a> { pub fn from_header(r: &RTHeader, key: &'a str) -> Self { Self { rt_curr_seqno: r.tacp_hdr_seqno, rt_my_sessid: r.tacp_hdr_sesid, + rt_my_version: (r.tacp_hdr_version.clone() as u8), rt_key: key, } } pub fn next_header(&mut self, reply: &RTAuthenReplyPacket) -> RTHeader { - return RTHeader::get_resp_header(self.rt_my_sessid, &reply, self.rt_curr_seqno) + return RTHeader::get_resp_header(self.rt_my_sessid, &reply, self.rt_curr_seqno, self.rt_my_version) } - pub fn send_error_packet(&mut self, stream: &mut TcpStream) -> Result { - let generic_error = RTAuthenReplyPacket::get_error_packet(); + pub fn do_get(&mut self, mut stream: &mut TcpStream, get_user_packet: RTAuthenReplyPacket) -> Result { + // TODO: Refactor this mantra into a neatly architected thingamajig + // ... maybe the 'outermost' detail needed is the session info (i.e., expected pack number, expected sesid), so + // ... it should be a part of a session implementation for the full transaction. + let user_resp_hdr = self.next_header(&get_user_packet); + println!("Ratchet Debug: {:#?}", user_resp_hdr); + println!("Ratchet Debug: {:#?}", get_user_packet); + let pad = user_resp_hdr.compute_md5_pad( self.rt_key ); + let mut payload = md5_xor(&get_user_packet.serialize(), &pad); + let mut msg = user_resp_hdr.serialize(); + msg.append(&mut payload); + + println!("{:?}", msg); + // TODO: This blocks + match stream.write(&msg) { + Ok(v) => { + if self.inc_seqno().is_err() { return Err("Wrapped sequence number, restart single-session") } + println!("Ratchet Debug: Sent {} bytes", v) + }, + Err(e) => + println!("Ratchet Error: TCP Error, {}", e), + //}, + } + + // TODO: Ok... session loop is starting over...? Not really it's a sequence .... hmmmmmmmmm... + let user_hdr: RTHeader = match RTHeader::parse_init_header(&mut stream, self.rt_curr_seqno) { + Ok(h) => { + //println!("Ratchet Debug: Processed {:#?}", h); + if self.inc_seqno().is_err() { return Err("Wrapped sequence number, restart single-session") } + h + }, + Err(e) => { + println!("Ratchet Error: {}", e); + self.send_error_packet( &mut stream); + return Err("Bad header from client"); + }, + }; + + let user_contents = match user_hdr.tacp_hdr_type { + RTTACType::TAC_PLUS_AUTHEN => user_hdr.parse_authen_packet(&mut stream, self.rt_key), + RTTACType::TAC_PLUS_AUTHOR => { + println!("Ratchet Debug: Not Implemented"); + self.send_error_packet( &mut stream); + return Err("Unexpected Authorization reply from client"); + }, + RTTACType::TAC_PLUS_ACCT => { + println!("Ratchet Debug: Not Implemented"); + self.send_error_packet( &mut stream); + return Err("Unexpected Accounting reply from client"); + }, + }; + + let decoded_user: RTDecodedPacket = match user_contents { + Err(e) => { + println!("Ratchet Error: {}", e); + self.send_error_packet( &mut stream); + return Err("Invalid data passed in GetUser body"); + } + Ok(d) => { + //println!("Ratchet Debug: Processed {:#?}", d); + d + }, + }; + + println!("Ratchet Debug: Deciding on decoded user packet"); + match decoded_user { + RTDecodedPacket::RTAuthenPacket(rtauthen_user_packet) => { + println!("Ratchet Debug: Was authen packet, checking for Continue"); + match rtauthen_user_packet { + RTAuthenPacket::RTAuthenContinuePacket(rtauthen_continue_packet) => { + Ok(String::from_utf8_lossy(&rtauthen_continue_packet.user_msg.clone()).to_string()) + }, + _ => { + println!("Ratchet Error: Unexpected packet type in ASCII Authentication sequence"); + self.send_error_packet( &mut stream); + return Err("Invalid data passed in GetUser body"); + }, + } + }, + _ => { + println!("Ratchet Error: Non authen packet in Authen sequence"); + println!("Ratchet Error: Unexpected packet type in ASCII Authentication sequence"); + self.send_error_packet( &mut stream); + return Err("Invalid data passed in GetUser body"); + }, + } + } + + pub fn send_final_packet(&mut self, stream: &mut TcpStream, generic_error: RTAuthenReplyPacket) -> Result { let generic_error_header: RTHeader = self.next_header(&generic_error); let pad = generic_error_header.compute_md5_pad( self.rt_key ); @@ -699,7 +788,7 @@ impl<'a> RTAuthenSess<'a> { match stream.write(&msg) { Ok(v) => { println!("Ratchet Debug: Sent {} bytes", v); - self.inc_seqno(); + if self.inc_seqno().is_err() { return Err("Wrapped sequence number, restart single-session") } Ok(true) }, Err(e) => { @@ -709,6 +798,29 @@ impl<'a> RTAuthenSess<'a> { } } + pub fn send_error_packet(&mut self, stream: &mut TcpStream) -> bool { + let generic_error = RTAuthenReplyPacket::get_error_packet(); + let generic_error_header: RTHeader = self.next_header(&generic_error); + + let pad = generic_error_header.compute_md5_pad( self.rt_key ); + let mut payload = md5_xor(&generic_error.serialize(), &pad); + let mut msg = generic_error_header.serialize(); + msg.append(&mut payload); + + // It's just a header, it shouldn't reveal anything interesting. + match stream.write(&msg) { + Ok(v) => { + println!("Ratchet Debug: Sent {} bytes", v); + if self.inc_seqno().is_err() { return false } + true + }, + Err(e) => { + println!("Ratchet Error: TCP Error, {}", e); + false + }, + } + } + fn inc_seqno(&mut self) -> Result { if self.rt_curr_seqno == 255 { return Err("Session restart"); diff --git a/src/main.rs b/src/main.rs index 462775f..bd2e979 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,8 +14,6 @@ use std::process::exit; use std::process::Command; use std::collections::HashMap; use std::net::TcpListener; -use std::net::TcpStream; -use std::io::Write; use std::time::Duration; use std::time::Instant; @@ -26,10 +24,8 @@ use ratchet::RTAuthenSess; use ratchet::RTHeader; use ratchet::RTTACType; use ratchet::RTAuthenPacket; -use ratchet::md5_xor; use ratchet::RTDecodedPacket; use ratchet::RTAuthenReplyPacket; -use ratchet::RTAuthenContinuePacket; const SECRET_KEY: &str = "testing123"; // TODO: When building a red-black tree of clients, //ensure that they are required to have a secret, or not clients. @@ -243,201 +239,48 @@ pub fn main() { // TODO: This can hang forever with a misbehaving client, // ... the server must be multithreaded or implement read/write timeout. // ... better to go multithreaded. - let mut cur_seq = 1; // We received one. println!("Ratchet Info: Decoded: {}", asp); // (sort of) Authenticate the server before putting a cred on the line let mut retries = 0; // Stage 1: Fetch the Username - let obtained_username; - if asp.user.len() == 0 { // have to fetch username - let get_user_packet = RTAuthenReplyPacket::get_getuser_packet(); - - // TODO: Refactor this mantra into a neatly architected thingamajig - // ... maybe the 'outermost' detail needed is the session info (i.e., expected pack number, expected sesid), so - // ... it should be a part of a session implementation for the full transaction. - let user_resp_hdr = RTHeader::get_v0_header(hdr.tacp_hdr_sesid, &get_user_packet, cur_seq); - cur_seq += 1; - println!("Ratchet Debug: {:#?}", user_resp_hdr); - println!("Ratchet Debug: {:#?}", get_user_packet); - let pad = user_resp_hdr.compute_md5_pad( SECRET_KEY ); - let mut payload = md5_xor(&get_user_packet.serialize(), &pad); - let mut msg = user_resp_hdr.serialize(); - msg.append(&mut payload); - - println!("{:?}", msg); - // TODO: This blocks - match stream.write(&msg) { - Ok(v) => println!("Ratchet Debug: Sent {} bytes", v), - Err(e) => - println!("Ratchet Error: TCP Error, {}", e), - //}, - } - - // TODO: Ok... session loop is starting over...? Not really it's a sequence .... hmmmmmmmmm... - let user_hdr: RTHeader = match RTHeader::parse_init_header(&mut stream, cur_seq) { - Ok(h) => { - //println!("Ratchet Debug: Processed {:#?}", h); - cur_seq += 1; - h - }, - Err(e) => { - println!("Ratchet Error: {}", e); - authen_sess.send_error_packet( &mut stream); - continue; - }, - }; - - let user_contents = match user_hdr.tacp_hdr_type { - RTTACType::TAC_PLUS_AUTHEN => user_hdr.parse_authen_packet(&mut stream, SECRET_KEY), - RTTACType::TAC_PLUS_AUTHOR => { - println!("Ratchet Debug: Not Implemented"); - authen_sess.send_error_packet( &mut stream); - continue; - }, - RTTACType::TAC_PLUS_ACCT => { - println!("Ratchet Debug: Not Implemented"); - authen_sess.send_error_packet( &mut stream); + let obtained_username= if asp.user.len() == 0 { // have to fetch username + match authen_sess.do_get(&mut stream, RTAuthenReplyPacket::get_getuser_packet()) { + Ok(u) => u, + Err(_) => { + authen_sess.send_error_packet(&mut stream); continue; }, - }; - - let decoded_user: RTDecodedPacket = match user_contents { - Err(e) => { - println!("Ratchet Error: {}", e); - authen_sess.send_error_packet( &mut stream); - continue; - } - Ok(d) => { - //println!("Ratchet Debug: Processed {:#?}", d); - d - }, - }; - - println!("Ratchet Debug: Deciding on decoded user packet"); - match decoded_user { - RTDecodedPacket::RTAuthenPacket(rtauthen_user_packet) => { - println!("Ratchet Debug: Was authen packet, checking for Continue"); - match rtauthen_user_packet { - RTAuthenPacket::RTAuthenContinuePacket(rtauthen_continue_packet) => { - obtained_username = rtauthen_continue_packet.user_msg; - }, - _ => { - println!("Ratchet Error: Unexpected packet type in ASCII Authentication sequence"); - authen_sess.send_error_packet( &mut stream); - continue; - }, - } - }, - _ => { - println!("Ratchet Error: Non authen packet in Authen sequence"); - println!("Ratchet Error: Unexpected packet type in ASCII Authentication sequence"); - authen_sess.send_error_packet( &mut stream); - continue; - }, } } else { - obtained_username = asp.user; - } + String::from_utf8_lossy(&asp.user).to_string() + }; // Stage 2: Fetch the Password // TODO: Everybody gets one - - let get_password_packet = RTAuthenReplyPacket::get_getpass_packet(); - - // TODO: Refactor this mantra into a neatly architected thingamajig - // ... maybe the 'outermost' detail needed is the session info (i.e., expected pack number, expected sesid), so - // ... it should be a part of a session implementation for the full transaction. - println!("Ratchet Debug: {:#?}", get_password_packet); - let getpass_resp_hdr = RTHeader::get_v0_header(hdr.tacp_hdr_sesid, &get_password_packet, cur_seq); - println!("Ratchet Debug: {:#?}", getpass_resp_hdr); - let pad = getpass_resp_hdr.compute_md5_pad( SECRET_KEY ); - let mut payload = md5_xor(&get_password_packet.serialize(), &pad); - let mut msg = getpass_resp_hdr.serialize(); - msg.append(&mut payload); - - println!("{:?}", msg); - // TODO: This blocks - match stream.write(&msg) { - Ok(v) => { - cur_seq += 1; - println!("Ratchet Debug: Sent {} bytes", v) - }, - Err(e) => - println!("Ratchet Error: TCP Error, {}", e), - //}, - } - - // TODO: Ok... session loop is starting over...? Not really it's a sequence .... hmmmmmmmmm... - let pass_hdr: RTHeader = match RTHeader::parse_init_header(&mut stream, cur_seq) { - Ok(h) => { - //println!("Ratchet Debug: Processed {:#?}", h); - cur_seq += 1; - h - }, - Err(e) => { - println!("Ratchet Error: {}", e); - authen_sess.send_error_packet( &mut stream); - continue; - }, - }; - - let pass_contents = match pass_hdr.tacp_hdr_type { - RTTACType::TAC_PLUS_AUTHEN => pass_hdr.parse_authen_packet(&mut stream, SECRET_KEY), - RTTACType::TAC_PLUS_AUTHOR => { - println!("Ratchet Debug: Not Implemented"); - authen_sess.send_error_packet( &mut stream); - continue; - }, - RTTACType::TAC_PLUS_ACCT => { - println!("Ratchet Debug: Not Implemented"); - authen_sess.send_error_packet( &mut stream); - continue; - }, - }; - - let decoded_pass: RTDecodedPacket = match pass_contents { - Err(e) => { - println!("Ratchet Error: {}", e); - authen_sess.send_error_packet( &mut stream); - continue; + let obtained_password= if asp.user.len() == 0 { // have to fetch username + match authen_sess.do_get(&mut stream, RTAuthenReplyPacket::get_getpass_packet()) { + Ok(u) => u, + Err(_) => { + authen_sess.send_error_packet(&mut stream); + continue; + }, } - Ok(d) => { - //println!("Ratchet Debug: Processed {:#?}", d); - d - }, + } else { + String::from_utf8_lossy(&asp.user).to_string() }; - - let obtained_password; - match decoded_pass { - RTDecodedPacket::RTAuthenPacket(rtauthen_pass_packet) => { - match rtauthen_pass_packet { - RTAuthenPacket::RTAuthenContinuePacket(rtauthen_continue_packet) => { - obtained_password = rtauthen_continue_packet.user_msg; - }, - _ => { - println!("Ratchet Error: Unexpected packet type in ASCII Authentication sequence"); - authen_sess.send_error_packet( &mut stream); - continue; - }, - } - }, - _ => { - println!("Ratchet Error: Unexpected packet type in ASCII Authentication sequence"); - authen_sess.send_error_packet( &mut stream); - continue; - }, - } + if obtained_password.len() == 0 || obtained_username.len() == 0 { + // buzz off + match authen_sess.send_final_packet(&mut stream, RTAuthenReplyPacket::get_fail_packet()) { + Ok(_) => println!("Ratchet Debug: Sent failure packet"), + Err(e) => println!("Ratchet Error: TCP Error, {}", e), + } + continue; + } - // TODO: BIG CODE DUPLICATION - // TODO: BIG CODE DUPLICATION - // TODO: BIG CODE DUPLICATION - // TODO: BIG CODE DUPLICATION - // TODO: BIG CODE DUPLICATION - // TODO: BIG CODE DUPLICATION - let raw_username = String::from_utf8_lossy(&obtained_username); - let auth_request_password = String::from_utf8_lossy(&obtained_password); + let raw_username = obtained_username; + let auth_request_password = obtained_password; let mut user_authenticated = false; println!("Ratchet Debug: Looking up {}", raw_username); @@ -455,7 +298,7 @@ pub fn main() { }, } } else { - raw_username + raw_username.try_into().unwrap() }; if let Some(p) = credentials.get(&username.to_string()) { @@ -469,42 +312,15 @@ pub fn main() { } if user_authenticated { - let r = RTAuthenReplyPacket::get_success_packet(); - println!("Ratchet Debug: {username} Authenticated successfully, signalling client."); - println!("Ratchet Debug: {:#?}", r); - let resp_hdr = RTHeader::get_v0_header(hdr.tacp_hdr_sesid, &r, cur_seq); - println!("Ratchet Debug: {:#?}", resp_hdr); - let pad = resp_hdr.compute_md5_pad( SECRET_KEY ); - let mut payload = md5_xor(&r.serialize(), &pad); - let mut msg = resp_hdr.serialize(); - msg.append(&mut payload); - - println!("{:?}", msg); - // TODO: This blocks - match stream.write(&msg) { - Ok(v) => println!("Ratchet Debug: Sent {} bytes", v), - Err(e) => { - println!("Ratchet Error: TCP Error, {}", e); - }, + match authen_sess.send_final_packet(&mut stream, RTAuthenReplyPacket::get_success_packet()) { + Ok(_) => println!("Ratchet Debug: Sent success packet"), + Err(e) => println!("Ratchet Error: TCP Error, {}", e), } + } else { - let r = RTAuthenReplyPacket::get_fail_packet(); - println!("Ratchet Debug: {username} Authentication failed, signalling client."); - println!("Ratchet Debug: {:#?}", r); - let resp_hdr = RTHeader::get_v0_header(hdr.tacp_hdr_sesid, &r, cur_seq); - println!("Ratchet Debug: {:#?}", resp_hdr); - let pad = resp_hdr.compute_md5_pad( SECRET_KEY ); - let mut payload = md5_xor(&r.serialize(), &pad); - let mut msg = resp_hdr.serialize(); - msg.append(&mut payload); - - println!("{:?}", msg); - // TODO: This blocks - match stream.write(&msg) { - Ok(v) => println!("Ratchet Debug: Sent {} bytes", v), - Err(e) => - println!("Ratchet Error: TCP Error, {}", e), - //}, + match authen_sess.send_final_packet(&mut stream, RTAuthenReplyPacket::get_fail_packet()) { + Ok(_) => println!("Ratchet Debug: Sent failure packet"), + Err(e) => println!("Ratchet Error: TCP Error, {}", e), } } }, @@ -543,42 +359,15 @@ pub fn main() { } if user_authenticated { - let r = RTAuthenReplyPacket::get_success_packet(); - println!("Ratchet Debug: {username} Authenticated successfully, signalling client."); - println!("Ratchet Debug: {:#?}", r); - let resp_hdr = RTHeader::get_resp_header(hdr.tacp_hdr_sesid, &r, 1); - println!("Ratchet Debug: {:#?}", resp_hdr); - let pad = resp_hdr.compute_md5_pad( SECRET_KEY ); - let mut payload = md5_xor(&r.serialize(), &pad); - let mut msg = resp_hdr.serialize(); - msg.append(&mut payload); - - println!("{:?}", msg); - // TODO: This blocks - match stream.write(&msg) { - Ok(v) => println!("Ratchet Debug: Sent {} bytes", v), - Err(e) => { - println!("Ratchet Error: TCP Error, {}", e); - }, + match authen_sess.send_final_packet(&mut stream, RTAuthenReplyPacket::get_success_packet()) { + Ok(_) => println!("Ratchet Debug: Sent success packet"), + Err(e) => println!("Ratchet Error: TCP Error, {}", e), } + } else { - let r = RTAuthenReplyPacket::get_fail_packet(); - println!("Ratchet Debug: {username} Authentication failed, signalling client."); - println!("Ratchet Debug: {:#?}", r); - let resp_hdr = RTHeader::get_resp_header(hdr.tacp_hdr_sesid, &r, 1); - println!("Ratchet Debug: {:#?}", resp_hdr); - let pad = resp_hdr.compute_md5_pad( SECRET_KEY ); - let mut payload = md5_xor(&r.serialize(), &pad); - let mut msg = resp_hdr.serialize(); - msg.append(&mut payload); - - println!("{:?}", msg); - // TODO: This blocks - match stream.write(&msg) { - Ok(v) => println!("Ratchet Debug: Sent {} bytes", v), - Err(e) => - println!("Ratchet Error: TCP Error, {}", e), - //}, + match authen_sess.send_final_packet(&mut stream, RTAuthenReplyPacket::get_fail_packet()) { + Ok(_) => println!("Ratchet Debug: Sent failure packet"), + Err(e) => println!("Ratchet Error: TCP Error, {}", e), } } }, From 802ff315421ea5232d95eb4c1bbbf34760b482da Mon Sep 17 00:00:00 2001 From: meltyness <86126050+meltyness@users.noreply.github.com> Date: Mon, 21 Oct 2024 16:05:07 -0500 Subject: [PATCH 3/7] password uses different logic --- src/main.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index bd2e979..1769173 100644 --- a/src/main.rs +++ b/src/main.rs @@ -258,17 +258,14 @@ pub fn main() { // Stage 2: Fetch the Password // TODO: Everybody gets one - let obtained_password= if asp.user.len() == 0 { // have to fetch username + let obtained_password= match authen_sess.do_get(&mut stream, RTAuthenReplyPacket::get_getpass_packet()) { Ok(u) => u, Err(_) => { authen_sess.send_error_packet(&mut stream); continue; }, - } - } else { - String::from_utf8_lossy(&asp.user).to_string() - }; + }; if obtained_password.len() == 0 || obtained_username.len() == 0 { // buzz off From 0a032b7bf6ebb06bd65a19f81141006e46043e9f Mon Sep 17 00:00:00 2001 From: meltyness <86126050+meltyness@users.noreply.github.com> Date: Mon, 21 Oct 2024 16:16:56 -0500 Subject: [PATCH 4/7] One retry --- src/main.rs | 66 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1769173..e4ece11 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,16 +47,6 @@ struct RTKnownClient { } -fn prefetch_memory_region(start_addr: *const u8, length: usize) { - let result = unsafe { madvise(start_addr as *mut _, length, MADV_WILLNEED) }; - - if result != 0 { - eprintln!("madvise failed"); - } else { - println!("Memory region prefetched successfully"); - } -} - static mut RUNS: f64 = 0.0; static mut RUNNING_AVG: f64 = 0.0; static mut FIRST_RUN: Option = None; @@ -125,10 +115,8 @@ pub fn main() { } } - println!("Ratchet Info: NOWLISTENING bound to some port 49"); - unsafe { ctrlc::set_handler(move || { println!("Ratchet Debug: Average processing time over {} RUNS: {:#?}", rt_get_runs(), Duration::from_secs_f64(rt_get_avg() / rt_get_runs())); @@ -240,21 +228,51 @@ pub fn main() { // ... the server must be multithreaded or implement read/write timeout. // ... better to go multithreaded. println!("Ratchet Info: Decoded: {}", asp); + // (sort of) Authenticate the server before putting a cred on the line - let mut retries = 0; + //let mut retries = 0; // Stage 1: Fetch the Username - let obtained_username= if asp.user.len() == 0 { // have to fetch username - match authen_sess.do_get(&mut stream, RTAuthenReplyPacket::get_getuser_packet()) { - Ok(u) => u, - Err(_) => { - authen_sess.send_error_packet(&mut stream); - continue; - }, - } - } else { - String::from_utf8_lossy(&asp.user).to_string() - }; + let mut obtained_username= if asp.user.len() == 0 { // have to fetch username + match authen_sess.do_get(&mut stream, RTAuthenReplyPacket::get_getuser_packet()) { + Ok(u) => u, + Err(_) => { + authen_sess.send_error_packet(&mut stream); + continue; + }, + } + } else { + String::from_utf8_lossy(&asp.user).to_string() + }; + + if obtained_username.len() == 0 { + obtained_username= if asp.user.len() == 0 { // have to fetch username + match authen_sess.do_get(&mut stream, RTAuthenReplyPacket::get_getuser_packet()) { + Ok(u) => u, + Err(_) => { + authen_sess.send_error_packet(&mut stream); + continue; + }, + } + } else { + String::from_utf8_lossy(&asp.user).to_string() + }; + } + + // just one do-over. + if obtained_username.len() == 0 { + obtained_username= if asp.user.len() == 0 { // have to fetch username + match authen_sess.do_get(&mut stream, RTAuthenReplyPacket::get_getuser_packet()) { + Ok(u) => u, + Err(_) => { + authen_sess.send_error_packet(&mut stream); + continue; + }, + } + } else { + String::from_utf8_lossy(&asp.user).to_string() + }; + } // Stage 2: Fetch the Password // TODO: Everybody gets one From 2280ee1ce7bb52444640c60b5baffd2c313c62ff Mon Sep 17 00:00:00 2001 From: meltyness <86126050+meltyness@users.noreply.github.com> Date: Mon, 21 Oct 2024 16:19:06 -0500 Subject: [PATCH 5/7] Tweak imports --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index e4ece11..866a36b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,7 @@ // (C) 2024 - T.J. Hampton // -use libc::{mlockall, madvise, MCL_CURRENT, MCL_FUTURE, MCL_ONFAULT, MADV_WILLNEED}; +use libc::{mlockall, MCL_CURRENT, MCL_FUTURE, MCL_ONFAULT}; use std::env; From baf3d82400a906a7fda5fb183822be9807bb6e67 Mon Sep 17 00:00:00 2001 From: meltyness <86126050+meltyness@users.noreply.github.com> Date: Mon, 21 Oct 2024 16:20:26 -0500 Subject: [PATCH 6/7] README edited --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 513ad4f..f41908b 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,8 @@ Later - [ ] fail2ban-like mechanism to protect server from misbehaving clients - [ ] Constructively walk through LLVM opt flag configurations 'rustc passes' - [ ] CRUD config changes (currently will necessitate brief server relaunch) +- [ ] Something to meaningfully improve using GNS3 to run tests over this + - [ ] ... or maybe setup like a dynaMIPS thing some way how ## Kernel Hacking / Optimization I discovered that when using `perf` to profile `ratchet` that the pipeline was 30% faster, which was,... odd. From 5d29fcbb355409deedea60870dbec14c23182ff4 Mon Sep 17 00:00:00 2001 From: meltyness <86126050+meltyness@users.noreply.github.com> Date: Mon, 21 Oct 2024 16:30:08 -0500 Subject: [PATCH 7/7] Avoid todo! since that creates a panic --- src/main.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 866a36b..554bf57 100644 --- a/src/main.rs +++ b/src/main.rs @@ -386,9 +386,21 @@ pub fn main() { } } }, - ratchet::RTAuthenPacketType::TAC_PLUS_AUTHEN_TYPE_CHAP => todo!(), - ratchet::RTAuthenPacketType::TAC_PLUS_AUTHEN_TYPE_MSCHAP => todo!(), - ratchet::RTAuthenPacketType::TAC_PLUS_AUTHEN_TYPE_MSCHAPV2 => todo!(), + ratchet::RTAuthenPacketType::TAC_PLUS_AUTHEN_TYPE_CHAP => { + println!("Unknown Packet Format"); + authen_sess.send_error_packet( &mut stream); + continue; + }, + ratchet::RTAuthenPacketType::TAC_PLUS_AUTHEN_TYPE_MSCHAP => { + println!("Unknown Packet Format"); + authen_sess.send_error_packet( &mut stream); + continue; + }, + ratchet::RTAuthenPacketType::TAC_PLUS_AUTHEN_TYPE_MSCHAPV2 => { + println!("Unknown Packet Format"); + authen_sess.send_error_packet( &mut stream); + continue; + }, } }, RTAuthenPacket::RTAuthenReplyPacket(rtauthen_reply_packet) => {