From 926b7cf5bb71a0c5e05a886919544963321e2f7f Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Sat, 10 Aug 2024 20:50:18 +0200 Subject: [PATCH] Return ERR_INPUTTOOLONG instead of closing connection on messages longer than ~1020 bytes As recommended by https://ircv3.net/specs/extensions/message-tags#size-limit --- Cargo.lock | 1 + client_listener/Cargo.toml | 1 + client_listener/src/error.rs | 2 ++ client_listener/src/internal/connection_task.rs | 6 +++++- sable_ircd/src/messages/numeric.rs | 1 + sable_ircd/src/server/mod.rs | 10 +++++++++- 6 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 608c59db..c379068f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -494,6 +494,7 @@ dependencies = [ name = "client_listener" version = "0.1.0" dependencies = [ + "bincode", "console-subscriber", "hex", "libc", diff --git a/client_listener/Cargo.toml b/client_listener/Cargo.toml index 3bb6e956..96dd311c 100644 --- a/client_listener/Cargo.toml +++ b/client_listener/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" [dependencies] sable_macros = { path = "../sable_macros" } sable_ipc = { path = "../sable_ipc" } +bincode = "1.3" tracing = "0.1" thiserror = "1" serde = { version = "1", features = [ "derive" ] } diff --git a/client_listener/src/error.rs b/client_listener/src/error.rs index 0e0bd09a..b2c0d11d 100644 --- a/client_listener/src/error.rs +++ b/client_listener/src/error.rs @@ -13,6 +13,8 @@ pub enum ConnectionError { InternalError, #[error("Send queue full")] SendQueueFull, + #[error("Input line was too long")] + InputLineTooLong, } /// An error that might occur when configuring a listener. diff --git a/client_listener/src/internal/connection_task.rs b/client_listener/src/internal/connection_task.rs index e632fe8a..59d72d16 100644 --- a/client_listener/src/internal/connection_task.rs +++ b/client_listener/src/internal/connection_task.rs @@ -51,7 +51,11 @@ where message = lines.next_line() => match message { Ok(None) => { break; }, Ok(Some(m)) => { - if self.event_channel.send(InternalConnectionEventType::Event(InternalConnectionEvent::Message(self.id, m))).await.is_err() { + if m.as_bytes().len() as u64 > crate::MAX_MSG_SIZE { + if self.event_channel.send(InternalConnectionEventType::Event(InternalConnectionEvent::ConnectionError(self.id, ConnectionError::InputLineTooLong))).await.is_err() { + tracing::error!("Error notifying socket error on connection {:?}", self.id); + } + } else if self.event_channel.send(InternalConnectionEventType::Event(InternalConnectionEvent::Message(self.id, m))).await.is_err() { tracing::error!("Error notifying socket message on connection {:?}", self.id); } } diff --git a/sable_ircd/src/messages/numeric.rs b/sable_ircd/src/messages/numeric.rs index 4b3b9ac9..17670602 100644 --- a/sable_ircd/src/messages/numeric.rs +++ b/sable_ircd/src/messages/numeric.rs @@ -78,6 +78,7 @@ define_messages! { 406(WasNoSuchNick) => { (nick: &Nickname) => "{nick} :There was no such nickname" }, 410(InvalidCapCmd) => { (subcommand: &str) => "{subcommand} :Invalid CAP command" }, 412(NoTextToSend) => { () => ":No text to send" }, + 417(InputTooLong) => { () => ":Input line was too long" }, 421(UnknownCommand) => { (command: &str) => "{command} :Unknown command" }, 432(ErroneousNickname) => { (nick: &str) => "{nick} :Erroneous nickname" }, 433(NicknameInUse) => { (nick: &Nickname) => "{nick} :Nickname is already in use." }, diff --git a/sable_ircd/src/server/mod.rs b/sable_ircd/src/server/mod.rs index 0dd4ec23..2f955782 100644 --- a/sable_ircd/src/server/mod.rs +++ b/sable_ircd/src/server/mod.rs @@ -336,7 +336,15 @@ impl ClientServer { .await; } } - conn.send(message::Error::new(&e.to_string())); + match e { + ConnectionError::InputLineTooLong => { + conn.send(numeric::InputTooLong::new_for( + &self.node.name().to_string(), + &"*".to_string(), + )) + } + _ => conn.send(message::Error::new(&e.to_string())), + } } self.connections.write().remove(msg.source); }