Implement review suggestions, simplify validation

This commit is contained in:
Daniel 2020-10-14 09:52:42 +02:00
parent ab55f908c9
commit 83f880f671
2 changed files with 50 additions and 46 deletions

View file

@ -17,7 +17,7 @@ const (
) )
var ( var (
containsRegex = regexp.MustCompile(`^\*?[a-z0-9\.-]+\*$`) allowedDomainChars = regexp.MustCompile(`^[a-z0-9\.-]+$`)
) )
// EndpointDomain matches domains. // EndpointDomain matches domains.
@ -88,72 +88,65 @@ func (ep *EndpointDomain) String() string {
return ep.renderPPP(ep.OriginalValue) return ep.renderPPP(ep.OriginalValue)
} }
func isValidEndpointDomain(value string) bool {
// Check for root domain
if value == "." {
return true
}
// Check for a "contains" value.
if containsRegex.MatchString(value) {
return true
}
// Remove special leading characters.
value = strings.TrimLeft(value, ".*")
// Check if value is now a valid domain.
return netutils.IsValidFqdn(value)
}
func parseTypeDomain(fields []string) (Endpoint, error) { func parseTypeDomain(fields []string) (Endpoint, error) {
domain := fields[1] domain := fields[1]
ep := &EndpointDomain{ ep := &EndpointDomain{
OriginalValue: domain, OriginalValue: domain,
} }
// fix domain ending // Fix domain ending.
switch domain[len(domain)-1] { switch domain[len(domain)-1] {
case '.': case '.', '*':
case '*':
default: default:
domain += "." domain += "."
} }
// Check if domain is valid. // Fix domain case.
if !isValidEndpointDomain(domain) {
return nil, nil
}
// fix domain case
domain = strings.ToLower(domain) domain = strings.ToLower(domain)
needValidFQDN := true
switch { switch {
case strings.HasPrefix(domain, "*") && strings.HasSuffix(domain, "*"): case strings.HasPrefix(domain, "*") && strings.HasSuffix(domain, "*"):
ep.MatchType = domainMatchTypeContains ep.MatchType = domainMatchTypeContains
ep.Domain = strings.Trim(domain, "*") ep.Domain = strings.TrimPrefix(domain, "*")
return ep.parsePPP(ep, fields) ep.Domain = strings.TrimSuffix(ep.Domain, "*")
needValidFQDN = false
case strings.HasSuffix(domain, "*"): case strings.HasSuffix(domain, "*"):
ep.MatchType = domainMatchTypePrefix ep.MatchType = domainMatchTypePrefix
ep.Domain = strings.Trim(domain, "*") ep.Domain = strings.TrimSuffix(domain, "*")
return ep.parsePPP(ep, fields) needValidFQDN = false
// Prefix matching cannot be combined with zone matching
if strings.HasPrefix(ep.Domain, ".") {
return nil, nil
}
case strings.HasPrefix(domain, "*"): case strings.HasPrefix(domain, "*"):
ep.MatchType = domainMatchTypeSuffix ep.MatchType = domainMatchTypeSuffix
ep.Domain = strings.Trim(domain, "*") ep.Domain = strings.TrimPrefix(domain, "*")
return ep.parsePPP(ep, fields) needValidFQDN = false
case strings.HasPrefix(domain, "."): case strings.HasPrefix(domain, "."):
ep.MatchType = domainMatchTypeZone ep.MatchType = domainMatchTypeZone
ep.Domain = strings.TrimLeft(domain, ".") ep.Domain = strings.TrimPrefix(domain, ".")
ep.DomainZone = "." + ep.Domain ep.DomainZone = "." + ep.Domain
return ep.parsePPP(ep, fields)
default: default:
ep.MatchType = domainMatchTypeExact ep.MatchType = domainMatchTypeExact
ep.Domain = domain ep.Domain = domain
return ep.parsePPP(ep, fields)
} }
// Validate domain "content".
switch {
case needValidFQDN && !netutils.IsValidFqdn(ep.Domain):
return nil, nil
case !needValidFQDN && !allowedDomainChars.MatchString(ep.Domain):
return nil, nil
case strings.Contains(ep.Domain, ".."):
// The above regex does not catch double dots.
return nil, nil
}
return ep.parsePPP(ep, fields)
} }

View file

@ -29,18 +29,29 @@ func testEndpointMatch(t *testing.T, ep Endpoint, entity *intel.Entity, expected
} }
} }
func testFormat(t *testing.T, endpoint string) { func testFormat(t *testing.T, endpoint string, shouldSucceed bool) {
_, err := parseEndpoint(endpoint) _, err := parseEndpoint(endpoint)
if shouldSucceed {
assert.NoError(t, err) assert.NoError(t, err)
} else {
assert.Error(t, err)
}
} }
func TestEndpointFormat(t *testing.T) { func TestEndpointFormat(t *testing.T) {
testFormat(t, "+ .") testFormat(t, "+ .", false)
testFormat(t, "+ .at") testFormat(t, "+ .at", true)
testFormat(t, "+ .at.") testFormat(t, "+ .at.", true)
testFormat(t, "+ 1.at") testFormat(t, "+ 1.at", true)
testFormat(t, "+ 1.at.") testFormat(t, "+ 1.at.", true)
testFormat(t, "+ 1.f.ix.de.") testFormat(t, "+ 1.f.ix.de.", true)
testFormat(t, "+ *contains*", true)
testFormat(t, "+ *has.suffix", true)
testFormat(t, "+ *.has.suffix", true)
testFormat(t, "+ *has.prefix*", true)
testFormat(t, "+ *has.prefix.*", true)
testFormat(t, "+ .sub.and.prefix.*", false)
testFormat(t, "+ *.sub..and.prefix.*", false)
} }
func TestEndpointMatching(t *testing.T) { func TestEndpointMatching(t *testing.T) {