From b097c298e705cb27ab5691e15fb3314473f5a924 Mon Sep 17 00:00:00 2001 From: DJMrTV Date: Mon, 3 Feb 2025 20:43:24 +0100 Subject: [PATCH] feat(secure server): start working on secure server --- src/main.rs | 94 ++++++++++++++++++++++++--- src/protocols/auth/method_login_ex.rs | 2 + src/prudp/socket.rs | 87 +++++++++++++++++++------ 3 files changed, 155 insertions(+), 28 deletions(-) diff --git a/src/main.rs b/src/main.rs index 999f9aa..a54a641 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,12 +3,14 @@ use std::{env, fs}; use std::fs::File; use std::net::{Ipv4Addr, SocketAddrV4}; +use std::sync::Arc; use chrono::Local; use log::info; use once_cell::sync::Lazy; use rc4::{KeyInit, Rc4, StreamCipher}; use rc4::consts::U5; use simplelog::{ColorChoice, CombinedLogger, Config, LevelFilter, TerminalMode, TermLogger, WriteLogger}; +use tokio::task::JoinHandle; use crate::nex::account::Account; use crate::protocols::auth; use crate::protocols::auth::AuthProtocolConfig; @@ -43,6 +45,12 @@ static AUTH_SERVER_PORT: Lazy = Lazy::new(||{ .and_then(|s| s.parse().ok()) .unwrap_or(10000) }); +static SECURE_SERVER_PORT: Lazy = Lazy::new(||{ + env::var("SECURE_SERVER_PORT") + .ok() + .and_then(|s| s.parse().ok()) + .unwrap_or(10001) +}); static OWN_IP: Lazy = Lazy::new(||{ env::var("SERVER_IP") @@ -51,6 +59,10 @@ static OWN_IP: Lazy = Lazy::new(||{ .expect("no public ip specified") }); +static SECURE_STATION_URL: Lazy = Lazy::new(|| + format!("prudps:/PID=2;sid=1;stream=10;type=2;address={};port={};CID=1", *OWN_IP, *SECURE_SERVER_PORT) +); + #[tokio::main] async fn main() { CombinedLogger::init( @@ -68,14 +80,16 @@ async fn main() { start_servers().await; } -async fn auth_server_handle_rmc(_packet: PRUDPPacket, _rmc_message: RMCMessage){ - +struct AuthServer{ + router: Arc, + join_handle: JoinHandle<()>, + socket: Socket } -async fn start_servers(){ +async fn start_auth_server() -> AuthServer{ info!("starting auth server on {}:{}", *OWN_IP, *AUTH_SERVER_PORT); - let (auth_server_router, auth_router_join) = + let (router, join_handle) = Router::new(SocketAddrV4::new(*OWN_IP, *AUTH_SERVER_PORT)).await .expect("unable to startauth server"); @@ -86,16 +100,16 @@ async fn start_servers(){ let auth_protocol_config = AuthProtocolConfig{ secure_server_account: &SECURE_SERVER_ACCOUNT, build_name: "branch:origin/project/wup-agmj build:3_8_15_2004_0", - station_url: "prudps:/PID=2;sid=1;stream=10;type=2;address=31.220.75.208;port=10001;CID=1" + station_url: &SECURE_STATION_URL }; let rmcserver = RMCProtocolServer::new(Box::new([ Box::new(auth::bound_protocol(auth_protocol_config)) ])); - let mut _socket = + let mut socket = Socket::new( - auth_server_router.clone(), + router.clone(), VirtualPort::new(1,10), "6f599f81", Box::new(|_|{ @@ -109,7 +123,7 @@ async fn start_servers(){ let cypher = Box::new(rc4); let client_cypher: Box = cypher; - (true, (server_cypher, client_cypher)) + Some((Vec::new(), (server_cypher, client_cypher), None)) } ) }), @@ -119,7 +133,69 @@ async fn start_servers(){ }) ).await.expect("unable to create socket"); - auth_router_join.await.expect("auth server crashed") + AuthServer{ + join_handle, + router, + socket, + } +} + +struct SecureServer{ + router: Arc, + join_handle: JoinHandle<()>, + socket: Socket +} + +async fn start_secure_server() -> SecureServer{ + info!("starting secure server on {}:{}", *OWN_IP, *SECURE_SERVER_PORT); + + let (router, join_handle) = + Router::new(SocketAddrV4::new(*OWN_IP, *SECURE_SERVER_PORT)).await + .expect("unable to startauth server"); + + info!("setting up endpoints"); + + let rmcserver = RMCProtocolServer::new(Box::new([])); + + let mut socket = + Socket::new( + router.clone(), + VirtualPort::new(1,10), + "6f599f81", + Box::new(|p|{ + Box::pin( + async move { + let rc4: Rc4 = Rc4::new_from_slice( "CD&ML".as_bytes()).unwrap(); + let cypher = Box::new(rc4); + let server_cypher: Box = cypher; + + let rc4: Rc4 = Rc4::new_from_slice( "CD&ML".as_bytes()).unwrap(); + let cypher = Box::new(rc4); + let client_cypher: Box = cypher; + + Some((Vec::new(), (server_cypher, client_cypher), None)) + } + ) + }), + Box::new(move |packet, socket, connection|{ + let rmcserver = rmcserver.clone(); + Box::pin(async move { rmcserver.process_message(packet, &socket, connection).await; }) + }) + ).await.expect("unable to create socket"); + + SecureServer{ + join_handle, + router, + socket, + } +} + +async fn start_servers(){ + let auth_server = start_auth_server().await; + let secure_server = start_secure_server().await; + + auth_server.join_handle.await.expect("auth server crashed"); + secure_server.join_handle.await.expect("auth server crashed"); } diff --git a/src/protocols/auth/method_login_ex.rs b/src/protocols/auth/method_login_ex.rs index cc80dce..6c2504c 100644 --- a/src/protocols/auth/method_login_ex.rs +++ b/src/protocols/auth/method_login_ex.rs @@ -15,6 +15,8 @@ use crate::rmc::structures::connection_data::ConnectionData; use crate::rmc::structures::qresult::QResult; pub async fn login_ex(rmcmessage: &RMCMessage, proto_data: AuthProtocolConfig, pid: u32) -> RMCResponseResult{ + return rmcmessage.error_result_with_code(ErrorCode::Authentication_OutOfService); + // todo: figure out how the AuthenticationInfo struct works, parse it and validate login info let Ok(mut client) = account::Client::new().await else { diff --git a/src/prudp/socket.rs b/src/prudp/socket.rs index 63e1d5b..4bf9f0c 100644 --- a/src/prudp/socket.rs +++ b/src/prudp/socket.rs @@ -11,7 +11,7 @@ use rc4::StreamCipher; use crate::prudp::packet::{PacketOption, PRUDPPacket, VirtualPort}; use crate::prudp::packet::flags::{ACK, HAS_SIZE, MULTI_ACK, NEED_ACK, RELIABLE}; use crate::prudp::packet::PacketOption::{ConnectionSignature, MaximumSubstreamId, SupportedFunctions}; -use crate::prudp::packet::types::{CONNECT, DATA, PING, SYN}; +use crate::prudp::packet::types::{CONNECT, DATA, DISCONNECT, PING, SYN}; use crate::prudp::router::{Error, Router}; use crate::prudp::sockaddr::PRUDPSockAddr; @@ -26,9 +26,14 @@ pub struct Socket { } -type OnConnectHandlerFn = Box Pin, Box))> + Send>> + Send + Sync>; +type OnConnectHandlerFn = Box Pin, (Box, Box), Option)>> + Send>> + Send + Sync>; type OnDataHandlerFn = Box Fn(PRUDPPacket, Arc, &'a mut MutexGuard<'_, ConnectionData>) -> Pin + 'a + Send>> + Send + Sync>; +pub struct ActiveSecureConnectionData { + pid: u32, + session_key: [u8; 32], +} + pub struct SocketData { virtual_port: VirtualPort, pub socket: Arc, @@ -45,6 +50,7 @@ pub struct ActiveConnectionData { server_encryption: Box, client_decryption: Box, pub server_session_id: u8, + pub active_secure_connection_data: Option } @@ -212,6 +218,25 @@ impl SocketData { CONNECT => { info!("got connect"); + let Some(( + accepted, + (client_decryption, server_encryption), + active_secure_connection_data + )) = (self.on_connect_handler)(packet.clone()).await else { + error!("invalid connection request"); + return; + }; + + connection.active_connection_data = Some(ActiveConnectionData { + client_decryption, + server_encryption, + reliable_client_queue: VecDeque::new(), + reliable_client_counter: 2, + reliable_server_counter: 1, + server_session_id: packet.header.session_id, + active_secure_connection_data + }); + let mut response_packet = packet.base_response_packet(); response_packet.header.types_and_flags.set_types(CONNECT); @@ -253,29 +278,21 @@ impl SocketData { response_packet.set_sizes(); - response_packet.calculate_and_assign_signature(self.access_key, None, Some(connection.server_signature)); + let potential_session_key = connection + .active_connection_data + .as_ref() + .unwrap().active_secure_connection_data + .as_ref() + .map(|s| s.session_key); + + response_packet.calculate_and_assign_signature(self.access_key, potential_session_key, 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"); - let (accepted, (client_decryption, server_encryption)) - = (self.on_connect_handler)(packet.clone()).await; - if !accepted { - // rejected - return; - } - - connection.active_connection_data = Some(ActiveConnectionData { - client_decryption, - server_encryption, - reliable_client_queue: VecDeque::new(), - reliable_client_counter: 2, - reliable_server_counter: 1, - server_session_id: packet.header.session_id, - }); } DATA => { if (packet.header.types_and_flags.get_flags() & RELIABLE) != 0 { @@ -362,7 +379,37 @@ impl SocketData { self.socket.send_to(&vec, client_address.regular_socket_addr).await.expect("failed to send data back"); } } - 3 => {} + DISCONNECT => { + let ConnectionData{ + server_signature, + active_connection_data, + .. + } = &*connection; + + let Some(active_connection) = active_connection_data.as_ref() else { + return; + }; + + let mut ack = packet.base_acknowledgement_packet(); + + ack.set_sizes(); + + let potential_session_key = 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(*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"); + } _ => unimplemented!("unimplemented packet type: {}", packet.header.types_and_flags.get_types()) } } @@ -370,6 +417,8 @@ impl SocketData { impl ConnectionData{ pub async fn finish_and_send_packet_to(&mut self, socket: &SocketData, mut packet: PRUDPPacket){ + println!("{}", hex::encode(&packet.payload)); + 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");