From 7ba68cedbd912713c5ee1c6add99fd432bd494c8 Mon Sep 17 00:00:00 2001 From: soruh Date: Sun, 9 Jul 2023 00:43:52 +0200 Subject: [PATCH] only allow clients that are already registered --- src/client.rs | 51 ++++++++++++++++++++++++++++++++------------------ src/packets.rs | 1 + 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/client.rs b/src/client.rs index b518d80..573f7b4 100644 --- a/src/client.rs +++ b/src/client.rs @@ -16,11 +16,19 @@ use crate::{ auth::dyn_ip_update, constants::{AUTH_TIMEOUT, CALL_ACK_TIMEOUT, CALL_TIMEOUT, PING_TIMEOUT, SEND_PING_INTERVAL}, http::peer_query, - packets::{Header, Packet, PacketKind, RemConnect, REJECT_OOP, REJECT_TIMEOUT}, + packets::{ + Header, Packet, PacketKind, RemConnect, REJECT_OOP, REJECT_TIMEOUT, REJECT_UNKNOWN_CLIENT, + }, ports::{PortHandler, PortStatus}, Config, HandlerMetadata, }; +pub enum AuthResult { + OutOfPorts, + UnknownClient, + Success { port: u16 }, +} + /// # Errors /// - the client authentication fails #[instrument(skip(config, port_handler, handler_metadata))] @@ -30,7 +38,16 @@ async fn authenticate( handler_metadata: &mut HandlerMetadata, number: u32, pin: u16, -) -> eyre::Result> { +) -> eyre::Result { + // TODO: do we want to cache this? If so, for how long? + let name = peer_query(&config.dyn_ip_server, number).await?; + + let Some(name) = name else { + return Ok(AuthResult::UnknownClient); + }; + + info!(%name, "found client"); + let mut authenticated = false; loop { let mut updated_server = false; @@ -41,7 +58,7 @@ async fn authenticate( .allocate_port_for_number(config, number); let Some(port) = port else { - return Ok(None); + return Ok(AuthResult::OutOfPorts); }; // make sure the client is authenticated before opening any ports @@ -71,19 +88,10 @@ async fn authenticate( let _ip = dyn_ip_update(&config.dyn_ip_server, number, pin, port).await?; } - // TODO: do we want to cache this? If so, for how long? - #[cfg(feature = "debug_server")] - let name = peer_query(&config.dyn_ip_server, number).await?; - let mut port_handler = port_handler.lock().await; - - #[cfg(feature = "debug_server")] - if let Some(name) = name { - info!(%name, "found client name"); - port_handler.names.insert(number, name); - } - port_handler.register_update(); + + port_handler.names.insert(number, name); port_handler .port_state .entry(port) @@ -92,7 +100,7 @@ async fn authenticate( handler_metadata.port = Some(port); - break Ok(Some(port)); + break Ok(AuthResult::Success { port }); } port_handler.lock().await.mark_port_error(number, port); @@ -340,9 +348,16 @@ pub async fn handler( handler_metadata.number = Some(number); - let Some(port) = authenticate(config, port_handler, handler_metadata, number, pin).await? else { - writer.write_all(REJECT_OOP).await?; - return Ok(()); + let port = match authenticate(config, port_handler, handler_metadata, number, pin).await? { + AuthResult::OutOfPorts => { + writer.write_all(REJECT_OOP).await?; + return Ok(()); + } + AuthResult::UnknownClient => { + writer.write_all(REJECT_UNKNOWN_CLIENT).await?; + return Ok(()); + } + AuthResult::Success { port } => port, }; info!(%addr, number, port, "authenticated"); diff --git a/src/packets.rs b/src/packets.rs index 3ae3d30..310ff74 100644 --- a/src/packets.rs +++ b/src/packets.rs @@ -10,6 +10,7 @@ use tokio::{ pub const REJECT_OOP: &[u8; 6] = b"\x04\x04oop\x00"; pub const REJECT_TIMEOUT: &[u8; 10] = b"\x04\x08timeout\x00"; +pub const REJECT_UNKNOWN_CLIENT: &[u8; 17] = b"\x04\x0funknown client\x00"; #[derive(Debug)] pub enum Error {