/* SPDX-License-Identifier: GPL-3.0-only */ #pragma once #include #include #define SSH_AUTH_POLICY_HANDSHAKE_CAPACITY 6U #define SSH_AUTH_POLICY_HANDSHAKE_REFILL_US INT64_C(10000000) #define SSH_AUTH_POLICY_VERIFICATION_CAPACITY 6U #define SSH_AUTH_POLICY_VERIFICATION_REFILL_US INT64_C(10000000) #define SSH_AUTH_POLICY_PROBE_CAPACITY 12U #define SSH_AUTH_POLICY_PROBE_REFILL_US INT64_C(5000000) typedef enum { SSH_AUTH_POLICY_HANDSHAKE, SSH_AUTH_POLICY_VERIFICATION, SSH_AUTH_POLICY_PROBE, SSH_AUTH_POLICY_KIND_COUNT } ssh_auth_policy_kind_t; typedef struct { int64_t refill_us; int64_t last_seen_us; uint8_t tokens; bool initialized; } ssh_auth_policy_bucket_t; typedef struct { ssh_auth_policy_bucket_t buckets[SSH_AUTH_POLICY_KIND_COUNT]; } ssh_auth_policy_t; /* Single-owner only: no allocation, locks, clock reads, timers or sleeps. * Start zero-initialized; each class lazily starts at capacity. The owner must * retain one shared instance across sessions, stop/start and counter clears; * only reboot resets it. Do not modify fields directly or refund admissions. * Each true result consumes one token, regardless of subsequent auth outcome. * Refill adds one token per class-specific interval, preserving partial credit * below capacity and discarding all surplus (including fractions) at capacity. * now_us must be nonnegative and nondecreasing across ALL classes (equal is OK). * NULL, invalid kind, negative time and regression reject without mutation. * An empty-bucket denial records time but never postpones the refill deadline. */ bool ssh_auth_policy_admit(ssh_auth_policy_t *policy, ssh_auth_policy_kind_t kind, int64_t now_us);