aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/login.rs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-08 15:39:06 +0000
committertv <tv@krebsco.de>2026-11-08 16:47:25 +0100
commit05943dad70ce17ff61b8c0352abeec0964ca14f0 (patch)
tree3ef8953eaa44493d393c786090d09acb34c8e3c9 /src/api/login.rs
parent0f55d5741b3dfda617670f92a77c3cd6e462be6d (diff)
login: logins by key capped per user
Review 6: a node remembers the challenges used until they expire, 10 000 at most, and refused every login by key once full. One user holding a key could make 10 000 logins within five minutes and keep everyone else out. A user may now log in by key at most --key-logins-per-user times (100) on a node within a challenge's lifetime, past which that user waits and others don't; the 10 000 stay as the cap for all users together. The lifetime, five minutes until now, is --challenge-lifetime.
Diffstat (limited to 'src/api/login.rs')
-rw-r--r--src/api/login.rs3
1 files changed, 2 insertions, 1 deletions
diff --git a/src/api/login.rs b/src/api/login.rs
index 4b42178..e3f8d02 100644
--- a/src/api/login.rs
+++ b/src/api/login.rs
@@ -283,7 +283,7 @@ pub(crate) async fn challenge(State(state): State<AppState>) -> Result<Response,
.node_key
.as_ref()
.ok_or(ApiError(StatusCode::SERVICE_UNAVAILABLE, None))?;
- let (challenge, exp) = challenge::issue(key, now);
+ let (challenge, exp) = challenge::issue(key, now, state.challenge_lifetime.as_millis() as u64);
Ok(Json(json!({
"challenge": challenge,
"namespace": challenge::NAMESPACE,
@@ -340,6 +340,7 @@ pub(crate) async fn login_key(
&request.user,
now,
&mut used,
+ state.key_logins_per_user,
)
.map_err(|why| {
debug!(user = %request.user, reason = %why, "Refused a login by key");