diff --git a/src/main.rs b/src/main.rs index f9190a6..8f49e9b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,33 +7,37 @@ //! also the first and only current usage of rnex, expect this and rnex to be split into seperate //! repos soon. -use crate::rmc::protocols::auth::RemoteAuth; -use crate::rmc::protocols::auth::RawAuthInfo; -use crate::rmc::protocols::auth::RawAuth; use crate::nex::account::Account; +use crate::nex::auth_handler::{AuthHandler, RemoteAuthClientProtocol}; use crate::prudp::packet::VirtualPort; use crate::prudp::router::Router; +use crate::prudp::secure::Secure; use crate::prudp::sockaddr::PRUDPSockAddr; -use crate::prudp::socket::Unsecure; -use chrono::{Local, SecondsFormat}; -use log::{error, info}; -use once_cell::sync::Lazy; -use simplelog::{ - ColorChoice, CombinedLogger, Config, LevelFilter, TermLogger, TerminalMode, WriteLogger, -}; -use std::fs::File; -use std::net::{Ipv4Addr, SocketAddrV4}; -use std::{env, fs}; -use std::marker::PhantomData; -use std::ops::{BitAnd, BitOr}; -use std::str::FromStr; -use macros::rmc_struct; +use crate::prudp::unsecure::Unsecure; use crate::rmc::protocols::auth::Auth; +use crate::rmc::protocols::auth::RawAuth; +use crate::rmc::protocols::auth::RawAuthInfo; +use crate::rmc::protocols::auth::RemoteAuth; use crate::rmc::protocols::{new_rmc_gateway_connection, OnlyRemote}; use crate::rmc::response::ErrorCode; use crate::rmc::structures::any::Any; use crate::rmc::structures::connection_data::ConnectionData; use crate::rmc::structures::qresult::QResult; +use chrono::{Local, SecondsFormat}; +use log::{error, info}; +use macros::rmc_struct; +use once_cell::sync::Lazy; +use simplelog::{ + ColorChoice, CombinedLogger, Config, LevelFilter, TermLogger, TerminalMode, WriteLogger, +}; +use std::fs::File; +use std::marker::PhantomData; +use std::net::{Ipv4Addr, SocketAddrV4}; +use std::ops::{BitAnd, BitOr}; +use std::str::FromStr; +use std::time::Duration; +use std::{env, fs}; +use tokio::task::JoinHandle; mod endianness; mod prudp; @@ -43,9 +47,9 @@ pub mod rmc; mod grpc; mod kerberos; mod nex; -mod web; -mod versions; mod result; +mod versions; +mod web; static KERBEROS_SERVER_PASSWORD: Lazy = Lazy::new(|| { env::var("AUTH_SERVER_PASSWORD") @@ -258,86 +262,112 @@ async fn start_secure_server() -> SecureServer{ } }*/ +async fn start_auth() -> JoinHandle<()> { + tokio::spawn(async { + let (router_secure, _) = Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *AUTH_SERVER_PORT)) + .await + .expect("unable to start router"); -impl Auth for AuthClient{ - async fn login(&self, name: String) -> Result<(), ErrorCode> { - todo!() - } + let mut socket_secure = router_secure + .add_socket(VirtualPort::new(1, 10), Unsecure("6f599f81")) + .await + .expect("unable to add socket"); - async fn login_ex(&self, name: String, extra_data: Any) -> Result<(QResult, u32, Vec, ConnectionData, String), ErrorCode> { - todo!() - } + // let conn = socket_secure.connect(auth_sockaddr).await.unwrap(); - async fn request_ticket(&self, source_pid: u32, destination_pid: u32) -> Result<(QResult, Vec), ErrorCode> { - todo!() - } + loop { + let Some(conn) = socket_secure.accept().await else { + error!("server crashed"); + return; + }; - async fn get_pid(&self, username: String) -> Result { - todo!() - } + info!("new connected user!"); - async fn get_name(&self, pid: u32) -> Result { - todo!() - } + let _ = new_rmc_gateway_connection(conn, |_| AuthHandler { + destination_server_acct: &SECURE_SERVER_ACCOUNT, + build_name: "branch:origin/project/wup-agmj build:3_8_15_2004_0", + station_url: &SECURE_STATION_URL, + }); + } + }) } -#[rmc_struct(AuthClientProtocol)] -struct AuthClient { +async fn start_secure() -> JoinHandle<()> { + tokio::spawn(async { + let (router_secure, _) = + Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *SECURE_SERVER_PORT)) + .await + .expect("unable to start router"); + let mut socket_secure = router_secure + .add_socket( + VirtualPort::new(1, 10), + Secure("6f599f81", &SECURE_SERVER_ACCOUNT), + ) + .await + .expect("unable to add socket"); + + // let conn = socket_secure.connect(auth_sockaddr).await.unwrap(); + + loop { + let Some(conn) = socket_secure.accept().await else { + error!("server crashed"); + return; + }; + + info!("new connected user on secure :D!"); + + let _ = new_rmc_gateway_connection(conn, |_| AuthHandler { + destination_server_acct: &SECURE_SERVER_ACCOUNT, + build_name: "branch:origin/project/wup-agmj build:3_8_15_2004_0", + station_url: &SECURE_STATION_URL, + }); + } + }) } -define_rmc_proto!( - proto AuthClientProtocol{ - Auth - } -); +async fn start_test() { + let addr = SocketAddrV4::new(*OWN_IP_PRIVATE, *AUTH_SERVER_PORT); + let virt_addr = VirtualPort::new(1, 10); + let prudp_addr = PRUDPSockAddr::new(addr, virt_addr); -async fn start_servers() { - - - //let auth_ip = SocketAddrV4::from_str("157.90.13.221:30039").unwrap(); - let auth_ip = SocketAddrV4::from_str("31.220.75.208:10000").unwrap(); - let auth_port = VirtualPort::new(1, 10); - - let auth_sockaddr = PRUDPSockAddr::new(auth_ip, auth_port); - - let (router_secure, _) = Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *AUTH_SERVER_PORT)) + let (router_test, _) = Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, 26969)) .await .expect("unable to start router"); - let mut socket_secure = router_secure + let mut socket_secure = router_test .add_socket(VirtualPort::new(1, 10), Unsecure("6f599f81")) .await .expect("unable to add socket"); - // let conn = socket_secure.connect(auth_sockaddr).await.unwrap(); + let conn = socket_secure.connect(prudp_addr).await.unwrap(); - - loop { - let Some(conn) = socket_secure.accept().await else { - error!("server crashed"); - return; - }; + let remote = + new_rmc_gateway_connection(conn, |r| OnlyRemote::::new(r)); - info!("new connected user!"); + let v = remote + .login_ex("1469690705".to_string(), Any::default()) + .await + .unwrap(); - let _ = new_rmc_gateway_connection(conn, |_| AuthClient {}); //OnlyRemote::::new + println!("got it"); +} - } - - - - /* +async fn start_servers() { #[cfg(feature = "auth")] - let auth_server = start_auth_server().await; + let auth_server = start_auth().await; #[cfg(feature = "secure")] - let secure_server = start_secure_server().await; - let web_server = web::start_web().await; + let secure_server = start_secure().await; + //let web_server = web::start_web().await; + + //tokio::time::sleep(Duration::from_secs(1)).await; + + //start_test().await; #[cfg(feature = "auth")] - auth_server.join_handle.await.expect("auth server crashed"); + auth_server.await.expect("auth server crashed"); #[cfg(feature = "secure")] - secure_server.join_handle.await.expect("auth server crashed"); - web_server.await.expect("webserver crashed");*/ -} \ No newline at end of file + secure_server.await.expect("auth server crashed"); + //web_server.await.expect("webserver crashed"); +} diff --git a/src/nex/auth_handler.rs b/src/nex/auth_handler.rs new file mode 100644 index 0000000..d0b5e2e --- /dev/null +++ b/src/nex/auth_handler.rs @@ -0,0 +1,167 @@ +use crate::grpc::account; +use crate::kerberos::{derive_key, KerberosDateTime, Ticket}; +use crate::nex::account::Account; +use crate::rmc::protocols::auth::{Auth, RawAuth, RawAuthInfo, RemoteAuth}; +use crate::rmc::response::ErrorCode; +use crate::rmc::response::ErrorCode::Core_Unknown; +use crate::rmc::structures::any::Any; +use crate::rmc::structures::connection_data::ConnectionData; +use crate::rmc::structures::qresult::QResult; +use crate::rmc::structures::RmcSerialize; +use crate::{define_rmc_proto, kerberos, rmc}; +use macros::rmc_struct; + +define_rmc_proto!( + proto AuthClientProtocol{ + Auth + } +); + +#[rmc_struct(AuthClientProtocol)] +pub struct AuthHandler { + pub destination_server_acct: &'static Account, + pub build_name: &'static str, + pub station_url: &'static str, +} + +pub fn generate_ticket( + source_act_login_data: (u32, [u8; 16]), + dest_act_login_data: (u32, [u8; 16]), +) -> Box<[u8]> { + let source_key = derive_key(source_act_login_data.0, source_act_login_data.1); + let dest_key = derive_key(dest_act_login_data.0, dest_act_login_data.1); + + let internal_data = kerberos::TicketInternalData::new(source_act_login_data.0); + + let encrypted_inner = internal_data.encrypt(dest_key); + let encrypted_session_ticket = Ticket { + pid: dest_act_login_data.0, + session_key: internal_data.session_key, + } + .encrypt(source_key, &encrypted_inner); + + encrypted_session_ticket +} + +async fn get_login_data_by_pid(pid: u32) -> Option<(u32, [u8; 16])> { + let Ok(mut client) = account::Client::new().await else { + return None; + }; + + let Ok(passwd) = client.get_nex_password(pid).await else { + return None; + }; + + Some((pid, passwd)) +} + +impl Auth for AuthHandler { + async fn login(&self, name: String) -> Result<(), ErrorCode> { + todo!() + } + + async fn login_ex( + &self, + name: String, + extra_data: Any, + ) -> Result<(QResult, u32, Vec, ConnectionData, String), ErrorCode> { + let Ok(pid) = name.parse() else { + return Err(ErrorCode::Core_InvalidArgument); + }; + + let Ok(mut client) = account::Client::new().await else { + return Err(ErrorCode::Core_Exception); + }; + + let Ok(passwd) = client.get_nex_password(pid).await else { + return Err(ErrorCode::Core_Exception); + }; + + let source_login_data = (pid, passwd); + let destination_login_data = self.destination_server_acct.get_login_data(); + + let ticket = generate_ticket(source_login_data, destination_login_data); + + let result = QResult::success(Core_Unknown); + + let connection_data = ConnectionData { + station_url: self.station_url.to_string(), + special_station_url: "".to_string(), + //date_time: KerberosDateTime::new(1,1,1,1,1,1), + date_time: KerberosDateTime::now(), + special_protocols: Vec::new(), + }; + + Ok(( + result, + source_login_data.0, + ticket.into(), + connection_data, + self.build_name.to_owned(), + )) + } + + async fn request_ticket( + &self, + source_pid: u32, + destination_pid: u32, + ) -> Result<(QResult, Vec), ErrorCode> { + let Some(source_login_data) = get_login_data_by_pid(source_pid).await else { + return Err(ErrorCode::Core_Exception); + }; + + let desgination_login_data = if destination_pid == self.destination_server_acct.pid { + self.destination_server_acct.get_login_data() + } else { + let Some(login) = get_login_data_by_pid(destination_pid).await else { + return Err(ErrorCode::Core_Exception); + }; + login + }; + + let result = QResult::success(Core_Unknown); + + let ticket = generate_ticket(source_login_data, desgination_login_data); + + Ok((result, ticket.into())) + } + + async fn get_pid(&self, username: String) -> Result { + Err(ErrorCode::Core_Exception) + } + + async fn get_name(&self, pid: u32) -> Result { + Err(ErrorCode::Core_Exception) + } +} + +#[cfg(test)] +mod test { + use crate::rmc::structures::connection_data::ConnectionData; + use crate::rmc::structures::qresult::QResult; + use crate::rmc::structures::RmcSerialize; + use crate::rmc::response::RMCResponse; + use std::io::Cursor; + + #[test] + fn test() { + + let stuff = hex::decode("200100000a0106000000028000000100010051b3995774000000a6321c7f78847c1c5e9fb825eb26bd91841f1a40d92fc694159666119cb13527f1463ac48ad42a63e6613ede67041554b1770978112e6f1f3e177a2bfc75933216dbe38f70133a1eb28e2ae32a4b5c4b0c3e3efd4c02907992e259b257270b57a9dbe7792f4721b07f8fafb9e32d50f2555c616a015c0000004b007072756470733a2f5049443d323b7369643d313b73747265616d3d31303b747970653d323b616464726573733d322e3234332e39352e3131333b706f72743d31303030313b4349443d3100000000000100002c153ba51f00000033006272616e63683a6f726967696e2f70726f6a6563742f7775702d61676d6a206275696c643a335f385f31355f323030345f3000").unwrap(); + let stuff = RMCResponse::new(&mut Cursor::new(stuff)).unwrap(); + + let crate::rmc::response::RMCResponseResult::Success { call_id, method_id, data: stuff} = stuff.response_result else { + panic!() + }; + + + + // let stuff = hex::decode("0100010051B399577400000085F1736FCFBE93660275A3FE36FED6C2EFC57222AC99A9219CF54170A415B02DF1463AC48AD42A6307813FDE67041554B177097832ED000F892D9551A09F88E9CB0388DC1BC9527CC7384556A3287B2A349ABBF7E34A5A3EC14C2287CC7F78DA616BC3B03A035347FBD2E9A505C8EF42447CD809015F0000004E007072756470733A2F73747265616D3D31303B747970653D323B616464726573733D3139322E3136382E3137382E3132303B706F72743D31303030313B4349443D313B5049443D323B7369643D310000000000010000CDF53AA51F00000033006272616E63683A6F726967696E2F70726F6A6563742F7775702D61676D6A206275696C643A335F385F31355F323030345F3000").unwrap(); + // let stuff = hex::decode("0100010051b399577400000037d3d4814d2b16dd546c94a75d32637b45f856b5abe73cf26cfaa235c5f2c1cef1463ac48ad42a637d873fde67041554b177097880cfa7e10bb810eaf686bfb0a0cf3d65b1f476ebc046d0855327986f557dca14fbb8594883c186b863f2206f22baa0309dbcc81da2f883cb2cdc12628ec7fced015c0000004b007072756470733a2f5049443d323b7369643d313b73747265616d3d31303b747970653d323b616464726573733d322e3234332e39352e3131333b706f72743d31303030313b4349443d310000000000010000b7f33aa51f00000033006272616e63683a6f726967696e2f70726f6a6563742f7775702d61676d6a206275696c643a335f385f31355f323030345f3000").unwrap(); + + let data = <(QResult, u32, Vec, ConnectionData, String) as RmcSerialize>::deserialize( + &mut Cursor::new(stuff), + ).unwrap(); + + println!("data: {:?}", data); + } +} diff --git a/src/nex/mod.rs b/src/nex/mod.rs index 3ce1632..20e508c 100644 --- a/src/nex/mod.rs +++ b/src/nex/mod.rs @@ -1 +1,2 @@ -pub mod account; \ No newline at end of file +pub mod account; +pub mod auth_handler; \ No newline at end of file diff --git a/src/prudp/mod.rs b/src/prudp/mod.rs index 41f721c..966523e 100644 --- a/src/prudp/mod.rs +++ b/src/prudp/mod.rs @@ -3,5 +3,6 @@ pub mod router; pub mod socket; mod auth_module; pub mod sockaddr; -//pub mod secure; -pub mod station_url; \ No newline at end of file +pub mod station_url; +pub mod secure; +pub mod unsecure; \ No newline at end of file diff --git a/src/prudp/router.rs b/src/prudp/router.rs index 16424c6..8621236 100644 --- a/src/prudp/router.rs +++ b/src/prudp/router.rs @@ -50,8 +50,7 @@ impl Router { trace!("got valid prudp packet from someone({}): \n{:?}", addr, packet); let connection = packet.source_sockaddr(addr); - - println!("data from {:?}", connection); + let endpoints = self.endpoints.read().await; diff --git a/src/prudp/secure.rs b/src/prudp/secure.rs index 2689963..486500f 100644 --- a/src/prudp/secure.rs +++ b/src/prudp/secure.rs @@ -4,10 +4,13 @@ use log::error; use rc4::cipher::StreamCipherCoreWrapper; use rc4::{KeyInit, Rc4, Rc4Core, StreamCipher}; use rc4::consts::U16; +use typenum::U5; use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions}; use crate::kerberos::{derive_key, TicketInternalData}; use crate::nex::account::Account; -use crate::prudp::socket::EncryptionPair; +use crate::prudp::packet::PRUDPPacket; +use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance, EncryptionPair}; +use crate::prudp::unsecure::UnsecureInstance; use crate::rmc::structures::RmcSerialize; pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 32], u32, u32)>{ @@ -97,4 +100,93 @@ pub fn generate_secure_encryption_pairs(mut session_key: [u8; 32], count: u8) -> } vec +} + + +pub struct Secure(pub &'static str, pub &'static Account); + + +pub struct SecureInstance { + access_key: &'static str, + session_key: [u8; 32], + streams: Vec>>, + self_signature: [u8; 16], + remote_signature: [u8; 16], + pid: u32, +} + +impl CryptoHandler for Secure { + type CryptoConnectionInstance = SecureInstance; + + fn instantiate( + &self, + remote_signature: [u8; 16], + self_signature: [u8; 16], + payload: &[u8], + substream_count: u8, + ) -> Option<(Vec, Self::CryptoConnectionInstance)> { + let (session_key, pid, check_value) = read_secure_connection_data(payload, &self.1)?; + + let check_value_response = check_value + 1; + + let data = bytemuck::bytes_of(&check_value_response); + + let mut response = Vec::new(); + + data.serialize(&mut response).ok()?; + + let encryption_pairs = generate_secure_encryption_pairs(session_key, substream_count); + + Some(( + response, + SecureInstance { + pid, + streams: encryption_pairs, + session_key, + access_key: self.0, + remote_signature, + self_signature, + }, + )) + } + + fn sign_pre_handshake(&self, packet: &mut PRUDPPacket) { + packet.set_sizes(); + packet.calculate_and_assign_signature(self.0, None, None); + } +} + + +impl CryptoHandlerConnectionInstance for SecureInstance { + type Encryption = Rc4; + + fn decrypt_incoming(&mut self, substream: u8, data: &mut [u8]) { + if let Some(crypt_pair) = self.streams.get_mut(substream as usize){ + crypt_pair.recv.apply_keystream(data); + } + } + + fn encrypt_outgoing(&mut self, substream: u8, data: &mut [u8]) { + if let Some(crypt_pair) = self.streams.get_mut(substream as usize){ + crypt_pair.send.apply_keystream(data); + } + } + + fn get_user_id(&self) -> u32 { + self.pid + } + + fn sign_connect(&self, packet: &mut PRUDPPacket) { + packet.set_sizes(); + packet.calculate_and_assign_signature(self.access_key, None, Some(self.self_signature)); + } + + fn sign_packet(&self, packet: &mut PRUDPPacket) { + packet.set_sizes(); + packet.calculate_and_assign_signature(self.access_key, Some(self.session_key), Some(self.self_signature)); + } + + fn verify_packet(&self, packet: &PRUDPPacket) -> bool { + true + } } \ No newline at end of file diff --git a/src/prudp/socket.rs b/src/prudp/socket.rs index 6b5c6a2..5702c51 100644 --- a/src/prudp/socket.rs +++ b/src/prudp/socket.rs @@ -27,6 +27,7 @@ use tokio::net::UdpSocket; use tokio::sync::mpsc::{channel, Receiver, Sender}; use tokio::sync::{Mutex, RwLock}; use tokio_stream::Stream; +use crate::nex::account::Account; // due to the way this is designed crashing the router thread causes deadlock, sorry ;-; // (maybe i will fix that some day) @@ -39,473 +40,13 @@ pub struct EncryptionPair { } impl EncryptionPair { - fn init_both T>(func: F) -> Self { + pub fn init_both T>(func: F) -> Self { Self { recv: func(), send: func(), } } } -/* - pub async fn process_packet( - self: &Arc, - client_address: PRUDPSockAddr, - packet: &PRUDPPacket, - ) { - let conn = self.connections.read().await; - - if !conn.contains_key(&client_address) { - drop(conn); - - let mut conn = self.connections.write().await; - //only insert if we STILL dont have the connection preventing double insertion - if !conn.contains_key(&client_address) { - conn.insert( - client_address, - ( - Arc::new(Mutex::new(ConnectionData { - sock_addr: client_address, - id: random(), - signature: [0; 16], - server_signature: [0; 16], - - active_connection_data: None, - })), - Arc::new(Mutex::new(())), - ), - ); - } - drop(conn); - } else { - drop(conn); - } - - let connections = self.connections.read().await; - - let Some(conn) = connections.get(&client_address) else { - error!("connection is still not present after making sure connection is present, giving up."); - return; - }; - - let conn = conn.clone(); - - // dont keep holding the connections list unnescesarily - drop(connections); - - let mutual_exclusion_packet_handeling_mtx = conn.1.lock().await; - let mut connection = conn.0.lock().await; - - if (packet.header.types_and_flags.get_flags() & ACK) != 0 { - //todo: handle acknowledgements and resending packets propperly - println!("got ack"); - return; - } - - if (packet.header.types_and_flags.get_flags() & MULTI_ACK) != 0 { - println!("got multi ack"); - return; - } - - match packet.header.types_and_flags.get_types() { - SYN => { - println!("got syn"); - // reset heartbeat? - let mut response_packet = packet.base_response_packet(); - - response_packet.header.types_and_flags.set_types(SYN); - response_packet.header.types_and_flags.set_flag(ACK); - response_packet.header.types_and_flags.set_flag(HAS_SIZE); - - connection.signature = client_address.calculate_connection_signature(); - - response_packet - .options - .push(ConnectionSignature(connection.signature)); - - for options in &packet.options { - match options { - SupportedFunctions(functions) => response_packet - .options - .push(SupportedFunctions(*functions & 0x04)), - MaximumSubstreamId(max_substream) => response_packet - .options - .push(MaximumSubstreamId(*max_substream)), - _ => { /* ??? */ } - } - } - - response_packet.set_sizes(); - - response_packet.calculate_and_assign_signature(self.access_key, None, None); - - let mut vec = Vec::new(); - - response_packet - .write_to(&mut vec) - .expect("somehow failed to convert backet to bytes"); - - self.socket - .send_to(&vec, client_address.regular_socket_addr) - .await - .expect("failed to send data back"); - } - CONNECT => { - println!("got connect"); - let Some(MaximumSubstreamId(max_substream)) = packet - .options - .iter() - .find(|v| matches!(v, MaximumSubstreamId(_))) - else { - return; - }; - - let Some((response_data, encryption_pairs, active_secure_connection_data)) = - (self.on_connect_handler)(packet.clone(), *max_substream).await - else { - error!("invalid connection request"); - return; - }; - - connection.active_connection_data = Some(ActiveConnectionData { - encryption_pairs, - reliable_client_queue: VecDeque::new(), - reliable_client_counter: 2, - reliable_server_counter: 1, - server_session_id: packet.header.session_id, - active_secure_connection_data, - connection_id: random(), - }); - - let mut response_packet = packet.base_response_packet(); - - response_packet.payload = response_data; - - response_packet.header.types_and_flags.set_types(CONNECT); - response_packet.header.types_and_flags.set_flag(ACK); - response_packet.header.types_and_flags.set_flag(HAS_SIZE); - - // todo: (or not) sliding windows and stuff - - response_packet.header.session_id = packet.header.session_id; - response_packet.header.sequence_id = 1; - - response_packet - .options - .push(ConnectionSignature(Default::default())); - - //let mut init_seq_id = 0; - - for option in &packet.options { - match option { - MaximumSubstreamId(max_substream) => response_packet - .options - .push(MaximumSubstreamId(*max_substream)), - SupportedFunctions(funcs) => { - response_packet.options.push(SupportedFunctions(*funcs)) - } - ConnectionSignature(sig) => connection.server_signature = *sig, - PacketOption::InitialSequenceId(_id) => { - //init_seq_id = *id; - } - _ => { /* ? */ } - } - } - - // Splatoon doesnt use compression so we arent gonna compress unless i at some point - // want to implement some server which requires it - // No encryption here for the same reason - - // todo: implement something to do secure servers - - if connection.server_signature == <[u8; 16] as Default>::default() { - error!("didn't get connection signature from client") - } - - response_packet.set_sizes(); - - response_packet.calculate_and_assign_signature( - self.access_key, - None, - Some(connection.server_signature), - ); - - let mut vec = Vec::new(); - response_packet - .write_to(&mut vec) - .expect("somehow failed to convert backet to bytes"); - - self.socket - .send_to(&vec, client_address.regular_socket_addr) - .await - .expect("failed to send data back"); - } - DATA => { - if (packet.header.types_and_flags.get_flags() & RELIABLE) != 0 { - let Some(active_connection) = connection.active_connection_data.as_mut() else { - error!("got data packet on non active connection!"); - return; - }; - - match active_connection - .reliable_client_queue - .binary_search_by_key(&packet.header.sequence_id, |p| p.header.sequence_id) - { - Ok(_) => warn!("recieved packet twice"), - Err(position) => active_connection - .reliable_client_queue - .insert(position, packet.clone()), - } - - if (packet.header.types_and_flags.get_flags() & NEED_ACK) != 0 { - let mut ack = packet.base_acknowledgement_packet(); - ack.header.session_id = active_connection.server_session_id; - - ack.set_sizes(); - let potential_session_key = connection - .active_connection_data - .as_ref() - .unwrap() - .active_secure_connection_data - .as_ref() - .map(|s| s.session_key); - - ack.calculate_and_assign_signature( - self.access_key, - potential_session_key, - Some(connection.server_signature), - ); - - let mut vec = Vec::new(); - ack.write_to(&mut vec) - .expect("somehow failed to convert backet to bytes"); - - self.socket - .send_to(&vec, client_address.regular_socket_addr) - .await - .expect("failed to send data back"); - } - drop(connection); - while let Some(mut packet) = { - let mut locked = conn.0.lock().await; - - let packet = locked - .active_connection_data - .as_mut() - .map(|a| { - a.reliable_client_queue - .front() - .is_some_and(|v| { - v.header.sequence_id == a.reliable_client_counter - }) - .then(|| a.reliable_client_queue.pop_front()) - }) - .flatten() - .flatten(); - - drop(locked); - packet - } { - if packet.options.iter().any(|v| match v { - PacketOption::FragmentId(f) => *f != 0, - _ => false, - }) { - error!("fragmented packets are unsupported right now") - } - - let mut locked = conn.0.lock().await; - - let active_connection = locked.active_connection_data.as_mut() - .expect("we litterally just recieved a packet which requires the connection to be active, failing this should be impossible"); - - active_connection.reliable_client_counter = active_connection - .reliable_client_counter - .overflowing_add(1) - .0; - - let Some(stream) = active_connection - .encryption_pairs - .get_mut(packet.header.substream_id as usize) - .map(|e| &mut e.recv) - else { - return; - }; - - stream.apply_keystream(&mut packet.payload); - - drop(locked); - // we cant divert this off to another thread we HAVE to process it now to keep order - - (self.on_data_handler)(packet, self.clone(), conn.0.clone()).await; - // ignored for now - } - } else { - error!("unreliable packets are unimplemented"); - unimplemented!() - } - //info!("{:?}", packet); - } - PING => { - let ConnectionData { - active_connection_data, - server_signature, - .. - } = &mut *connection; - - info!("got ping"); - - if (packet.header.types_and_flags.get_flags() & NEED_ACK) != 0 { - let Some(active_connection) = active_connection_data.as_mut() else { - error!("got data packet on non active connection!"); - return; - }; - - let mut ack = packet.base_acknowledgement_packet(); - ack.header.session_id = active_connection.server_session_id; - - ack.set_sizes(); - - let potential_session_key = active_connection - .active_secure_connection_data - .as_ref() - .map(|s| s.session_key); - - ack.calculate_and_assign_signature( - self.access_key, - potential_session_key, - Some(*server_signature), - ); - - let mut vec = Vec::new(); - ack.write_to(&mut vec) - .expect("somehow failed to convert backet to bytes"); - - self.socket - .send_to(&vec, client_address.regular_socket_addr) - .await - .expect("failed to send data back"); - } - } - DISCONNECT => { - println!("got disconnect"); - let Some(active_connection) = &connection.active_connection_data else { - return; - }; - - let mut ack = packet.base_acknowledgement_packet(); - - ack.header.session_id = active_connection.server_session_id; - - ack.set_sizes(); - - let potential_session_key = active_connection - .active_secure_connection_data - .as_ref() - .map(|s| s.session_key); - - ack.calculate_and_assign_signature( - self.access_key, - potential_session_key, - Some(connection.server_signature), - ); - - let mut vec = Vec::new(); - ack.write_to(&mut vec) - .expect("somehow failed to convert backet to bytes"); - - self.socket - .send_to(&vec, client_address.regular_socket_addr) - .await - .expect("failed to send data back"); - self.socket - .send_to(&vec, client_address.regular_socket_addr) - .await - .expect("failed to send data back"); - self.socket - .send_to(&vec, client_address.regular_socket_addr) - .await - .expect("failed to send data back"); - } - _ => error!( - "unimplemented packet type: {}", - packet.header.types_and_flags.get_types() - ), - } - - drop(mutual_exclusion_packet_handeling_mtx) - }*/ -/* -impl ConnectionData { - pub async fn finish_and_send_packet_to( - &mut self, - socket: &SocketData, - mut packet: PRUDPPacket, - ) { - let mut web = WEB_DATA.lock().await; - web.data.push(( - self.sock_addr.regular_socket_addr, - Outgoing(hex::encode(&packet.payload)), - )); - drop(web); - - if (packet.header.types_and_flags.get_flags() & RELIABLE) != 0 { - let Some(active_connection) = self.active_connection_data.as_mut() else { - error!("tried to send a secure packet to an inactive connection"); - return; - }; - - packet.header.sequence_id = active_connection.reliable_server_counter; - active_connection.reliable_server_counter += 1; - - let Some(encryption) = active_connection - .encryption_pairs - .get_mut(packet.header.substream_id as usize) - .map(|e| &mut e.send) - else { - return; - }; - - encryption.apply_keystream(&mut packet.payload); - } - - packet.header.session_id = self - .active_connection_data - .as_ref() - .map(|v| v.server_session_id) - .unwrap_or_default(); - - packet.header.source_port = socket.virtual_port; - packet.header.destination_port = self.sock_addr.virtual_port; - - packet.set_sizes(); - - let potential_session_key = self - .active_connection_data - .as_ref() - .unwrap() - .active_secure_connection_data - .as_ref() - .map(|s| s.session_key); - - packet.calculate_and_assign_signature( - socket.access_key, - potential_session_key, - Some(self.server_signature), - ); - let mut vec = Vec::new(); - - packet - .write_to(&mut vec) - .expect("somehow failed to convert backet to bytes"); - - if let Err(e) = socket - .socket - .send_to(&vec, self.sock_addr.regular_socket_addr) - .await - { - error!("unable to send packet to destination: {}", e); - } - } -}*/ pub struct NewEncryptionPair { pub send: E, @@ -538,9 +79,11 @@ impl Deref for InternalConnection{ impl InternalConnection{ fn next_server_count(&mut self) -> u16{ + let prev_val = self.reliable_server_counter; let (val, _) = self.reliable_server_counter.overflowing_add(1); self.reliable_server_counter = val; - val + println!("{}", prev_val); + prev_val } } @@ -645,14 +188,14 @@ impl AnyInternalConnection for InternalConne self.crypto_handler_instance.sign_packet(&mut packet); - packet.set_sizes(); - let mut vec = Vec::new(); packet .write_to(&mut vec) .expect("somehow failed to convert backet to bytes"); + println!("{}", hex::encode(&vec)); + self.socket .send_to(&vec, self.socket_addr.regular_socket_addr) .await @@ -670,8 +213,6 @@ impl InternalSocket { .write_to(&mut vec) .expect("somehow failed to convert backet to bytes"); - println!("sent out: {}", hex::encode(&vec)); - self.socket .send_to(&vec, dest.regular_socket_addr) .await @@ -824,12 +365,15 @@ impl InternalSocket { let session_id = packet.header.session_id; - let (return_data, crypto) = self.crypto_handler.instantiate( + let Some((return_data, crypto)) = self.crypto_handler.instantiate( remote_signature, *own_signature, &packet.payload, 1 + *max_substream, - ); + ) else { + error!("someone attempted to connect with invalid data"); + return; + }; let mut response = packet.base_response_packet(); response.header.types_and_flags.set_types(CONNECT); @@ -895,12 +439,6 @@ impl InternalSocket { mem::swap(&mut data, &mut packet.payload); - conn.data_sender.send(data).await.expect("socket died"); - - if packet.header.types_and_flags.get_flags() & NEED_ACK == 0{ - return; - } - let mut response = packet.base_acknowledgement_packet(); response.header.types_and_flags.set_flag(HAS_SIZE | ACK); response.header.session_id = conn.session_id; @@ -908,6 +446,10 @@ impl InternalSocket { conn.crypto_handler_instance.sign_packet(&mut response); self.send_packet_unbuffered(address, response).await; + + conn.data_sender.send(data).await.ok(); + + } async fn handle_ping(&self, address: PRUDPSockAddr, packet: PRUDPPacket){ @@ -993,6 +535,8 @@ impl AnyInternalSocket for InternalSocket { SYN => self.handle_syn(address, packet).await, CONNECT => self.handle_connect(address, packet).await, DATA => self.handle_data(address, packet).await, + DISCONNECT => self.handle_disconnect(address, packet).await, + PING => self.handle_ping(address, packet).await, _ => { error!( "unimplemented packet type: {}", @@ -1068,7 +612,7 @@ impl AnyInternalSocket for InternalSocket { return None; }; - let (_, crypt) = self.crypto_handler.instantiate(remote_signature, *own_signature, &[], 1); + let (_, crypt) = self.crypto_handler.instantiate(remote_signature, *own_signature, &[], 1)?; //todo: make this work for secure servers as well self.create_connection(crypt, address, 0).await; @@ -1130,7 +674,7 @@ pub trait CryptoHandler: Send + Sync + 'static { own_signature: [u8; 16], _: &[u8], substream_count: u8, - ) -> (Vec, Self::CryptoConnectionInstance); + ) -> Option<(Vec, Self::CryptoConnectionInstance)>; fn sign_pre_handshake(&self, packet: &mut PRUDPPacket); } @@ -1162,6 +706,7 @@ impl ExternalConnection{ impl SendingConnection{ pub async fn send(&self, data: Vec) -> Option<()> { + println!("{}", hex::encode(&data)); let internal = self.inernal.upgrade()?; let mut internal = internal.lock().await; @@ -1169,81 +714,4 @@ impl SendingConnection{ internal.send_data_packet(data).await; Some(()) } -} - -pub struct Unsecure(pub &'static str); - -pub struct UnsecureInstance { - key: &'static str, - streams: Vec>>, - self_signature: [u8; 16], - remote_signature: [u8; 16], -} - -// my hand was forced to use lazy so that we can guarantee this code -// only runs once and so that i can put it here as a "constant" (for performance and readability) -// since for some reason rust crypto doesn't have any const time key initialization -static DEFAULT_KEY: Lazy> = Lazy::new(|| Key::from(*b"CD&ML")); - -impl CryptoHandler for Unsecure { - type CryptoConnectionInstance = UnsecureInstance; - - fn instantiate( - &self, - remote_signature: [u8; 16], - self_signature: [u8; 16], - _: &[u8], - substream_count: u8, - ) -> (Vec, Self::CryptoConnectionInstance) { - ( - Vec::new(), - UnsecureInstance { - streams: (0..substream_count) - .map(|_| EncryptionPair::init_both(|| Rc4::new(&DEFAULT_KEY))) - .collect(), - key: self.0, - remote_signature, - self_signature, - }, - ) - } - - fn sign_pre_handshake(&self, packet: &mut PRUDPPacket) { - packet.set_sizes(); - packet.calculate_and_assign_signature(self.0, None, None); - } -} - -impl CryptoHandlerConnectionInstance for UnsecureInstance { - type Encryption = Rc4; - - fn decrypt_incoming(&mut self, substream: u8, data: &mut [u8]) { - if let Some(crypt_pair) = self.streams.get_mut(substream as usize){ - crypt_pair.recv.apply_keystream(data); - } - } - - fn encrypt_outgoing(&mut self, substream: u8, data: &mut [u8]) { - if let Some(crypt_pair) = self.streams.get_mut(substream as usize){ - crypt_pair.send.apply_keystream(data); - } - } - - fn get_user_id(&self) -> u32 { - 0 - } - - fn sign_connect(&self, packet: &mut PRUDPPacket) { - packet.set_sizes(); - packet.calculate_and_assign_signature(self.key, None, Some(self.self_signature)); - } - - fn sign_packet(&self, packet: &mut PRUDPPacket) { - packet.set_sizes(); - packet.calculate_and_assign_signature(self.key, None, Some(self.self_signature)); - } - - fn verify_packet(&self, packet: &PRUDPPacket) -> bool { - true - } -} +} \ No newline at end of file diff --git a/src/prudp/unsecure.rs b/src/prudp/unsecure.rs new file mode 100644 index 0000000..12e15ca --- /dev/null +++ b/src/prudp/unsecure.rs @@ -0,0 +1,84 @@ +use once_cell::sync::Lazy; +use rc4::{Key, KeyInit, Rc4, StreamCipher}; +use typenum::U5; +use crate::prudp::packet::PRUDPPacket; +use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance, EncryptionPair}; + +pub struct Unsecure(pub &'static str); + + + +pub struct UnsecureInstance { + key: &'static str, + streams: Vec>>, + self_signature: [u8; 16], + remote_signature: [u8; 16], +} + +// my hand was forced to use lazy so that we can guarantee this code +// only runs once and so that i can put it here as a "constant" (for performance and readability) +// since for some reason rust crypto doesn't have any const time key initialization +static DEFAULT_KEY: Lazy> = Lazy::new(|| Key::from(*b"CD&ML")); + +impl CryptoHandler for Unsecure { + type CryptoConnectionInstance = UnsecureInstance; + + fn instantiate( + &self, + remote_signature: [u8; 16], + self_signature: [u8; 16], + _: &[u8], + substream_count: u8, + ) -> Option<(Vec, Self::CryptoConnectionInstance)> { + Some(( + Vec::new(), + UnsecureInstance { + streams: (0..substream_count) + .map(|_| EncryptionPair::init_both(|| Rc4::new(&DEFAULT_KEY))) + .collect(), + key: self.0, + remote_signature, + self_signature, + }, + )) + } + + fn sign_pre_handshake(&self, packet: &mut PRUDPPacket) { + packet.set_sizes(); + packet.calculate_and_assign_signature(self.0, None, None); + } +} + +impl CryptoHandlerConnectionInstance for UnsecureInstance { + type Encryption = Rc4; + + fn decrypt_incoming(&mut self, substream: u8, data: &mut [u8]) { + if let Some(crypt_pair) = self.streams.get_mut(substream as usize){ + crypt_pair.recv.apply_keystream(data); + } + } + + fn encrypt_outgoing(&mut self, substream: u8, data: &mut [u8]) { + if let Some(crypt_pair) = self.streams.get_mut(substream as usize){ + crypt_pair.send.apply_keystream(data); + } + } + + fn get_user_id(&self) -> u32 { + 0 + } + + fn sign_connect(&self, packet: &mut PRUDPPacket) { + packet.set_sizes(); + packet.calculate_and_assign_signature(self.key, None, Some(self.self_signature)); + } + + fn sign_packet(&self, packet: &mut PRUDPPacket) { + packet.set_sizes(); + packet.calculate_and_assign_signature(self.key, None, Some(self.self_signature)); + } + + fn verify_packet(&self, packet: &PRUDPPacket) -> bool { + true + } +} \ No newline at end of file diff --git a/src/rmc/protocols/mod.rs b/src/rmc/protocols/mod.rs index 38430df..4640592 100644 --- a/src/rmc/protocols/mod.rs +++ b/src/rmc/protocols/mod.rs @@ -34,7 +34,7 @@ pub enum RemoteCallError { ServerError(ErrorCode), #[error("Connection broke")] ConnectionBroke, - #[error("Error reading response data")] + #[error("Error reading response data: {0}")] InvalidResponse(#[from] structures::Error), } @@ -148,7 +148,7 @@ macro_rules! define_rmc_proto { $($protocol:path),* }) => { paste::paste!{ - trait []: std::any::Any $( + [] + $protocol)* { + pub trait []: std::any::Any $( + [] + $protocol)* { async fn rmc_call(&self, remote_response_connection: &crate::prudp::socket::SendingConnection, protocol_id: u16, method_id: u32, call_id: u32, rest: Vec){ match protocol_id{ $( @@ -159,7 +159,7 @@ macro_rules! define_rmc_proto { } } - struct [](crate::rmc::protocols::RmcConnection); + pub struct [](crate::rmc::protocols::RmcConnection); impl crate::rmc::protocols::RemoteInstantiatable for []{ fn new(conn: crate::rmc::protocols::RmcConnection) -> Self{ @@ -235,7 +235,7 @@ async fn handle_incoming( return }; - if proto_id & 0x80 == 0{ + if (proto_id & 0x80) == 0{ let Some(response) = RMCResponse::new(&mut Cursor::new(v)).display_err_or_some() else { error!("ending rmc gateway."); return @@ -260,9 +260,11 @@ async fn handle_incoming( rest_of_data } = message; + info!("got rmc request, handeling it now..."); + remote.rmc_call(&sending_conn, protocol_id, method_id, call_id, rest_of_data).await; - info!("got rmc request"); + } } } diff --git a/src/rmc/response.rs b/src/rmc/response.rs index 84bd529..f47ee66 100644 --- a/src/rmc/response.rs +++ b/src/rmc/response.rs @@ -36,7 +36,7 @@ pub struct RMCResponse { impl RMCResponse { pub fn new(stream: &mut (impl Seek + Read)) -> io::Result{ // ignore the size for now this will only be used for checking - let _: u32 = stream.read_struct(IS_BIG_ENDIAN)?; + let size: u32 = stream.read_struct(IS_BIG_ENDIAN)?; let protocol_id: u8 = stream.read_struct(IS_BIG_ENDIAN)?; @@ -54,9 +54,9 @@ impl RMCResponse { let method_id: u32 = stream.read_struct(IS_BIG_ENDIAN)?; let method_id = method_id & (!0x8000); - let mut data: Vec = Vec::new(); + let mut data: Vec = vec![0u8; (size - 2 - 4 - 4) as _]; - stream.read_to_end(&mut data)?; + stream.read(&mut data)?; RMCResponseResult::Success { @@ -154,15 +154,13 @@ pub async fn send_result( method_id: u32, call_id: u32, ) { + + println!("{}", hex::encode(result.clone().unwrap())); let response_result = match result { Ok(v) => RMCResponseResult::Success { call_id, method_id, - data: { - let mut vec = Vec::new(); - v.serialize(&mut vec).expect("serialization error"); - vec - } + data: v }, Err(e) => RMCResponseResult::Error { @@ -187,7 +185,7 @@ pub async fn send_response(connection: &SendingConnection, rmcresponse: RMCRespo //taken from kinnays error list directly #[allow(nonstandard_style)] #[repr(u32)] -#[derive(Debug, EnumTryInto)] +#[derive(Debug, EnumTryInto, Clone, Copy)] pub enum ErrorCode { Core_Unknown = 0x00010001, Core_NotImplemented = 0x00010002, diff --git a/src/rmc/structures/connection_data.rs b/src/rmc/structures/connection_data.rs index d0c27b1..1adbb20 100644 --- a/src/rmc/structures/connection_data.rs +++ b/src/rmc/structures/connection_data.rs @@ -1,30 +1,15 @@ use std::io::{Read, Write}; use bytemuck::bytes_of; +use macros::RmcSerialize; use crate::kerberos::KerberosDateTime; use crate::rmc::structures::{rmc_struct, RmcSerialize}; -#[derive(Debug)] -pub struct ConnectionData<'a>{ - pub station_url: &'a str, +#[derive(Debug, RmcSerialize)] +#[rmc_struct(1)] +pub struct ConnectionData{ + pub station_url: String, pub special_protocols: Vec, - pub special_station_url: &'a str, + pub special_station_url: String, pub date_time: KerberosDateTime } -impl<'a> RmcSerialize for ConnectionData<'a>{ - fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> { - rmc_struct::write_struct(writer, 1, |v|{ - self.station_url.serialize(v).expect("unable to write station url"); - self.special_protocols.serialize(v).expect("unable to write special protocols"); - self.special_station_url.serialize(v).expect("unable to write special station url"); - v.write_all(bytes_of(&self.date_time)).expect("unable to write date time"); - - Ok(()) - }) - } - - fn deserialize(_reader: &mut dyn Read) -> crate::rmc::structures::Result { - todo!() - } -} - diff --git a/src/rmc/structures/rmc_struct.rs b/src/rmc/structures/rmc_struct.rs index 2477315..8f51a5a 100644 --- a/src/rmc/structures/rmc_struct.rs +++ b/src/rmc/structures/rmc_struct.rs @@ -17,7 +17,7 @@ pub fn write_struct(writer: &mut dyn Write, version: u8, pred: impl FnOnce(&mut (pred)(&mut scratch_space)?; - let u32_size= scratch_space.len() as u32; + let u32_size = scratch_space.len() as u32; writer.write_all(bytes_of(&u32_size))?; writer.write_all(&scratch_space)?;