From 59c1ebe6881c73c4e5cfb219fd888f4ab42d34ba Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Sun, 8 Dec 2024 20:09:40 +0100 Subject: [PATCH] Add LINKS command This will be used by irctest to wait for sable_history to be up and reachable --- sable_ircd/src/command/handlers/links.rs | 25 +++++++++++++++++++ sable_ircd/src/command/mod.rs | 1 + sable_ircd/src/messages/numeric.rs | 3 +++ sable_network/src/policy/debugging_policy.rs | 11 ++++++++ sable_network/src/policy/mod.rs | 11 ++++++++ .../src/policy/standard_debugging_policy.rs | 16 ++++++++++++ 6 files changed, 67 insertions(+) create mode 100644 sable_ircd/src/command/handlers/links.rs create mode 100644 sable_network/src/policy/debugging_policy.rs create mode 100644 sable_network/src/policy/standard_debugging_policy.rs diff --git a/sable_ircd/src/command/handlers/links.rs b/sable_ircd/src/command/handlers/links.rs new file mode 100644 index 00000000..d200b492 --- /dev/null +++ b/sable_ircd/src/command/handlers/links.rs @@ -0,0 +1,25 @@ +use super::*; +use sable_network::prelude::wrapper::ObjectWrapper; + +#[command_handler("LINKS")] +fn handle_links( + response: &dyn CommandResponse, + server: &ClientServer, + net: &Network, + source: UserSource, +) -> CommandResult { + server.policy().can_list_links(&source)?; + + for server in net.servers() { + let server_info = format!( + "last_ping={}, version={}", + server.last_ping(), + server.raw().version + ); + response.numeric(make_numeric!(Links, server.name(), 0, &server_info)); + } + + response.numeric(make_numeric!(EndOfLinks)); + + Ok(()) +} diff --git a/sable_ircd/src/command/mod.rs b/sable_ircd/src/command/mod.rs index 054b9347..dbd58d2e 100644 --- a/sable_ircd/src/command/mod.rs +++ b/sable_ircd/src/command/mod.rs @@ -48,6 +48,7 @@ mod handlers { mod kick; mod kill; mod kline; + mod links; mod mode; mod monitor; mod motd; diff --git a/sable_ircd/src/messages/numeric.rs b/sable_ircd/src/messages/numeric.rs index 1404c767..73155268 100644 --- a/sable_ircd/src/messages/numeric.rs +++ b/sable_ircd/src/messages/numeric.rs @@ -51,6 +51,9 @@ define_messages! { => "{chname} {user} {host} * {nick} {status} :{hopcount} {realname}" }, 353(NamesReply) => { (is_pub: char, chan: &Channel.name(), content: &str) => "{is_pub} {chan} :{content}" }, + 364(Links) => { (server_name: &ServerName, hopcount: u64, server_info: &str) + => "* {server_name} :{hopcount} {server_info}" }, + 365(EndOfLinks) => { () => "* :End of /LINKS list" }, 366(EndOfNames) => { (chname: &str) => "{chname} :End of names list" }, 369(EndOfWhowas) => { (nick: &Nickname) => "{nick} :End of /WHOWAS" }, diff --git a/sable_network/src/policy/debugging_policy.rs b/sable_network/src/policy/debugging_policy.rs new file mode 100644 index 00000000..725ba1e7 --- /dev/null +++ b/sable_network/src/policy/debugging_policy.rs @@ -0,0 +1,11 @@ +#![allow(clippy::crate_in_macro_def)] + +use super::*; + +/// Makes authorisation decisions regarding inspecting private but non-sensitive +/// network information +#[delegatable_trait] +pub trait DebuggingPolicyService { + /// Determine whether a given user is permitted to oper up + fn can_list_links(&self, user: &wrapper::User) -> PermissionResult; +} diff --git a/sable_network/src/policy/mod.rs b/sable_network/src/policy/mod.rs index 2c30a1fb..5212832e 100644 --- a/sable_network/src/policy/mod.rs +++ b/sable_network/src/policy/mod.rs @@ -21,6 +21,10 @@ pub use user_policy::*; mod oper_policy; pub use oper_policy::*; +#[macro_use] +mod debugging_policy; +pub use debugging_policy::*; + #[macro_use] mod registration_policy; pub use registration_policy::*; @@ -34,6 +38,9 @@ pub use standard_user_policy::*; mod standard_oper_policy; pub use standard_oper_policy::*; +mod standard_debugging_policy; +pub use standard_debugging_policy::*; + mod standard_registration_policy; pub use standard_registration_policy::*; @@ -49,6 +56,7 @@ pub trait PolicyService: + UserPolicyService + OperAuthenticationService + OperPolicyService + + DebuggingPolicyService + RegistrationPolicyService + Sync + Send @@ -61,12 +69,14 @@ pub trait PolicyService: #[delegate(ChannelPolicyService, target = "channel_policy")] #[delegate(UserPolicyService, target = "user_policy")] #[delegate(OperPolicyService, target = "oper_policy")] +#[delegate(DebuggingPolicyService, target = "debugging_policy")] #[delegate(OperAuthenticationService, target = "oper_policy")] #[delegate(RegistrationPolicyService, target = "registration_policy")] pub struct StandardPolicyService { channel_policy: StandardChannelPolicy, user_policy: StandardUserPolicy, oper_policy: StandardOperPolicy, + debugging_policy: StandardDebuggingPolicy, registration_policy: StandardRegistrationPolicy, } @@ -76,6 +86,7 @@ impl StandardPolicyService { channel_policy: StandardChannelPolicy::new(), user_policy: StandardUserPolicy::new(), oper_policy: StandardOperPolicy::new(), + debugging_policy: StandardDebuggingPolicy::new(), registration_policy: StandardRegistrationPolicy::new(), } } diff --git a/sable_network/src/policy/standard_debugging_policy.rs b/sable_network/src/policy/standard_debugging_policy.rs new file mode 100644 index 00000000..95297bc3 --- /dev/null +++ b/sable_network/src/policy/standard_debugging_policy.rs @@ -0,0 +1,16 @@ +use super::*; + +/// Standard implementation of [`DebuggingPolicyService`] +pub struct StandardDebuggingPolicy {} + +impl StandardDebuggingPolicy { + pub fn new() -> Self { + Self {} + } +} + +impl DebuggingPolicyService for StandardDebuggingPolicy { + fn can_list_links(&self, _user: &wrapper::User) -> PermissionResult { + Ok(()) + } +}