diff --git a/intel/customlists/config.go b/intel/customlists/config.go index 33e285a9..99d5c2e6 100644 --- a/intel/customlists/config.go +++ b/intel/customlists/config.go @@ -11,9 +11,7 @@ var ( cfgOptionCustomListCategoryAnnotation = "Filter Lists" ) -var ( - getFilePath func() string -) +var getFilePath config.StringOption func registerConfig() error { help := `File that contains list of all domains, Ip addresses, country codes and autonomous system that you want to block, where each entry is on a new line. diff --git a/intel/customlists/lists.go b/intel/customlists/lists.go index e9cbb90a..5a18d4f3 100644 --- a/intel/customlists/lists.go +++ b/intel/customlists/lists.go @@ -2,6 +2,7 @@ package customlists import ( "bufio" + "bytes" "fmt" "net" "os" @@ -22,9 +23,9 @@ var ( ) const ( - numberOfZeroIPsUntilWarning = 100 - customFilterListStatusNotificationID = "intel/customlists_status" - customFilterListZeroIPNotificationID = "intel/customlists_zeroip" + numberOfZeroIPsUntilWarning = 100 + parseStatusNotificationID = "customlists:parse-status" + zeroIPNotificationID = "customlists:too-many-zero-ips" ) func initFilterLists() { @@ -35,7 +36,7 @@ func initFilterLists() { } func parseFile(filePath string) error { - // reset all maps, previous (if any) settings will be lost + // reset all maps, previous (if any) settings will be lost. for key := range countryCodesFilterList { delete(countryCodesFilterList, key) } @@ -49,7 +50,7 @@ func parseFile(filePath string) error { delete(domainsFilterList, key) } - // ignore empty file path + // ignore empty file path. if filePath == "" { return nil } @@ -58,46 +59,35 @@ func parseFile(filePath string) error { file, err := os.Open(filePath) if err != nil { log.Warningf("intel/customlists: failed to parse file %q ", err) - // notifications.NotifyWarn("intel/customlists parse failed", "Failed to open custom filter list") - notifications.Notify(¬ifications.Notification{ - EventID: customFilterListStatusNotificationID, - Type: notifications.Warning, - Title: "Failed to open custom filter list", - Message: err.Error(), - ShowOnSystem: false, - AvailableActions: []*notifications.Action{ - { - ID: "ack", - Text: "OK", - }, - }, - }) + module.Warning(parseStatusNotificationID, "Failed to open custom filter list", err.Error()) return err } defer file.Close() var numberOfZeroIPs uint64 - // read filter file line by line + // read filter file line by line. scanner := bufio.NewScanner(file) - // the scanner will error out if the line is greater than 64K, in this case it is enough + // the scanner will error out if the line is greater than 64K, in this case it is enough. for scanner.Scan() { parseLine(scanner.Text(), &numberOfZeroIPs) } - // check for scanner error + // check for scanner error. if err := scanner.Err(); err != nil { return err } if numberOfZeroIPs >= numberOfZeroIPsUntilWarning { log.Warning("intel/customlists: Too many zero IP addresses.") - notifications.NotifyWarn(customFilterListZeroIPNotificationID, "Too many zero IP addresses. Check your custom filter list.", "Hosts file format is not spported.") + module.Warning(zeroIPNotificationID, "Too many zero IP addresses. Check your custom filter list.", "Hosts file format is not spported.") + } else { + module.Resolve(zeroIPNotificationID) } log.Infof("intel/customlists: list loaded successful: %s", filePath) - notifications.NotifyInfo(customFilterListStatusNotificationID, + notifications.NotifyInfo(parseStatusNotificationID, "Custom filter list loaded successfully.", fmt.Sprintf(`Custom filter list loaded successfully from file %s %d domains @@ -110,48 +100,64 @@ func parseFile(filePath string) error { len(autonomousSystemsFilterList), len(domainsFilterList))) + module.Resolve(parseStatusNotificationID) + return nil } func parseLine(line string, numberOfZeroIPs *uint64) { - // ignore empty lines and comment lines - if len(line) == 0 || line[0] == '#' { + // everything after the first field will be ignored. + fields := strings.Fields(line) + + // ignore empty lines. + if len(fields) == 0 { return } - // everything after the first field will be ignored - field := strings.Fields(line)[0] + field := fields[0] - // check if it'a a country code - if isCountryCode(field) { - countryCodesFilterList[field] = struct{}{} + // ignore comments + if field[0] == '#' { + return } - // try to parse IP address + // check if it'a a country code. + if isCountryCode(field) { + countryCodesFilterList[field] = struct{}{} + return + } + + // try to parse IP address. ip := net.ParseIP(field) if ip != nil { ipAddressesFilterList[ip.String()] = struct{}{} - // check if its zero ip - for i := 0; i < len(ip); i++ { - if ip[i] != 0 { - *numberOfZeroIPs++ + // check for zero ip. + if bytes.Compare(ip.To4(), net.IPv4zero) == 0 || bytes.Compare(ip.To16(), net.IPv6zero) == 0 { + // check if its zero ip. + for i := 0; i < len(ip); i++ { + if ip[i] != 0 { + *numberOfZeroIPs++ + } } } + return } - // check if it's a Autonomous system (example AS123) + // check if it's a Autonomous system (example AS123). if isAutonomousSystem(field) { asNumber, err := strconv.ParseUint(field[2:], 10, 32) if err != nil { return } autonomousSystemsFilterList[uint(asNumber)] = struct{}{} + return } - // check if it's a domain + // check if it's a domain. domain := dns.Fqdn(field) if netutils.IsValidFqdn(domain) { domainsFilterList[domain] = struct{}{} + return } }