From e406b4e1e0de40bf59f2a2313cce90616ac836b5 Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Sun, 25 Jan 2026 11:06:26 +0100 Subject: [PATCH 1/2] Reply with RPL_SASLFAIL instead of NOTICE on invalid base64 This is consistent with Ergo, InspIRCd, Solanum, UnrealIRCd --- sable_ircd/src/command/handlers/services/sasl.rs | 10 ++++++---- sable_ircd/src/messages/numeric.rs | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/sable_ircd/src/command/handlers/services/sasl.rs b/sable_ircd/src/command/handlers/services/sasl.rs index 9fa74fc3..268e1549 100644 --- a/sable_ircd/src/command/handlers/services/sasl.rs +++ b/sable_ircd/src/command/handlers/services/sasl.rs @@ -6,6 +6,8 @@ use sable_network::{ use super::*; use base64::prelude::*; +const DEFAULT_SASL_FAIL: &str = "SASL authentication failed"; + #[command_handler("AUTHENTICATE")] async fn handle_authenticate( source: PreClientSource, @@ -22,7 +24,7 @@ async fn handle_authenticate( RemoteServicesServerRequestType::AbortAuthenticate(*session) } else { let Ok(data) = BASE64_STANDARD.decode(text) else { - response.notice("Invalid base64"); + response.numeric(make_numeric!(SaslFail, "Invalid Base64")); return Ok(()); }; @@ -39,7 +41,7 @@ async fn handle_authenticate( for ban in net.network_bans().find_pre_sasl(&user_details) { if let NetworkBanAction::DenySasl = ban.action { - response.numeric(make_numeric!(SaslFail)); + response.numeric(make_numeric!(SaslFail, DEFAULT_SASL_FAIL)); return Ok(()); } } @@ -88,7 +90,7 @@ async fn handle_authenticate( response.numeric(make_numeric!(SaslSuccess)); } Fail => { - response.numeric(make_numeric!(SaslFail)); + response.numeric(make_numeric!(SaslFail, DEFAULT_SASL_FAIL)); } Aborted => { response.numeric(make_numeric!(SaslAborted)); @@ -116,6 +118,6 @@ fn do_sasl_external( } } - response.numeric(make_numeric!(SaslFail)); + response.numeric(make_numeric!(SaslFail, DEFAULT_SASL_FAIL)); Ok(()) } diff --git a/sable_ircd/src/messages/numeric.rs b/sable_ircd/src/messages/numeric.rs index edfbc932..3c2e8889 100644 --- a/sable_ircd/src/messages/numeric.rs +++ b/sable_ircd/src/messages/numeric.rs @@ -138,6 +138,6 @@ define_messages! { 900(LoggedIn) => { (account: &Nickname) => "* {account} :You are now logged in as {account}" }, // TODO: !@ instead of * 903(SaslSuccess) => { () => ":SASL authentication successful" }, - 904(SaslFail) => { () => ":SASL authentication failed" }, + 904(SaslFail) => { (reason: &str) => ":{reason}" }, 906(SaslAborted) => { () => ":SASL authentication aborted" } } From 2feaf5bbf5f02d1de2f4cf624eca84d1ec96499f Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Sun, 25 Jan 2026 11:52:36 +0100 Subject: [PATCH 2/2] Use default failure message even for invalid base64 A future commit will make SaslFail round-trip through services, which makes it not work as-is; and base64 issues should be pretty rare so they are not worth bothering --- sable_ircd/src/command/handlers/services/sasl.rs | 10 ++++------ sable_ircd/src/messages/numeric.rs | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/sable_ircd/src/command/handlers/services/sasl.rs b/sable_ircd/src/command/handlers/services/sasl.rs index 268e1549..e2486188 100644 --- a/sable_ircd/src/command/handlers/services/sasl.rs +++ b/sable_ircd/src/command/handlers/services/sasl.rs @@ -6,8 +6,6 @@ use sable_network::{ use super::*; use base64::prelude::*; -const DEFAULT_SASL_FAIL: &str = "SASL authentication failed"; - #[command_handler("AUTHENTICATE")] async fn handle_authenticate( source: PreClientSource, @@ -24,7 +22,7 @@ async fn handle_authenticate( RemoteServicesServerRequestType::AbortAuthenticate(*session) } else { let Ok(data) = BASE64_STANDARD.decode(text) else { - response.numeric(make_numeric!(SaslFail, "Invalid Base64")); + response.numeric(make_numeric!(SaslFail)); return Ok(()); }; @@ -41,7 +39,7 @@ async fn handle_authenticate( for ban in net.network_bans().find_pre_sasl(&user_details) { if let NetworkBanAction::DenySasl = ban.action { - response.numeric(make_numeric!(SaslFail, DEFAULT_SASL_FAIL)); + response.numeric(make_numeric!(SaslFail)); return Ok(()); } } @@ -90,7 +88,7 @@ async fn handle_authenticate( response.numeric(make_numeric!(SaslSuccess)); } Fail => { - response.numeric(make_numeric!(SaslFail, DEFAULT_SASL_FAIL)); + response.numeric(make_numeric!(SaslFail)); } Aborted => { response.numeric(make_numeric!(SaslAborted)); @@ -118,6 +116,6 @@ fn do_sasl_external( } } - response.numeric(make_numeric!(SaslFail, DEFAULT_SASL_FAIL)); + response.numeric(make_numeric!(SaslFail)); Ok(()) } diff --git a/sable_ircd/src/messages/numeric.rs b/sable_ircd/src/messages/numeric.rs index 3c2e8889..edfbc932 100644 --- a/sable_ircd/src/messages/numeric.rs +++ b/sable_ircd/src/messages/numeric.rs @@ -138,6 +138,6 @@ define_messages! { 900(LoggedIn) => { (account: &Nickname) => "* {account} :You are now logged in as {account}" }, // TODO: !@ instead of * 903(SaslSuccess) => { () => ":SASL authentication successful" }, - 904(SaslFail) => { (reason: &str) => ":{reason}" }, + 904(SaslFail) => { () => ":SASL authentication failed" }, 906(SaslAborted) => { () => ":SASL authentication aborted" } }