github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/utils/domain/whitelist.go (about) 1 /* 2 * Copyright (C) 2021 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package domain 19 20 import ( 21 "strings" 22 ) 23 24 // NormalizeHostname casts FQDN to canonical representation: 25 // no whitespace, no trailing dot, lower case. 26 func NormalizeHostname(hostname string) string { 27 return strings.ToLower( 28 strings.TrimRight( 29 strings.TrimSpace(hostname), 30 ".", 31 ), 32 ) 33 } 34 35 // Whitelist is a set of domain names and suffixes for fast matching 36 type Whitelist struct { 37 exactList map[string]struct{} 38 suffixList map[string]struct{} 39 } 40 41 // NewWhitelist creates Whitelist from list of domains and suffixes 42 func NewWhitelist(domainList []string) *Whitelist { 43 exactList := make(map[string]struct{}) 44 suffixList := make(map[string]struct{}) 45 for _, domain := range domainList { 46 domain = strings.TrimSpace(domain) 47 normalized := NormalizeHostname(domain) 48 if strings.Index(domain, ".") == 0 { 49 // suffix pattern 50 suffixList[strings.TrimLeft(normalized, ".")] = struct{}{} 51 } else { 52 // exact domain name 53 exactList[normalized] = struct{}{} 54 } 55 } 56 return &Whitelist{ 57 exactList: exactList, 58 suffixList: suffixList, 59 } 60 } 61 62 // Match returns whether hostname is present in whitelist 63 func (l *Whitelist) Match(hostname string) bool { 64 hostname = NormalizeHostname(hostname) 65 66 // check for exact match 67 if _, found := l.exactList[hostname]; found { 68 return true 69 } 70 71 // handle special case of root suffix (".") added to whitelist 72 if _, found := l.suffixList[""]; found && hostname != "" { 73 return true 74 } 75 76 // check for suffix match 77 for needle := strings.Split(hostname, ".")[1:]; len(needle) > 0; needle = needle[1:] { 78 if _, found := l.suffixList[strings.Join(needle, ".")]; found { 79 return true 80 } 81 } 82 83 return false 84 }