mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 05:56:46 +08:00

- 创建通用SMB框架,包含抽象接口、凭据管理和并发扫描引擎 - SMB2插件代码量从492行减少到159行,减少68%代码量 - 统一错误分类和处理机制,提高代码可维护性 - 支持密码和哈希两种认证方式,保持向后兼容性 - 模块化设计便于单元测试和功能扩展
102 lines
3.2 KiB
Go
102 lines
3.2 KiB
Go
package common
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
)
|
|
|
|
// 定义常见的SMB错误类型
|
|
var (
|
|
ErrAuthFailed = errors.New("认证失败")
|
|
ErrAccountLocked = errors.New("账户锁定")
|
|
ErrAccessDenied = errors.New("拒绝访问")
|
|
ErrAccountDisabled = errors.New("账户禁用")
|
|
ErrPasswordExpired = errors.New("密码过期")
|
|
ErrConnectionFailed = errors.New("连接失败")
|
|
ErrTimeout = errors.New("连接超时")
|
|
ErrSessionDeleted = errors.New("会话断开")
|
|
)
|
|
|
|
// ClassifySmbError 对SMB错误进行分类和标准化
|
|
func ClassifySmbError(err error) error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
|
|
// 清理错误信息中的换行符和多余空格
|
|
errMsg := strings.TrimSpace(strings.ReplaceAll(err.Error(), "\n", " "))
|
|
errMsgLower := strings.ToLower(errMsg)
|
|
|
|
// SMB1特定错误处理
|
|
if strings.Contains(errMsg, "NT Status Error") {
|
|
switch {
|
|
case strings.Contains(errMsg, "STATUS_LOGON_FAILURE"):
|
|
return ErrAuthFailed
|
|
case strings.Contains(errMsg, "STATUS_ACCOUNT_LOCKED_OUT"):
|
|
return ErrAccountLocked
|
|
case strings.Contains(errMsg, "STATUS_ACCESS_DENIED"):
|
|
return ErrAccessDenied
|
|
case strings.Contains(errMsg, "STATUS_ACCOUNT_DISABLED"):
|
|
return ErrAccountDisabled
|
|
case strings.Contains(errMsg, "STATUS_PASSWORD_EXPIRED"):
|
|
return ErrPasswordExpired
|
|
case strings.Contains(errMsg, "STATUS_USER_SESSION_DELETED"):
|
|
return ErrSessionDeleted
|
|
default:
|
|
return ErrAuthFailed
|
|
}
|
|
}
|
|
|
|
// SMB2特定错误处理
|
|
switch {
|
|
case strings.Contains(errMsgLower, "account has been automatically locked") ||
|
|
strings.Contains(errMsgLower, "account has been locked") ||
|
|
strings.Contains(errMsgLower, "user account has been automatically locked"):
|
|
return ErrAccountLocked
|
|
|
|
case strings.Contains(errMsgLower, "access denied") ||
|
|
strings.Contains(errMsgLower, "access is denied"):
|
|
return ErrAccessDenied
|
|
|
|
case strings.Contains(errMsgLower, "account disabled") ||
|
|
strings.Contains(errMsgLower, "account is disabled"):
|
|
return ErrAccountDisabled
|
|
|
|
case strings.Contains(errMsgLower, "password expired") ||
|
|
strings.Contains(errMsgLower, "password has expired"):
|
|
return ErrPasswordExpired
|
|
|
|
case strings.Contains(errMsgLower, "connection refused") ||
|
|
strings.Contains(errMsgLower, "connection failed") ||
|
|
strings.Contains(errMsgLower, "no connection could be made"):
|
|
return ErrConnectionFailed
|
|
|
|
case strings.Contains(errMsgLower, "timeout") ||
|
|
strings.Contains(errMsgLower, "timed out"):
|
|
return ErrTimeout
|
|
|
|
case strings.Contains(errMsgLower, "session") && strings.Contains(errMsgLower, "deleted"):
|
|
return ErrSessionDeleted
|
|
|
|
case strings.Contains(errMsgLower, "logon failure") ||
|
|
strings.Contains(errMsgLower, "authentication failed") ||
|
|
strings.Contains(errMsgLower, "login failed"):
|
|
return ErrAuthFailed
|
|
}
|
|
|
|
// 默认返回原始错误
|
|
return err
|
|
}
|
|
|
|
// IsAccountLockError 判断是否为账户锁定错误
|
|
func IsAccountLockError(err error) bool {
|
|
return errors.Is(err, ErrAccountLocked) ||
|
|
strings.Contains(strings.ToLower(err.Error()), "locked")
|
|
}
|
|
|
|
// IsFatalError 判断是否为致命错误(应该停止尝试该用户)
|
|
func IsFatalError(err error) bool {
|
|
return errors.Is(err, ErrAccountLocked) ||
|
|
errors.Is(err, ErrAccountDisabled) ||
|
|
errors.Is(err, ErrPasswordExpired)
|
|
} |