W5波+N-19收口:FTP鉴权落地、Trap25三连定案修复(N-30)、N-20/N-23/N-26

N-19 FTP 鉴权:
- lftpd_auth(USER/PASS 状态机 + 连续5次失败锁60s)+ SHA-256
  (user||pwd) 口令哈希;config.ini [ftp] 段 user/pwd_hash/write,
  出厂 admin/admin 在用有启动告警;lftpd_log.c 删除并入 lftpd_auth
- ftp_cfg 配置读写;台架 ftp_auth_bench.py 13/13

N-30 / Trap 25(CH395F_Trap_Records.md 四次定案全记录):
- 修复1 closed-with-data accept:客户端发完正常 FIN 后芯片按
  FUN_PARA(0x09) §5.52② 保留 Socket+RX 缓冲,旧代码把 CLOSED 一律
  relisten 自毁缓冲 → STOR 必挂 425;改为接受"已关但可读"连接排空
- 修复2 丢 CONNECT 中断探针 net_lost_connect_probe + last_peer_port
  幽灵甄别(拆链窗口握手完成但中断丢失,双信源去抖补 accept)
- 修复3 send_list/send_nlst 批量单发:背靠背 ~60B 小段毒化芯片 TX
  (芯片报 SEND_OK 但对端全丢),整份目录一次性写入
- 证伪存档:固定沉降/Socket 轮换冷却/listen 门控(台架 v7 矩阵)
- 台架工具 test/board/ch395f_reuse_bench.{c,h} + host 脚本存档
  (不注册编译;实验分支 n30-chip-bench 保留)

N-20:Error_Handler 死循环降级(记录+复位路径)
N-23:scripts/check_registration.py 双端注册反向校验(pre-commit)
N-26:GD5F NAND 直 DMA 调用方缓冲窗口断言

验证:BUILD_OK 0/0;ftp_regression 连跑 4 轮 11/11(修复前
LIST#4/#7 100% 挂、STOR#2 曾 100% 425);ftp_auth_bench 13/13;
@test 启动标记 PASS;ci_local L0+L0.5 全过;doc-links 通过。
登记簿 N-30 已销项。
This commit is contained in:
2026-10-11 18:50:24 +08:00
parent eddbedeee8
commit d1e6bb4ba7
75 changed files with 3928 additions and 352 deletions
+73
View File
@@ -0,0 +1,73 @@
/*
* 模块名称:lftpd_auth
* 模块功能:FTP 鉴权状态机(纯函数、零平台依赖,主机侧可测)——用户名匹配、
* SHA-256(user‖password) 恒定时间校验、连续失败计数与限时锁定;
* tick 由调用方注入(MCU = xTaskGetTickCount,单测 = 合成值)
* 适用平台:STM32F407ZGTx / PC 主机侧单测(双端共用)
* 作者:王建锋
* 创建日期:2026-10-11
* 修改记录:
* v1.0 2026-10-11 王建锋 创建初始版本(N-19 FTP 鉴权;lftpd.c 为唯一消费者)
*/
#ifndef LFTPD_AUTH_H
#define LFTPD_AUTH_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#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 */