fscan/plugins/legacy/smb/common/credentials.go
ZacharyZcR daa7fb2dcb refactor: 重构SMB和SMB2插件架构,大幅减少代码重复
- 创建通用SMB框架,包含抽象接口、凭据管理和并发扫描引擎
- SMB2插件代码量从492行减少到159行,减少68%代码量
- 统一错误分类和处理机制,提高代码可维护性
- 支持密码和哈希两种认证方式,保持向后兼容性
- 模块化设计便于单元测试和功能扩展
2025-08-12 19:11:40 +08:00

106 lines
2.6 KiB
Go

package common
import (
"strings"
"sync"
"github.com/shadow1ng/fscan/common"
)
// DefaultCredentialManager 默认凭据管理器实现
type DefaultCredentialManager struct {
credentials []Credential
lockedUsers map[string]bool
mutex sync.RWMutex
}
// NewPasswordCredentialManager 创建密码认证凭据管理器
func NewPasswordCredentialManager() *DefaultCredentialManager {
mgr := &DefaultCredentialManager{
lockedUsers: make(map[string]bool),
}
mgr.generatePasswordCredentials()
return mgr
}
// NewHashCredentialManager 创建哈希认证凭据管理器
func NewHashCredentialManager() *DefaultCredentialManager {
mgr := &DefaultCredentialManager{
lockedUsers: make(map[string]bool),
}
mgr.generateHashCredentials()
return mgr
}
// generatePasswordCredentials 生成密码凭据列表
func (m *DefaultCredentialManager) generatePasswordCredentials() {
for _, user := range common.Userdict["smb"] {
for _, pass := range common.Passwords {
actualPass := strings.ReplaceAll(pass, "{user}", user)
m.credentials = append(m.credentials, Credential{
Username: user,
Password: actualPass,
Hash: []byte{},
IsHash: false,
})
}
}
}
// generateHashCredentials 生成哈希凭据列表
func (m *DefaultCredentialManager) generateHashCredentials() {
for _, user := range common.Userdict["smb"] {
for _, hash := range common.HashBytes {
m.credentials = append(m.credentials, Credential{
Username: user,
Password: "",
Hash: hash,
IsHash: true,
})
}
}
}
// GenerateCredentials 获取所有凭据
func (m *DefaultCredentialManager) GenerateCredentials() []Credential {
m.mutex.RLock()
defer m.mutex.RUnlock()
result := make([]Credential, len(m.credentials))
copy(result, m.credentials)
return result
}
// HandleAuthFailure 处理认证失败
func (m *DefaultCredentialManager) HandleAuthFailure(username string, err error) {
if err == nil {
return
}
errMsg := strings.ToLower(err.Error())
isLocked := strings.Contains(errMsg, "locked") ||
strings.Contains(errMsg, "account has been automatically locked") ||
strings.Contains(errMsg, "user account has been automatically locked")
if isLocked {
m.mutex.Lock()
m.lockedUsers[username] = true
m.mutex.Unlock()
common.LogError("用户 " + username + " 已被锁定")
}
}
// IsUserLocked 检查用户是否被锁定
func (m *DefaultCredentialManager) IsUserLocked(username string) bool {
m.mutex.RLock()
defer m.mutex.RUnlock()
return m.lockedUsers[username]
}
// GetCredentialCount 获取凭据总数
func (m *DefaultCredentialManager) GetCredentialCount() int {
m.mutex.RLock()
defer m.mutex.RUnlock()
return len(m.credentials)
}