feat(meowpanel): 可选密码鉴权 (agent-196, 用户定案) — panel.auth_enabled(默认0)+panel.auth_pass(带盐sha256不明文); token会话(/dev/urandom,TTL12h,内存+卡持久化,静态屏蔽session文件); 未启用零回归,启用后 /api/* 全要会话; 前端登录页+401回跳+设置卡片; 顺带修 settings_write_one 容忍等号两侧空格(原会重复追加行)

meowpanel→f91856a4; 0 warning; 宿主curl 20例+headless Chromium 全过
This commit is contained in:
MeowOS committed 2026-08-31 05:25:28 +08:00
1 parent 5f7e7542bd
commit feb3df681c
7 files changed
+701 -35

No files matched your search

+33 -10
View File
@@ -28,9 +28,10 @@ cd /home/Aska/Project/R3ProII/patch_v2/meowpanel
- 两分支均以 `-Os -Wall -Wextra` 复核,**0 warning**。
- 产出(本次构建实测):
- `meowpanel`:mipsel 静态,`ELF 32-bit LSB executable, MIPS, MIPS32 rel2, statically linked, stripped`,
体积约 **166 KB**(固件阈值内)。md5:`11ed76ecb2e1c5773a01f0fb056a2df5`。
- `meowpanel_host`:aarch64 动态链接(宿主编译,仅供调试),体积约 **77 KB**。
- 依赖:仅 libc + Linux 内核头(`linux/input.h`),零第三方库(设备无 python3/lua)。
体积约 **183 KB**(固件阈值内)。md5:`f91856a44de0c8d12aba00cd40b44b91`。
- `meowpanel_host`:aarch64 动态链接(宿主编译,仅供调试),体积约 **142 KB**。
- 依赖:仅 libc + Linux 内核头(`linux/input.h`),零第三方库(设备无 python3/lua)。鉴权用**内联 SHA-256**(拷贝自
`meow_verify/sha256.c` 公有领域参考写法,前缀 `mp_sha256_*` 避免符号冲突;**未改 `meow_verify/` 目录**)。
- 头文件引用:`-I patch_v2/meow_launcherd`(`meow_ipc.h` 帧格式 / `m_perf_*`/`m_power_*`/`POWER_*`,
**header 为权威源**,结构体字段以它为准)。
@@ -64,7 +65,9 @@ http://<host>.local:8080/
- mDNS 由板载 `meow_mdns` 应答 `<host>.local`。
- 端口默认 **8080**,可用 `-p PORT` / 环境变量 `MEOWPORT` / 与后端同目录 `meowpanel.conf`(`port=N`)覆盖。
(优先级:`-p` > `MEOWPORT` > `meowpanel.conf` > 默认 8080。)
- 无鉴权(设备内网信任模型;token 鉴权为 MEOWPANEL_PROTOCOL §1.3 草案项,未实现)。
- 无鉴权(设备内网信任模型;**可选**密码鉴权已实现,见 §5.9)。默认关=零回归;开启后除登录/登出/状态外 `/api/*` 需会话。
- 上传/下载/管理类请求统一带 `X-MeowToken: <token>`(或 `Authorization: Bearer <token>` / `Cookie: meow_token=<token>`);
缺/错/过期 → 401 `UNAUTHORIZED`。**默认无鉴权时请勿把 8080 暴露公网**。
---
@@ -75,6 +78,9 @@ http://<host>.local:8080/
| 方法 | 路径 | 说明 | 实现 |
|---|---|---|---|
| GET | `/`、`/meowpanel.css`、`/meowpanel.js`、`/assets/<f>` | 静态托管 | ✅ |
| GET | `/api/auth/status` | 鉴权状态(enabled/会话有效) | ✅(公开) |
| POST | `/api/auth/login` | 密码登录发 token(sha256 带盐校验) | ✅(公开;错→401) |
| POST | `/api/auth/logout` | 登出失效 token | ✅(公开;幂等) |
| GET | `/api/status` | 性能+系统(`meow_svc_perf` IPC subset=all 透传) | ✅ |
| GET | `/api/perf` | 仅性能(subset=perf 透传) | ✅ |
| GET | `/api/system` | perf IPC + boot/network/ota 局部补全(network 含蓝牙,无网口;`ota` 只读检查,勿误触升级) | ✅ |
@@ -211,6 +217,22 @@ http://<host>.local:8080/
- **并发**:面板清空/删除用「写临时 + rename」重写日志;launcher 侧仍以 `O_APPEND` 追加,二者为竞写(低并发、会话级日志,
可接受),已写入「已知边界」(§7)。
### 5.9 可选鉴权(panel.auth_enabled / panel.auth_pass)
- **设置键**:`panel.auth_enabled`(bool,默认 `0`=关)+ `panel.auth_pass`(str,存 `salt:hex`)。两者写 `settings.conf`,
与实体设置页/CLI 同一存储契约(面板为独立进程,直接镜像文件)。`panel.auth_pass` 的 `GET /api/settings` 恒回
`"value":"" + "set":<bool>`,**绝不回传存量哈希/明文**。
- **门禁**:`require_auth` 在路由分发前执行——未启用直接放行(零回归);启用后除 `/api/auth/{login,logout,status}` 外全部
`/api/` 需有效会话(token 头 / `X-MeowToken` / `Cookie meow_token`),缺/错/过期 → 401 `UNAUTHORIZED`。
危险端点(reboot/shutdown/ota、key 注入)在未开启时**不额外限制**(保持内网模型),开启后亦统一纳入会话校验。
- **密码**:`PUT /api/settings/panel.auth_pass` 传明文,后端生成 16B 盐(/dev/urandom)→ `salt:hex`(sha256(salt||password))
落盘;空串=清除。校验时重算并恒定比较。**哈希/明文绝不进日志/响应**。`panel.auth_enabled` 置 1 时若未设密码 → 422 `请先设置面板密码`。
- **会话**:`POST /api/auth/login` 校验后发 token(32B → 64 hex),存内存(`AUTH_MAX_SESS`=8,满淘汰最早过期)+ 卡上
`<web_root>/meowpanel.session`(`<token> <expires_at>`,重启加载、防吊销失效),有效期 12h。`logout` 失效当前 token。
- **静态屏蔽**:`serve_static` 额外拒绝后端可执行文件与 `meowpanel.session`(403),防 token 文件被 HTTP 读取。
- **前端**:api 客户端统一带 `X-MeowToken`,收到 401 → 弹登录页(`#login` overlay);登录成功 token 存 `localStorage`;
首次进入以 `/api/auth/status` 决定是否弹登录。设置页「面板鉴权」卡片含开关(`panel.auth_enabled`)+「设置/修改密码」
按钮(`panel.auth_pass`,走 `passwordDlg` 输入)。
---
## 6. 与协议的出入(「实现为准 + 原因」,供回改 MEOWPANEL_PROTOCOL.md)
@@ -243,8 +265,9 @@ http://<host>.local:8080/
## 7. 已知边界 / 风险
- **单线程串行**:面板访问量极小,但并发请求会被排队(长上传/下载期间其它请求等待)。对面板用途可接受。
- **无鉴权**:设备内网信任模型(协议 §1.3 token 鉴权待定案)。**高危端点**(`reboot/shutdown/ota/apps/删除/上传)无鉴权,
- **无鉴权(默认)**:设备内网信任模型(协议 §1.3)。**高危端点**(`reboot/shutdown/ota/apps/删除/上传)在默认关鉴权时无鉴权,
请勿把 8080 暴露到不可信网络。`meow_svc_power` 服务端做 `SO_PEERCRED uid==0` 基础校验(root 才受理动作),后端以 root 运行可过;launcher 电源菜单/后端同链路。
**可选鉴权**(§5.9)开启后可对内网作加固(登录密码 + 会话),但密码经**局域网明文 HTTP** 传输,不提供 TLS。
- **IPC 服务未起**:`meow_svc_perf`/`meow_svc_power` 为板载 `trigger=boot` 服务,正常恒在;若异常退出,读侧返回 500 `INTERNAL`,
动作侧返回 500/503,绝不静默。请勿拔除这两服务。
- **升级保护**:`POWER_UPGRADE` 由 `meow_svc_power` 在写 mtd5 前校验卡根 `r3proii.upt`(存在/可读/非空/size>0),失败不写 mtd5;期望 md5/hash 校验留二期。
@@ -266,15 +289,15 @@ http://<host>.local:8080/
```
patch_v2/meowpanel/
├── meowpanel.c # 后端源码(单文件,约 3150 行,-Wall -Wextra 0 warning)
├── meowpanel.c # 后端源码(单文件,约 3667 行,-Wall -Wextra 0 warning;含可选鉴权/内联 SHA-256)
├── build_meowpanel.sh # 交叉编译 + host 分支(-Wall -Wextra 0 warning)
├── meowpanel # 交叉产物(mipsel 静态,约 174 KB,md5 58a7b186…)
├── meowpanel # 交叉产物(mipsel 静态,约 183 KB,md5 f91856a4…)
├── meowpanel_host # 宿主编译(本机 ld,调试用)
├── services.d/
│ └── meowpanel.conf # 部署到 TF 卡 MeowOS/services.d/meowpanel.conf
├── web/ # 前端(已存在;部署时拷到后端同目录)
│ ├── index.html
│ ├── meowpanel.css
│ └── meowpanel.js
│ ├── index.html # 含登录页 overlay + 设置密码对话框
│ ├── meowpanel.css # 含登录页样式
│ └── meowpanel.js # API 客户端带 token/401 登录、设置页鉴权卡片
└── README.md # 本文件
```