mirror of
https://github.com/safing/portmaster
synced 2025-09-01 18:19:12 +00:00
Fix domain endpoint validation
This commit is contained in:
parent
eab2ab3413
commit
ab55f908c9
2 changed files with 81 additions and 46 deletions
|
@ -5,6 +5,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/safing/portmaster/intel"
|
||||
"github.com/safing/portmaster/network/netutils"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -16,8 +17,7 @@ const (
|
|||
)
|
||||
|
||||
var (
|
||||
domainRegex = regexp.MustCompile(`^\*?(([a-z0-9][a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z]{2,}\.?$`)
|
||||
altDomainRegex = regexp.MustCompile(`^\*?[a-z0-9\.-]+\*$`)
|
||||
containsRegex = regexp.MustCompile(`^\*?[a-z0-9\.-]+\*$`)
|
||||
)
|
||||
|
||||
// EndpointDomain matches domains.
|
||||
|
@ -88,53 +88,72 @@ func (ep *EndpointDomain) String() string {
|
|||
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) {
|
||||
domain := fields[1]
|
||||
|
||||
if domainRegex.MatchString(domain) || altDomainRegex.MatchString(domain) {
|
||||
ep := &EndpointDomain{
|
||||
OriginalValue: domain,
|
||||
}
|
||||
|
||||
// fix domain ending
|
||||
switch domain[len(domain)-1] {
|
||||
case '.':
|
||||
case '*':
|
||||
default:
|
||||
domain += "."
|
||||
}
|
||||
|
||||
// fix domain case
|
||||
domain = strings.ToLower(domain)
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(domain, "*") && strings.HasSuffix(domain, "*"):
|
||||
ep.MatchType = domainMatchTypeContains
|
||||
ep.Domain = strings.Trim(domain, "*")
|
||||
return ep.parsePPP(ep, fields)
|
||||
|
||||
case strings.HasSuffix(domain, "*"):
|
||||
ep.MatchType = domainMatchTypePrefix
|
||||
ep.Domain = strings.Trim(domain, "*")
|
||||
return ep.parsePPP(ep, fields)
|
||||
|
||||
case strings.HasPrefix(domain, "*"):
|
||||
ep.MatchType = domainMatchTypeSuffix
|
||||
ep.Domain = strings.Trim(domain, "*")
|
||||
return ep.parsePPP(ep, fields)
|
||||
|
||||
case strings.HasPrefix(domain, "."):
|
||||
ep.MatchType = domainMatchTypeZone
|
||||
ep.Domain = strings.TrimLeft(domain, ".")
|
||||
ep.DomainZone = "." + ep.Domain
|
||||
return ep.parsePPP(ep, fields)
|
||||
|
||||
default:
|
||||
ep.MatchType = domainMatchTypeExact
|
||||
ep.Domain = domain
|
||||
return ep.parsePPP(ep, fields)
|
||||
}
|
||||
ep := &EndpointDomain{
|
||||
OriginalValue: domain,
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
// fix domain ending
|
||||
switch domain[len(domain)-1] {
|
||||
case '.':
|
||||
case '*':
|
||||
default:
|
||||
domain += "."
|
||||
}
|
||||
|
||||
// Check if domain is valid.
|
||||
if !isValidEndpointDomain(domain) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// fix domain case
|
||||
domain = strings.ToLower(domain)
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(domain, "*") && strings.HasSuffix(domain, "*"):
|
||||
ep.MatchType = domainMatchTypeContains
|
||||
ep.Domain = strings.Trim(domain, "*")
|
||||
return ep.parsePPP(ep, fields)
|
||||
|
||||
case strings.HasSuffix(domain, "*"):
|
||||
ep.MatchType = domainMatchTypePrefix
|
||||
ep.Domain = strings.Trim(domain, "*")
|
||||
return ep.parsePPP(ep, fields)
|
||||
|
||||
case strings.HasPrefix(domain, "*"):
|
||||
ep.MatchType = domainMatchTypeSuffix
|
||||
ep.Domain = strings.Trim(domain, "*")
|
||||
return ep.parsePPP(ep, fields)
|
||||
|
||||
case strings.HasPrefix(domain, "."):
|
||||
ep.MatchType = domainMatchTypeZone
|
||||
ep.Domain = strings.TrimLeft(domain, ".")
|
||||
ep.DomainZone = "." + ep.Domain
|
||||
return ep.parsePPP(ep, fields)
|
||||
|
||||
default:
|
||||
ep.MatchType = domainMatchTypeExact
|
||||
ep.Domain = domain
|
||||
return ep.parsePPP(ep, fields)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/safing/portmaster/core/pmtesting"
|
||||
"github.com/safing/portmaster/intel"
|
||||
)
|
||||
|
@ -27,6 +29,20 @@ func testEndpointMatch(t *testing.T, ep Endpoint, entity *intel.Entity, expected
|
|||
}
|
||||
}
|
||||
|
||||
func testFormat(t *testing.T, endpoint string) {
|
||||
_, err := parseEndpoint(endpoint)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestEndpointFormat(t *testing.T) {
|
||||
testFormat(t, "+ .")
|
||||
testFormat(t, "+ .at")
|
||||
testFormat(t, "+ .at.")
|
||||
testFormat(t, "+ 1.at")
|
||||
testFormat(t, "+ 1.at.")
|
||||
testFormat(t, "+ 1.f.ix.de.")
|
||||
}
|
||||
|
||||
func TestEndpointMatching(t *testing.T) {
|
||||
// ANY
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue