mirror of
https://github.com/safing/portmaster
synced 2025-09-04 03:29:12 +00:00
Fix FQDN validation and add tests
This commit is contained in:
parent
75d7a91843
commit
ca8b36cbc7
2 changed files with 89 additions and 2 deletions
|
@ -2,13 +2,57 @@ package netutils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
cleanDomainRegex = regexp.MustCompile(`^((xn--)?[a-z0-9-_]{0,61}[a-z0-9]{1,1}\.)*(xn--)?([a-z0-9-]{1,61}|[a-z0-9-]{1,30}\.[a-z]{2,}\.)$`)
|
cleanDomainRegex = regexp.MustCompile(
|
||||||
|
`^` + // match beginning
|
||||||
|
`(` + // start subdomain group
|
||||||
|
`(xn--)?` + // idn prefix
|
||||||
|
`[a-z0-9_-]{1,63}` + // main chunk
|
||||||
|
`\.` + // ending with a dot
|
||||||
|
`)*` + // end subdomain group, allow any number of subdomains
|
||||||
|
`(xn--)?` + // TLD idn prefix
|
||||||
|
`[a-z0-9_-]{2,63}` + // TLD main chunk with at least two characters
|
||||||
|
`\.` + // ending with a dot
|
||||||
|
`$`, // match end
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsValidFqdn returns whether the given string is a valid fqdn.
|
// IsValidFqdn returns whether the given string is a valid fqdn.
|
||||||
func IsValidFqdn(fqdn string) bool {
|
func IsValidFqdn(fqdn string) bool {
|
||||||
return cleanDomainRegex.MatchString(fqdn)
|
// root zone
|
||||||
|
if fqdn == "." {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// check max length
|
||||||
|
if len(fqdn) > 256 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// check with regex
|
||||||
|
if !cleanDomainRegex.MatchString(fqdn) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// check with miegk/dns
|
||||||
|
|
||||||
|
// IsFqdn checks if a domain name is fully qualified.
|
||||||
|
if !dns.IsFqdn(fqdn) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsDomainName checks if s is a valid domain name, it returns the number of
|
||||||
|
// labels and true, when a domain name is valid. Note that non fully qualified
|
||||||
|
// domain name is considered valid, in this case the last label is counted in
|
||||||
|
// the number of labels. When false is returned the number of labels is not
|
||||||
|
// defined. Also note that this function is extremely liberal; almost any
|
||||||
|
// string is a valid domain name as the DNS is 8 bit protocol. It checks if each
|
||||||
|
// label fits in 63 characters and that the entire name will fit into the 255
|
||||||
|
// octet wire format limit.
|
||||||
|
_, ok := dns.IsDomainName(fqdn)
|
||||||
|
return ok
|
||||||
}
|
}
|
||||||
|
|
43
network/netutils/cleandns_test.go
Normal file
43
network/netutils/cleandns_test.go
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
package netutils
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func testDomainValidity(t *testing.T, domain string, isValid bool) {
|
||||||
|
if IsValidFqdn(domain) != isValid {
|
||||||
|
t.Errorf("domain %s failed check: was valid=%v, expected valid=%v", domain, IsValidFqdn(domain), isValid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDNSValidation(t *testing.T) {
|
||||||
|
// valid
|
||||||
|
testDomainValidity(t, ".", true)
|
||||||
|
testDomainValidity(t, "at.", true)
|
||||||
|
testDomainValidity(t, "orf.at.", true)
|
||||||
|
testDomainValidity(t, "www.orf.at.", true)
|
||||||
|
testDomainValidity(t, "a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.x.y.z.example.org.", true)
|
||||||
|
testDomainValidity(t, "a_a.com.", true)
|
||||||
|
testDomainValidity(t, "a-a.com.", true)
|
||||||
|
testDomainValidity(t, "a_a.com.", true)
|
||||||
|
testDomainValidity(t, "a-a.com.", true)
|
||||||
|
testDomainValidity(t, "xn--a.com.", true)
|
||||||
|
testDomainValidity(t, "xn--asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasd.com.", true)
|
||||||
|
|
||||||
|
// maybe valid
|
||||||
|
testDomainValidity(t, "-.com.", true)
|
||||||
|
testDomainValidity(t, "_.com.", true)
|
||||||
|
testDomainValidity(t, "a_.com.", true)
|
||||||
|
testDomainValidity(t, "a-.com.", true)
|
||||||
|
testDomainValidity(t, "_a.com.", true)
|
||||||
|
testDomainValidity(t, "-a.com.", true)
|
||||||
|
|
||||||
|
// invalid
|
||||||
|
testDomainValidity(t, ".com.", false)
|
||||||
|
testDomainValidity(t, ".com.", false)
|
||||||
|
testDomainValidity(t, "xn--asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf.com.", false)
|
||||||
|
testDomainValidity(t, "asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf.com.", false)
|
||||||
|
testDomainValidity(t, "asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf.com.", false)
|
||||||
|
testDomainValidity(t, "asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.asdf.as.com.", false)
|
||||||
|
|
||||||
|
// real world examples
|
||||||
|
testDomainValidity(t, "iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea.com.", true)
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue