/* * 模块名称:lftpd_auth * 模块功能:FTP 鉴权状态机(纯函数、零平台依赖,主机侧可测)——用户名匹配、 * SHA-256(user‖password) 恒定时间校验、连续失败计数与限时锁定; * tick 由调用方注入(MCU = xTaskGetTickCount,单测 = 合成值) * 适用平台:STM32F407ZGTx / PC 主机侧单测(双端共用) * 作者:王建锋 * 创建日期:2026-10-11 * 修改记录: * v1.0 2026-10-11 王建锋 创建初始版本(FTP 鉴权;lftpd.c 为唯一消费者) */ #ifndef LFTPD_AUTH_H #define LFTPD_AUTH_H #ifdef __cplusplus extern "C" { #endif #include #define FTP_AUTH_FAIL_MAX 5u /* 连续失败 N 次后锁定 */ #define FTP_AUTH_LOCK_TICKS 60000u /* 锁定时长(tick = 1 ms → 60 s) */ /* 一次校验所需的配置快照(由消费者从 ftp_cfg_t 组装,本模块不认配置引擎) */ typedef struct { const char *p_user; /* 期望用户名 */ const char *p_pwd_hash; /* 64 字符 hex 摘要 */ uint8_t write_en; /* 透传位:写命令门由 lftpd 侧执行,本模块不判 */ } ftp_auth_creds_t; /* 鉴权状态(跨会话持久;单连接服务器,全局一份即可) */ typedef struct { uint8_t fail_count; /* 连续失败计数(成功即清零) */ uint32_t lock_until_tick; /* 锁定截止 tick(fail_count ≥ FAIL_MAX 时有效) */ } ftp_auth_state_t; typedef enum { FTP_AUTH_OK = 0, /* 口令正确 */ FTP_AUTH_FAIL, /* 口令/用户名错误(已计入失败计数) */ FTP_AUTH_LOCKED /* 锁定中(本次不校验、不计数) */ } ftp_auth_result_t; /* * 函数功能:用户名匹配(大小写不敏感,与配置引擎键名口径一致) * 入口参数:p_expect - 期望用户名 p_user - 来客输入 * 返回值:1 - 匹配;0 - 不匹配或任一为 NULL int * 限定条件:无 */ int ftp_auth_user_match(const char *p_expect, const char *p_user); /* * 函数功能:口令校验 + 失败计数 + 限时锁定(一次 PASS 的完整判定) * 入口参数:p_creds - 配置快照 user_ok - USER 阶段的用户名匹配结果 * p_pass - 来客口令(NULL 按空串) p_state - 鉴权状态 * now_tick - 当前 tick(ms) * 返回值:ftp_auth_result_t * 限定条件:p_creds/p_state 非空(NULL 一律 FAIL,fail-closed) * 函数说明:1. 锁定中直接 LOCKED(不算哈希——锁定状态非机密,无侧信道); * tick 差用 (int32_t) 有符号比较,天然抗 32 位回绕 * 2. 无论用户名对错都走同一条哈希路径(盐 = 期望用户名), * 耗时一致 → 不泄露"用户是否存在" * 3. 成功清零计数;失败累计到 FTP_AUTH_FAIL_MAX 上锁 */ ftp_auth_result_t ftp_auth_check(const ftp_auth_creds_t *p_creds, uint8_t user_ok, const char *p_pass, ftp_auth_state_t *p_state, uint32_t now_tick); #ifdef __cplusplus } #endif #endif /* LFTPD_AUTH_H */