captcha: issue the challenge once per held client, not on every command they send
This commit is contained in:
parent
d6cc813aad
commit
f2e23fffa9
2 changed files with 41 additions and 1 deletions
|
|
@ -19,6 +19,11 @@ use crate::Uid;
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct Passed(HashSet<Uid>);
|
struct Passed(HashSet<Uid>);
|
||||||
|
|
||||||
|
/// uids already handed a challenge, so a held client sending extra commands doesn't
|
||||||
|
/// get the challenge notice re-issued each time. In `Server.ext`.
|
||||||
|
#[derive(Default)]
|
||||||
|
struct Challenged(HashSet<Uid>);
|
||||||
|
|
||||||
fn enabled(s: &Server) -> bool {
|
fn enabled(s: &Server) -> bool {
|
||||||
s.conf_bool("cloudflare_challenge", false)
|
s.conf_bool("cloudflare_challenge", false)
|
||||||
&& s.conf("cloudflare_secret").is_some_and(|v| !v.is_empty())
|
&& s.conf("cloudflare_secret").is_some_and(|v| !v.is_empty())
|
||||||
|
|
@ -66,6 +71,9 @@ impl Module for CloudflareChallenge {
|
||||||
if let Some(p) = s.ext.get_mut::<Passed>() {
|
if let Some(p) = s.ext.get_mut::<Passed>() {
|
||||||
p.0.remove(&uid);
|
p.0.remove(&uid);
|
||||||
}
|
}
|
||||||
|
if let Some(c) = s.ext.get_mut::<Challenged>() {
|
||||||
|
c.0.remove(&uid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_user_register(&mut self, srv: &mut Server, uid: Uid) -> ModResult {
|
fn on_user_register(&mut self, srv: &mut Server, uid: Uid) -> ModResult {
|
||||||
|
|
@ -75,6 +83,18 @@ impl Module for CloudflareChallenge {
|
||||||
if passed(srv, uid) || port_whitelisted(srv, uid) {
|
if passed(srv, uid) || port_whitelisted(srv, uid) {
|
||||||
return ModResult::Passthru;
|
return ModResult::Passthru;
|
||||||
}
|
}
|
||||||
|
// issue the challenge exactly once; later held attempts just keep holding
|
||||||
|
if srv
|
||||||
|
.ext
|
||||||
|
.get::<Challenged>()
|
||||||
|
.is_some_and(|c| c.0.contains(&uid))
|
||||||
|
{
|
||||||
|
return ModResult::Hold;
|
||||||
|
}
|
||||||
|
srv.ext
|
||||||
|
.get_or_insert_with::<Challenged>(Challenged::default)
|
||||||
|
.0
|
||||||
|
.insert(uid);
|
||||||
let (nick, token) = (
|
let (nick, token) = (
|
||||||
srv.users
|
srv.users
|
||||||
.get(&uid)
|
.get(&uid)
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,11 @@ use crate::Uid;
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct Verified(HashSet<Uid>);
|
struct Verified(HashSet<Uid>);
|
||||||
|
|
||||||
|
/// The set of uids already handed a challenge, so a held client sending extra
|
||||||
|
/// commands doesn't get the challenge notice re-issued each time. In `Server.ext`.
|
||||||
|
#[derive(Default)]
|
||||||
|
struct Challenged(HashSet<Uid>);
|
||||||
|
|
||||||
fn enabled(s: &Server) -> bool {
|
fn enabled(s: &Server) -> bool {
|
||||||
s.conf_bool("recaptcha", false)
|
s.conf_bool("recaptcha", false)
|
||||||
&& s.conf("recaptcha_secret").is_some_and(|v| !v.is_empty())
|
&& s.conf("recaptcha_secret").is_some_and(|v| !v.is_empty())
|
||||||
|
|
@ -75,6 +80,9 @@ impl Module for ReCaptcha {
|
||||||
if let Some(v) = s.ext.get_mut::<Verified>() {
|
if let Some(v) = s.ext.get_mut::<Verified>() {
|
||||||
v.0.remove(&uid);
|
v.0.remove(&uid);
|
||||||
}
|
}
|
||||||
|
if let Some(c) = s.ext.get_mut::<Challenged>() {
|
||||||
|
c.0.remove(&uid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_user_register(&mut self, srv: &mut Server, uid: Uid) -> ModResult {
|
fn on_user_register(&mut self, srv: &mut Server, uid: Uid) -> ModResult {
|
||||||
|
|
@ -84,7 +92,19 @@ impl Module for ReCaptcha {
|
||||||
if is_verified(srv, uid) || port_whitelisted(srv, uid) {
|
if is_verified(srv, uid) || port_whitelisted(srv, uid) {
|
||||||
return ModResult::Passthru;
|
return ModResult::Passthru;
|
||||||
}
|
}
|
||||||
// hand out a challenge and refuse the link until they verify
|
// issue the challenge exactly once; later held attempts just keep holding
|
||||||
|
if srv
|
||||||
|
.ext
|
||||||
|
.get::<Challenged>()
|
||||||
|
.is_some_and(|c| c.0.contains(&uid))
|
||||||
|
{
|
||||||
|
return ModResult::Hold;
|
||||||
|
}
|
||||||
|
srv.ext
|
||||||
|
.get_or_insert_with::<Challenged>(Challenged::default)
|
||||||
|
.0
|
||||||
|
.insert(uid);
|
||||||
|
// hand out a challenge and hold the link until they verify
|
||||||
let (nick, token) = (
|
let (nick, token) = (
|
||||||
srv.users
|
srv.users
|
||||||
.get(&uid)
|
.get(&uid)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue