Skip to content

fix: prevent partial login failures from becoming shell prompts - #11

Merged
LeeEirc merged 2 commits into
masterfrom
fix/telnet-login-review-regressions
Nov 3, 2026
Merged

LeeEirc merged 2 commits into
masterfrom
fix/telnet-login-review-regressions

Conversation

@LeeEirc

@LeeEirc LeeEirc commented Nov 3, 2026

Copy link
Copy Markdown
Owner

背景

基于已合并 #10 的最新 master:e0353600101e9ab6e2ea833a1dcb41ce2615a7eb。

逐条复核了 Copilot 在 #10 中的三条评论,并先添加回归测试验证:三条都可复现,不是误报。本 PR 只修正登录事件优先级和提示符兼容性,不改公开 API、不增加配置字段、不修改 Koko。

对应评论:

1. 未完成的失败消息不能落入成功或凭据发送分支

问题:Invalid user>、Wrong passwords>、用户名或密码错误> 如果先到达而 CRLF 在下一次读取到达,原来的局部提示路径跳过失败判断,可能先识别成 Shell Prompt。相同内容与 CRLF 同时到达时又正确失败。

修复:新增内部 handlePartialLine,对未完成行先检查失败/改密规则。匹配叙述性诊断时保持 pending,保留原文本和登录阶段,不再进入 Shell、用户名、密码或 Continue 动作。等待 CRLF/LF、EOF 或总登录超时;如果后续扩展成正常统计 Banner,则继续登录而不是提前失败。New password: 等明确交互式改密提示仍立即返回改密错误。

这个优先级同样适用于用户自定义规则重叠的情况。解决的是客户端库误报认证成功,并不声称绕过了设备自身认证。

2. 将局部提示上限与完整逻辑行上限分开

问题:完整 CRLF/LF 行也复用了带 512 字节限制的 handlePrompt,导致 601 字节等合法自定义 Shell Prompt 被拒绝。

修复:

  • 未完成提示:最多 512 字节,维持实时扫描开销限制。
  • 完整逻辑行:最多 maxLoginBuffer(当前 64 KiB)。
  • 默认 Shell Prompt:仍保留自己的 128 字节限制。
  • 超长行仍然丢弃,不扩大缓存或重新引入滑动尾部伪提示。

3. 结构化 Unix Prompt 不被 Banner 关键词误伤

问题:先按 login、error 等词过滤,会错误拒绝 [admin@login ~]$、[admin@router /var/log/error]#。

修复:在默认 Shell 判断中先识别有明确 [user@host path] 结构并以 $/#/% 结束的 Unix 提示;用户名、主机名和目录中的关键词不再被当成 Banner 标签。[Warning]#、[ERROR]%、[Login successful]# 等普通标签仍被拒绝,明确失败/改密规则的优先级高于 Shell 识别。

保持不变

继续使用 4 KiB Peek/Discard 批量扫描;无固定 sleep;不在每个字节上运行全部正则;保持 Prompt 后数据保留、Trace 脱敏和超长子协商恢复逻辑。

回归测试

新增 login_prompt_regression_test.go,覆盖:

  • 三种失败文本在每一个拆分点下都不会产生成功。
  • CR 和 LF 分别到达时保持原文本、原阶段,且不发送数据。
  • 失败前缀后补统计信息时仍可继续登录。
  • 自定义失败/改密规则与 Shell、用户名、密码、Continue 规则重叠。
  • net.Pipe 模拟失败消息无换行后 EOF / 超时。
  • 512、513、601、4097、65536 字节完整自定义提示及超过 64 KiB 的行。
  • Unix 提示中的用户名、主机名、目录关键词与 Banner 负例。
  • 1/2/7/1024/4096 字节分块的构造函数端到端测试,检查剩余数据和发送凭据。
  • 新增 FuzzFailurePromptChunking。

验证

本地 Go 1.23.2 对新增用例及既有 login_stream_test.go 执行:

go test -race -count=20 -timeout=40s ./...
go vet ./...
go test -run '^$' -fuzz '^FuzzFailurePromptChunking$' -fuzztime=5s -parallel=2
go test -run '^$' -fuzz '^FuzzLoginDiagnosticChunking$' -fuzztime=5s -parallel=2

全部通过。新增回归在未修复的 master 登录实现上先验证失败,再验证修复后通过。完整仓库原有及新增测试、示例客户端和 monitor 由此 PR 的 Go 1.20.x / stable CI 验证。

尚未进行真实网络设备回归;保留文档中无换行文本提示存在固有歧义的说明。

Copilot AI balanced review requested due to automatic review settings November 3, 2026 12:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new UTF-8 check discards failure diagnostics containing invalid bytes before classification, allowing failed logins to be reported as successful.

1 open issue
What changed in this PR

This PR refines Telnet login handling after #10, preventing incomplete failure messages from triggering prompt actions while improving prompt compatibility without changing the public API.

Changes:

  • Gives incomplete failure and password-change diagnostics precedence over interactive prompts.
  • Separates partial-prompt and completed-line limits, and recognizes structured Unix prompts before banner filtering.
  • Adds regression tests, chunking fuzz coverage, and documentation for these behaviors.
File Description
login.go Updates diagnostic precedence, prompt length limits, and structured Unix prompt recognition.
login_prompt_regression_test.go Adds regression and fuzz coverage for diagnostics, chunk boundaries, prompt limits, and retained session data.
docs/​login-stream.md Documents precedence rules, prompt limits, Unix prompt handling, and added coverage.

Review effort: Balanced

Comment thread login.go Outdated
Comment on lines 188 to 193
if len(line) > m.config.maxLoginBuffer || !utf8.Valid(line) {
return loginPending, nil
}
if result := m.messageResult(line, trace); result != loginPending {
return result, nil
}
Recognize complete failure and password-change messages before validating
UTF-8 so legacy-encoded usernames cannot hide errors behind a later shell
prompt. Keep validation for interactive actions and incomplete prompts.

Add encoding, split-point, EOF, custom-pattern and fuzz regression tests.
Addresses review comment 4454941793 on PR #11.
@LeeEirc
LeeEirc merged commit 2b28da6 into master Nov 3, 2026
4 checks passed
@LeeEirc
LeeEirc deleted the fix/telnet-login-review-regressions branch November 3, 2026 13:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants