package core import ( "fmt" "github.com/shadow1ng/fscan/common" "github.com/shadow1ng/fscan/common/i18n" "strings" ) /* BaseScanStrategy.go - 扫描策略基础类 提供所有扫描策略的通用功能,包括插件管理、验证、 日志输出等,减少代码重复并提升维护性。 */ // PluginFilterType 插件过滤类型 type PluginFilterType int const ( FilterNone PluginFilterType = iota // 不过滤 FilterLocal // 仅本地插件 FilterService // 仅服务插件(排除本地) FilterWeb // 仅Web插件 ) // BaseScanStrategy 扫描策略基础类 type BaseScanStrategy struct { strategyName string filterType PluginFilterType } // NewBaseScanStrategy 创建基础扫描策略 func NewBaseScanStrategy(name string, filterType PluginFilterType) *BaseScanStrategy { return &BaseScanStrategy{ strategyName: name, filterType: filterType, } } // ============================================================================= // 插件管理通用方法 // ============================================================================= // GetPlugins 获取插件列表(通用实现) func (b *BaseScanStrategy) GetPlugins() ([]string, bool) { // 如果指定了特定插件且不是"all" if common.ScanMode != "" && common.ScanMode != "all" { requestedPlugins := parsePluginList(common.ScanMode) if len(requestedPlugins) == 0 { requestedPlugins = []string{common.ScanMode} } // 验证插件是否存在 var validPlugins []string for _, name := range requestedPlugins { if _, exists := common.PluginManager[name]; exists { validPlugins = append(validPlugins, name) } } return validPlugins, true } // 未指定或使用"all":获取所有插件,由IsPluginApplicable做类型过滤 return GetAllPlugins(), false } // GetApplicablePlugins 获取适用的插件列表(用于日志显示) func (b *BaseScanStrategy) GetApplicablePlugins(allPlugins []string, isCustomMode bool) []string { if isCustomMode { return allPlugins } var applicablePlugins []string for _, pluginName := range allPlugins { plugin, exists := common.PluginManager[pluginName] if !exists { continue } if b.isPluginTypeMatched(plugin) { applicablePlugins = append(applicablePlugins, pluginName) } } return applicablePlugins } // isPluginTypeMatched 检查插件类型是否匹配过滤器 func (b *BaseScanStrategy) isPluginTypeMatched(plugin common.ScanPlugin) bool { switch b.filterType { case FilterLocal: return plugin.HasType(common.PluginTypeLocal) case FilterService: return !plugin.HasType(common.PluginTypeLocal) case FilterWeb: return plugin.HasType(common.PluginTypeWeb) default: return true } } // IsPluginApplicable 判断插件是否适用(通用实现) func (b *BaseScanStrategy) IsPluginApplicable(plugin common.ScanPlugin, targetPort int, isCustomMode bool) bool { // 自定义模式下运行所有明确指定的插件 if isCustomMode { return true } // 检查插件类型过滤 if !b.isPluginTypeMatched(plugin) { return false } // 对于服务扫描,还需检查端口匹配 if b.filterType == FilterService { // 无端口限制的插件适用于所有端口 if len(plugin.Ports) == 0 { return true } // 有端口限制的插件:检查端口是否匹配 if targetPort > 0 { return plugin.HasPort(targetPort) } // 如果没有提供目标端口,则不执行有端口限制的插件 return false } return true } // ============================================================================= // 日志输出通用方法 // ============================================================================= // LogPluginInfo 输出插件信息(通用实现) func (b *BaseScanStrategy) LogPluginInfo() { allPlugins, isCustomMode := b.GetPlugins() applicablePlugins := b.GetApplicablePlugins(allPlugins, isCustomMode) // 生成日志消息 var messageKey, prefix string switch b.filterType { case FilterLocal: messageKey = "scan_plugins_local" prefix = i18n.GetText("scan_mode_local_prefix") case FilterService: messageKey = "scan_plugins_service" prefix = i18n.GetText("scan_mode_service_prefix") case FilterWeb: messageKey = "scan_plugins_web" prefix = i18n.GetText("scan_mode_web_prefix") default: messageKey = "scan_plugins_custom" prefix = "" } if len(applicablePlugins) > 0 { if isCustomMode { common.LogBase(fmt.Sprintf("%s: %s", prefix, i18n.GetText("scan_plugins_custom_specified", strings.Join(applicablePlugins, ", ")))) } else { common.LogBase(fmt.Sprintf("%s: %s", prefix, i18n.GetText(messageKey, strings.Join(applicablePlugins, ", ")))) } } else { noPluginsKey := fmt.Sprintf("scan_no_%s_plugins", b.getFilterTypeName()) common.LogBase(fmt.Sprintf("%s: %s", prefix, i18n.GetText(noPluginsKey))) } } // getFilterTypeName 获取过滤器类型名称 func (b *BaseScanStrategy) getFilterTypeName() string { switch b.filterType { case FilterLocal: return "local" case FilterService: return "service" case FilterWeb: return "web" default: return "general" } } // ============================================================================= // 验证通用方法 // ============================================================================= // ValidateConfiguration 验证扫描配置(通用实现) func (b *BaseScanStrategy) ValidateConfiguration() error { return validateScanPlugins() } // ============================================================================= // 通用辅助方法 // ============================================================================= // LogScanStart 输出扫描开始信息 func (b *BaseScanStrategy) LogScanStart() { switch b.filterType { case FilterLocal: common.LogBase(i18n.GetText("scan_local_start")) case FilterService: common.LogBase(i18n.GetText("scan_service_start")) case FilterWeb: common.LogBase(i18n.GetText("scan_web_start")) default: common.LogBase(i18n.GetText("scan_general_start")) } }