diff options
| author | tv <tv@krebsco.de> | 2026-11-08 14:15:26 +0000 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-08 15:32:02 +0100 |
| commit | fac4b143587188d283578bc51e13ca44bcfc6382 (patch) | |
| tree | 9ddaef363ca7e936c26744e218b12302b41709e5 /src/access/token.rs | |
| parent | 075ee0be09be7ebce846043e5230ffb67a7f9a5c (diff) | |
token: a banned node's tokens aren't taken
Review finding 11: token::verify checked only that the issuer is a
member, and a ban leaves the member entry. A compromised node's tokens
stayed valid after it was banned, until it was forgotten too.
A token issued by a banned node is now refused (BannedIssuer), as soon
as the ban reaches the node judging it.
Diffstat (limited to 'src/access/token.rs')
| -rw-r--r-- | src/access/token.rs | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/src/access/token.rs b/src/access/token.rs index 3af8672..d33a3fe 100644 --- a/src/access/token.rs +++ b/src/access/token.rs @@ -75,6 +75,8 @@ pub(crate) enum Refused { OtherSwarm, #[error("issued by a node that isn't a member here (not yet, or no longer)")] UnknownIssuer, + #[error("issued by a node the swarm banned")] + BannedIssuer, #[error("its signature doesn't hold")] BadSignature, #[error("expired")] @@ -90,7 +92,7 @@ pub(crate) enum Refused { } /// The claims of `token` if this node takes it: well formed, for `swarm`, signed by a -/// node that is a member in `doc`, not expired at `now` (Unix ms), nor issued later +/// node that is a member in `doc` and not banned, not expired at `now` (Unix ms), nor issued later /// than a clock off by `SKEW_MS` would; and in a swarm with a registry, for a /// registered user that is enabled, issued after its tokens were last revoked /// (`registry::User::tokens_not_before`). @@ -126,6 +128,9 @@ pub(crate) fn verify( if !member { return Err(Refused::UnknownIssuer); } + if super::bans::banned(doc, &claims.issuer) { + return Err(Refused::BannedIssuer); + } let mut signed = LABEL.to_vec(); signed.extend_from_slice(&payload); if !identity::verify(&key, &signed, &signature) { @@ -236,6 +241,17 @@ mod tests { verify(&doc, &forged, "s", 1_500), Err(Refused::BadSignature) ); + // By a member banned since. + let token = issue(&key, &claims(&key)); + let ban = crate::access::bans::path(&key.id()); + let mut banned = doc.fork(); + change(&mut banned, |tx| { + store::write_path(tx, &ban, &json!({"reason": "lost"})).unwrap() + }); + assert_eq!( + verify(&banned, &token, "s", 1_500), + Err(Refused::BannedIssuer) + ); // Changed claims, the signature kept. let token = issue(&key, &claims(&key)); let (_, signature) = token.rsplit_once('.').unwrap(); |
