Validate resolver config for unknown parameters

This commit is contained in:
Daniel 2022-03-16 11:29:16 +01:00
parent 52506ffb1e
commit 75b3c40ffc

View file

@ -27,6 +27,14 @@ type Scope struct {
Resolvers []*Resolver Resolvers []*Resolver
} }
const (
parameterName = "name"
parameterVerify = "verify"
parameterBlockedIf = "blockedif"
parameterSearch = "search"
parameterSearchOnly = "search-only"
)
var ( var (
globalResolvers []*Resolver // all (global) resolvers globalResolvers []*Resolver // all (global) resolvers
localResolvers []*Resolver // all resolvers that are in site-local or link-local IP ranges localResolvers []*Resolver // all resolvers that are in site-local or link-local IP ranges
@ -122,31 +130,47 @@ func createResolver(resolverURL, source string) (*Resolver, bool, error) {
return nil, true, nil // skip return nil, true, nil // skip
} }
// Get parameters and check if keys exist.
query := u.Query() query := u.Query()
verifyDomain := query.Get("verify") for key := range query {
switch key {
case parameterName,
parameterVerify,
parameterBlockedIf,
parameterSearch,
parameterSearchOnly:
// Known key, continue.
default:
// Unknown key, abort.
return nil, false, fmt.Errorf(`unknown parameter "%s"`, key)
}
}
// Check domain verification config.
verifyDomain := query.Get(parameterVerify)
if verifyDomain != "" && u.Scheme != ServerTypeDoT { if verifyDomain != "" && u.Scheme != ServerTypeDoT {
return nil, false, fmt.Errorf("domain verification only supported in DOT") return nil, false, fmt.Errorf("domain verification only supported in DOT")
} }
if verifyDomain == "" && u.Scheme == ServerTypeDoT { if verifyDomain == "" && u.Scheme == ServerTypeDoT {
return nil, false, fmt.Errorf("DOT must have a verify query parameter set") return nil, false, fmt.Errorf("DOT must have a verify query parameter set")
} }
blockType := query.Get("blockedif") // Check block detection type.
blockType := query.Get(parameterBlockedIf)
if blockType == "" { if blockType == "" {
blockType = BlockDetectionZeroIP blockType = BlockDetectionZeroIP
} }
switch blockType { switch blockType {
case BlockDetectionDisabled, BlockDetectionEmptyAnswer, BlockDetectionRefused, BlockDetectionZeroIP: case BlockDetectionDisabled, BlockDetectionEmptyAnswer, BlockDetectionRefused, BlockDetectionZeroIP:
default: default:
return nil, false, fmt.Errorf("invalid value for upstream block detection (blockedif=)") return nil, false, fmt.Errorf("invalid value for upstream block detection (blockedif=)")
} }
// Build resolver.
newResolver := &Resolver{ newResolver := &Resolver{
ConfigURL: resolverURL, ConfigURL: resolverURL,
Info: &ResolverInfo{ Info: &ResolverInfo{
Name: query.Get("name"), Name: query.Get(parameterName),
Type: u.Scheme, Type: u.Scheme,
Source: source, Source: source,
IP: ip, IP: ip,
@ -159,7 +183,7 @@ func createResolver(resolverURL, source string) (*Resolver, bool, error) {
} }
// Parse search domains. // Parse search domains.
searchDomains := query.Get("search") searchDomains := query.Get(parameterSearch)
if searchDomains != "" { if searchDomains != "" {
err = configureSearchDomains(newResolver, strings.Split(searchDomains, ","), true) err = configureSearchDomains(newResolver, strings.Split(searchDomains, ","), true)
if err != nil { if err != nil {
@ -168,14 +192,13 @@ func createResolver(resolverURL, source string) (*Resolver, bool, error) {
} }
// Check if searchOnly is set and valid. // Check if searchOnly is set and valid.
if query.Has("searchOnly") { if query.Has(parameterSearchOnly) {
newResolver.SearchOnly = true newResolver.SearchOnly = true
if query.Get(parameterSearchOnly) != "" {
if query.Get("searchOnly") != "" { return nil, false, fmt.Errorf("%s may only be used as an empty parameter", parameterSearchOnly)
return nil, false, errors.New("searchOnly may only be used as an empty parameter")
} }
if len(newResolver.Search) == 0 { if len(newResolver.Search) == 0 {
return nil, false, errors.New("cannot use searchOnly without search scopes") return nil, false, fmt.Errorf("cannot use %s without search scopes", parameterSearchOnly)
} }
} }
@ -186,7 +209,7 @@ func createResolver(resolverURL, source string) (*Resolver, bool, error) {
func configureSearchDomains(resolver *Resolver, searches []string, hardfail bool) error { func configureSearchDomains(resolver *Resolver, searches []string, hardfail bool) error {
// Check all search domains. // Check all search domains.
for i, value := range searches { for i, value := range searches {
trimmedDomain := strings.Trim(value, ".") trimmedDomain := strings.ToLower(strings.Trim(value, "."))
err := checkSearchScope(trimmedDomain) err := checkSearchScope(trimmedDomain)
if err != nil { if err != nil {
if hardfail { if hardfail {