234 lines
9.5 KiB
Markdown
234 lines
9.5 KiB
Markdown
# V2 文件/文本传输功能清单
|
||
|
||
## 一、文件传输
|
||
|
||
| 方向 | 触发方式 | 断点续传 | 进度显示 | 备注 |
|
||
|------|----------|:--------:|:--------:|------|
|
||
| 服务端 → 客户端 | 文件管理器拖放/Ctrl+V | ✅ | ✅ | 支持大文件(>4GB) |
|
||
| 客户端 → 服务端 | 文件管理器下载 | ✅ | ✅ | 支持大文件(>4GB) |
|
||
| 客户端A → 客户端B (C2C) | 远程桌面 Ctrl+C/Ctrl+V | ✅ | ✅ | 自动捕获目标目录 |
|
||
|
||
## 二、文本传输
|
||
|
||
| 方向 | 触发方式 | 说明 |
|
||
|------|----------|------|
|
||
| 服务端 → 客户端 | 远程桌面剪贴板同步 | `COMMAND_SCREEN_SET_CLIPBOARD` |
|
||
| 客户端 → 服务端 | 远程桌面剪贴板同步 | `COMMAND_SCREEN_GET_CLIPBOARD` |
|
||
| 客户端A → 客户端B (C2C) | 远程桌面 Ctrl+C/Ctrl+V | 自动粘贴 |
|
||
|
||
## 三、C2C 传输流程
|
||
|
||
```
|
||
┌─────────────┐ Ctrl+V ┌─────────────┐ CLIPBOARD_V2 ┌─────────────┐
|
||
│ 远程桌面B │ ───────────────>│ 服务端 │ ──────────────────>│ 远程桌面A │
|
||
│ (目标) │ │ │ │ (源) │
|
||
└─────────────┘ └─────────────┘ └─────────────┘
|
||
▲ │ │
|
||
│ │ C2C_PREPARE │
|
||
│<──────────────────────────────┘ │
|
||
│ │
|
||
│ ┌─────────────┐ │
|
||
│ SEND_FILE_V2/C2C_TEXT │ 服务端 │ SEND_FILE_V2/C2C_TEXT │
|
||
│<────────────────────────│ (转发) │<──────────────────────────┘
|
||
│ └─────────────┘
|
||
```
|
||
|
||
## 四、协议命令
|
||
|
||
| 命令 | 值 | 用途 |
|
||
|------|:--:|------|
|
||
| `COMMAND_SEND_FILE_V2` | 85 | V2文件数据包 |
|
||
| `COMMAND_FILE_RESUME` | 86 | 断点续传响应 |
|
||
| `COMMAND_CLIPBOARD_V2` | 87 | C2C剪贴板请求 |
|
||
| `COMMAND_FILE_QUERY_RESUME` | 88 | 断点续传查询 |
|
||
| `COMMAND_C2C_PREPARE` | 89 | C2C准备接收通知 |
|
||
| `COMMAND_C2C_TEXT` | 90 | C2C文本传输 |
|
||
| `COMMAND_FILE_COMPLETE_V2` | 91 | V2文件完成校验包 |
|
||
| `COMMAND_C2C_PREPARE_RESP` | 92 | C2C准备响应(返回目标目录) |
|
||
|
||
## 五、核心特性
|
||
|
||
- **断点续传**: 基于 transferID + 文件特征匹配,支持传输中断后恢复
|
||
- **大文件支持**: 使用 uint64_t 存储文件大小和偏移,突破4GB限制
|
||
- **自动目标目录**: C2C传输自动捕获目标客户端当前焦点窗口的目录
|
||
- **自动粘贴**: C2C文本传输完成后自动模拟 Ctrl+V 完成粘贴
|
||
- **版本协商**: 能力位 `CLIENT_CAP_V2` + 版本日期双重检测
|
||
- **文件完整性校验**: 传输完成后发送 SHA-256 校验包,接收端自动验证
|
||
- **服务端开关**: 参数菜单可控制是否启用 V2(默认关闭)
|
||
- **自动清理**: 状态文件超过 7 天自动删除
|
||
|
||
## 5.1 文件完整性校验
|
||
|
||
每个文件传输完成后,发送端计算并发送 `COMMAND_FILE_COMPLETE_V2` 校验包:
|
||
|
||
```cpp
|
||
struct FileCompletePacketV2 {
|
||
uint8_t cmd; // = 91
|
||
uint64_t transferID;
|
||
uint64_t srcClientID;
|
||
uint64_t dstClientID;
|
||
uint32_t fileIndex;
|
||
uint64_t fileSize;
|
||
uint8_t sha256[32]; // SHA-256 哈希
|
||
}; // 69 bytes
|
||
```
|
||
|
||
**工作流程**:
|
||
1. 发送端在发送文件数据同时计算 SHA-256
|
||
2. 文件最后一个块发送完成后,发送 `FILE_COMPLETE_V2` 校验包
|
||
3. 接收端在接收数据时同步计算 SHA-256(流式计算,无需重读文件)
|
||
4. 收到校验包后对比哈希值,输出校验结果
|
||
|
||
**支持的传输方向**:
|
||
| 方向 | 校验位置 |
|
||
|------|----------|
|
||
| 客户端 → 服务端 | 服务端校验 |
|
||
| 服务端 → 客户端 | 客户端校验 |
|
||
| 客户端A → 客户端B (C2C) | 服务端转发,客户端B校验 |
|
||
|
||
**校验失败处理**:
|
||
- 校验失败时自动删除损坏文件
|
||
- 日志输出期望和实际的 SHA-256 哈希值
|
||
|
||
**断点续传与校验**:
|
||
- 断点续传时无法使用流式 SHA-256(缺少历史数据)
|
||
- 自动切换为从文件重新计算完整 SHA-256
|
||
|
||
## 六、相关文件
|
||
|
||
| 文件 | 说明 |
|
||
|------|------|
|
||
| `common/commands.h` | 协议命令定义 |
|
||
| `common/file_upload.h/cpp` | V2传输核心实现 |
|
||
| `client/KernelManager.cpp` | 客户端主连接处理 |
|
||
| `client/ScreenManager.cpp` | 客户端远程桌面会话处理 |
|
||
| `server/2015Remote/2015RemoteDlg.cpp` | 服务端主逻辑 |
|
||
| `server/2015Remote/ScreenSpyDlg.cpp` | 服务端远程桌面会话处理 |
|
||
| `server/2015Remote/CDlgFileSend.cpp` | 文件传输进度对话框 |
|
||
|
||
## 七、使用说明
|
||
|
||
### C2C 文件传输
|
||
1. 打开两个远程桌面窗口(源A和目标B)
|
||
2. 在源A上选中文件,按 Ctrl+C
|
||
3. 按 X 切换到目标B
|
||
4. 按 Ctrl+V,文件自动传输到B当前目录
|
||
|
||
### C2C 文本传输
|
||
1. 在源A上复制文本(Ctrl+C)
|
||
2. 按 X 切换到目标B
|
||
3. 在目标B的应用中按 Ctrl+V,文本自动粘贴
|
||
|
||
### 断点续传
|
||
- 传输中断后,重新执行相同操作
|
||
- 系统自动检测已传输部分,从断点继续
|
||
- 状态文件保存在 `%TEMP%\FileTransfer\`
|
||
- 状态文件超过 7 天自动删除
|
||
|
||
### 状态文件说明
|
||
|
||
| 后缀 | 用途 | 说明 |
|
||
|------|------|------|
|
||
| `.resume` | 断点续传状态 | 记录 transferID、文件列表、已接收字节数 |
|
||
| `.recv` | C2C 接收方目录 | 记录目标客户端当前焦点窗口目录 |
|
||
| `.send` | C2C 发送方目录 | 记录源客户端剪贴板文件路径 |
|
||
|
||
所有状态文件统一存放在 `%TEMP%\FileTransfer\` 目录,文件名格式为 `{transferID}.{后缀}`。
|
||
|
||
---
|
||
|
||
## 八、代码审查报告
|
||
|
||
### 8.1 审查范围
|
||
|
||
| 文件 | 改动行数 | 审查结果 |
|
||
|------|:--------:|:--------:|
|
||
| `common/commands.h` | +16 | ✅ |
|
||
| `common/file_upload.h` | +288 | ✅ |
|
||
| `SimplePlugins/file_upload.cpp` | 核心实现 | ✅ |
|
||
| `client/KernelManager.cpp` | +294 | ✅ |
|
||
| `client/ScreenManager.cpp` | +360 | ✅ |
|
||
| `server/2015Remote/2015RemoteDlg.cpp` | +698 | ✅ |
|
||
| `server/2015Remote/CDlgFileSend.cpp` | +116 | ✅ |
|
||
| `server/2015Remote/context.h` | +34 | ✅ |
|
||
|
||
### 8.2 代码质量评估
|
||
|
||
#### 优点
|
||
|
||
1. **协议设计清晰** - 结构体使用 `#pragma pack(push, 1)` 确保跨平台对齐,注释详尽
|
||
2. **版本兼容性** - V1/V2 协议共存,旧客户端仍可使用
|
||
3. **能力协商机制完善** - `CLIENT_CAP_V2` 能力位 + 版本日期双重检测
|
||
4. **断点续传设计** - `transferID + fileIndex` 组合键唯一标识,状态持久化
|
||
5. **线程安全** - 使用 `std::mutex` 保护共享状态(`g_fileStatesV2Mtx` 等)
|
||
6. **智能指针** - `std::unique_ptr` 管理内存,RAII 处理文件句柄
|
||
7. **SHA-256 校验** - 使用 Windows bcrypt API,流式计算
|
||
|
||
#### 待改进项
|
||
|
||
| 优先级 | 问题 | 位置 | 建议 |
|
||
|:------:|------|------|------|
|
||
| 🟠 中 | 路径穿越未验证 | `file_upload.cpp:712` | `GetRelativePath` 添加 `..` 检查 |
|
||
| 🟠 中 | 变量命名误导 | `file_upload.cpp:2463` | `utf8Name` 实际是 ANSI,应改名 |
|
||
| 🟡 低 | 重复代码 | `KernelManager.cpp` / `ScreenManager.cpp` | C2C_TEXT 处理逻辑可提取公共函数 |
|
||
|
||
### 8.3 安全审查
|
||
|
||
| 检查项 | 状态 | 说明 |
|
||
|--------|:----:|------|
|
||
| 缓冲区溢出 | ✅ | 有长度校验 `if (len < sizeof(...) + nameLength + dataLength)` |
|
||
| 认证校验 | ✅ | 使用 hash + hmac 验证 |
|
||
| 路径穿越 | ⚠️ | `GetRelativePath` 未检查 `..` 序列(实际风险低) |
|
||
| 客户端ID伪造 | ✅ | 通过 `FindHost` 验证客户端存在 |
|
||
| 文件句柄泄漏 | ✅ | RAII 析构函数处理 |
|
||
| 整数溢出 | ✅ | 使用 `uint64_t` 支持大文件 |
|
||
|
||
**路径穿越风险分析**:
|
||
- `GetRelativePath` 未过滤 `..` 序列
|
||
- 实际风险较低:C2C 由服务端键盘钩子触发,非任意用户输入
|
||
- 建议后续版本加固
|
||
|
||
### 8.4 边界条件测试建议
|
||
|
||
| 场景 | 测试点 |
|
||
|------|--------|
|
||
| 大文件 | >4GB 文件传输和断点续传 |
|
||
| 网络抖动 | 传输中断后恢复 |
|
||
| 并发传输 | 多个 C2C 同时进行 |
|
||
| 客户端重启 | `.resume` 文件恢复 + SHA-256 重算 |
|
||
| 目录结构 | 深层嵌套目录创建 |
|
||
| 空文件 | 0 字节文件传输和校验 |
|
||
|
||
---
|
||
|
||
## 九、提交评估
|
||
|
||
### 9.1 总体评估:✅ 可发布
|
||
|
||
| 指标 | 状态 | 说明 |
|
||
|------|:----:|------|
|
||
| 功能完整性 | ✅ | C2C/断点续传/SHA-256 校验均已实现 |
|
||
| 编译通过 | ✅ | 无编译错误 |
|
||
| 向后兼容 | ✅ | V1 协议仍可用,能力协商正确 |
|
||
| 崩溃风险 | ✅ | 无明显崩溃点 |
|
||
| 数据安全 | ✅ | HMAC 认证、长度校验完善 |
|
||
|
||
### 9.2 问题分类
|
||
|
||
| 严重程度 | 数量 | 是否阻塞提交 |
|
||
|:--------:|:----:|:------------:|
|
||
| 🔴 致命 | 0 | - |
|
||
| 🟠 中等 | 2 | 否 |
|
||
| 🟡 低危 | 1 | 否 |
|
||
|
||
### 9.3 后续改进建议
|
||
|
||
1. **路径安全加固** - 在 `GetRelativePath` 添加 `..` 过滤
|
||
2. **重复代码重构** - 提取 C2C_TEXT 处理为公共函数
|
||
3. **变量命名修正** - `utf8Name` → `ansiName`
|
||
4. **日志级别控制** - 添加 verbose 模式开关
|
||
|
||
---
|
||
|
||
*审查日期: 2026-02-27*
|