From 4b86de3b62b4fb9c70c1f4d24c76cbc2c46fb930 Mon Sep 17 00:00:00 2001 From: reverse Date: Mon, 17 Aug 2026 19:06:17 +0000 Subject: [PATCH] registration: add a Hold verdict so captcha/challenge modules pend the client for the challenge instead of tearing the link down --- src/ircd.rs | 20 +++++++++++++------- src/module.rs | 6 ++++++ src/modules/cloudflare_challenge.rs | 3 ++- src/modules/recaptcha.rs | 3 ++- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/ircd.rs b/src/ircd.rs index 6c034c5..83766aa 100644 --- a/src/ircd.rs +++ b/src/ircd.rs @@ -545,13 +545,19 @@ impl Ircd { fn complete_registration(&mut self, uid: Uid) { for m in &mut self.modules { - if m.on_user_register(&mut self.server, uid) == ModResult::Deny { - self.server.send( - uid, - "ERROR :Closing link (registration refused)".to_string(), - ); - self.server.remove_user(uid, "Registration refused"); - return; + match m.on_user_register(&mut self.server, uid) { + ModResult::Deny => { + self.server.send( + uid, + "ERROR :Closing link (registration refused)".to_string(), + ); + self.server.remove_user(uid, "Registration refused"); + return; + } + // a challenge is pending: keep the connection, don't welcome yet. + // A later command (the CAPTCHA/VERIFYCHALLENGE reply) re-runs this. + ModResult::Hold => return, + _ => {} } } // x-line: refuse a banned host / ip before welcoming diff --git a/src/module.rs b/src/module.rs index e2c1ae7..d999e3e 100644 --- a/src/module.rs +++ b/src/module.rs @@ -15,6 +15,12 @@ pub enum ModResult { Passthru, Allow, Deny, + /// `on_user_register` only: hold the client in the pre-registration state (a + /// challenge is pending) without completing OR refusing the link. Registration + /// resumes on a later command once the hold clears (e.g. the client presents a + /// CAPTCHA/VERIFYCHALLENGE token). If they never do, the registration timeout + /// reaps them like any other stalled connection. + Hold, } /// A queued notify-event, drained by the core after each command. diff --git a/src/modules/cloudflare_challenge.rs b/src/modules/cloudflare_challenge.rs index e198c5b..ae9b6d2 100644 --- a/src/modules/cloudflare_challenge.rs +++ b/src/modules/cloudflare_challenge.rs @@ -93,7 +93,8 @@ impl Module for CloudflareChallenge { let msg = template.replace("{url}", &link); srv.send(uid, format!(":{} NOTICE {nick} :{msg}", srv.name)); } - ModResult::Deny + // Hold the connection for the challenge (VERIFYCHALLENGE ), don't drop it. + ModResult::Hold } } diff --git a/src/modules/recaptcha.rs b/src/modules/recaptcha.rs index 480df32..0922f47 100644 --- a/src/modules/recaptcha.rs +++ b/src/modules/recaptcha.rs @@ -103,7 +103,8 @@ impl Module for ReCaptcha { let msg = template.replace("{url}", &link); srv.send(uid, format!(":{} NOTICE {nick} :{msg}", srv.name)); } - ModResult::Deny + // Hold the connection for the challenge (CAPTCHA ), don't tear it down. + ModResult::Hold } }