diff --git a/framework/address/validation.go b/framework/address/validation.go index 4e2b38a..a165adc 100644 --- a/framework/address/validation.go +++ b/framework/address/validation.go @@ -20,6 +20,8 @@ package address import ( "strings" + + "golang.org/x/net/idna" ) /* @@ -109,17 +111,23 @@ func ValidMailboxName(mbox string) bool { // ValidDomain checks whether the specified string is a valid DNS domain. func ValidDomain(domain string) bool { - if len(domain) > 255 { + if len(domain) > 255 || len(domain) == 0 { return false } - if strings.HasPrefix(domain, ".") || strings.HasSuffix(domain, ".") { + if strings.HasPrefix(domain, ".") { return false } if strings.Contains(domain, "..") { return false } - labels := strings.Split(domain, ".") + // Length checks are to be applied to A-labels form. + // maddy uses U-labels representation across the code (for lookups, etc). + domainASCII, err := idna.ToASCII(domain) + if err != nil { + return false + } + labels := strings.Split(domainASCII, ".") for _, label := range labels { if len(label) > 64 { return false diff --git a/framework/address/validation_test.go b/framework/address/validation_test.go index 9416e55..fdac834 100644 --- a/framework/address/validation_test.go +++ b/framework/address/validation_test.go @@ -1,6 +1,7 @@ package address_test import ( + "strings" "testing" "github.com/foxcpp/maddy/framework/address" @@ -11,3 +12,22 @@ func TestValidMailboxName(t *testing.T) { t.Error("caddy.bug should be valid mailbox name") } } + +func TestValidDomain(t *testing.T) { + for _, c := range []struct { + Domain string + Valid bool + }{ + {Domain: "maddy.email", Valid: true}, + {Domain: "", Valid: false}, + {Domain: "maddy.email.", Valid: true}, + {Domain: "..", Valid: false}, + {Domain: strings.Repeat("a", 256), Valid: false}, + {Domain: "äõäoaõoäaõaäõaoäaoaäõoaäooaoaoiuaiauäõiuüõaõäiauõaaa.tld", Valid: true}, // https://github.com/foxcpp/maddy/issues/554 + {Domain: "xn--oaoaaaoaoaoaooaoaoiuaiauiuaiauaaa-f1cadccdcmd01eddchqcbe07a.tld", Valid: true}, // https://github.com/foxcpp/maddy/issues/554 + } { + if actual := address.ValidDomain(c.Domain); actual != c.Valid { + t.Errorf("expected domain %v to be valid=%v, but got %v", c.Domain, c.Valid, actual) + } + } +}