1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-17 09:37:02 +00:00

Reject invalidomain with wildcards (#412)

Co-authored-by: Cyril DUPONT <cyd@9bis.com>
This commit is contained in:
Cyd
2023-11-12 18:42:20 +01:00
committed by GitHub
parent d7c538a210
commit 20ef8af047
4 changed files with 94 additions and 2 deletions

View File

@@ -117,7 +117,14 @@ func (a *Addressing) ShouldStoreDomain(domain string) bool {
// ShouldAcceptOriginDomain indicates if Inbucket accept mail from the specified domain. // ShouldAcceptOriginDomain indicates if Inbucket accept mail from the specified domain.
func (a *Addressing) ShouldAcceptOriginDomain(domain string) bool { func (a *Addressing) ShouldAcceptOriginDomain(domain string) bool {
domain = strings.ToLower(domain) domain = strings.ToLower(domain)
return !stringutil.SliceContains(a.Config.SMTP.RejectOriginDomains, domain) if len(a.Config.SMTP.RejectOriginDomains) > 0 {
for _, d := range a.Config.SMTP.RejectOriginDomains {
if stringutil.MatchWithWildcards(d, domain) {
return false
}
}
}
return true
} }
// ParseEmailAddress unescapes an email address, and splits the local part from the domain part. // ParseEmailAddress unescapes an email address, and splits the local part from the domain part.

View File

@@ -206,6 +206,8 @@ func TestReadyStateRejectedDomains(t *testing.T) {
tests := []scriptStep{ tests := []scriptStep{
{"MAIL FROM: <john@validdomain.com>", 250}, {"MAIL FROM: <john@validdomain.com>", 250},
{"MAIL FROM: <john@invalidomain.com>", 501}, {"MAIL FROM: <john@invalidomain.com>", 501},
{"MAIL FROM: <john@s1.otherinvaliddomain.com>", 501},
{"MAIL FROM: <john@s2.otherinvaliddomain.com>", 501},
} }
for _, tc := range tests { for _, tc := range tests {
@@ -582,7 +584,7 @@ func setupSMTPServer(ds storage.Store, extHost *extension.Host) *Server {
MaxMessageBytes: 5000, MaxMessageBytes: 5000,
DefaultAccept: true, DefaultAccept: true,
RejectDomains: []string{"deny.com"}, RejectDomains: []string{"deny.com"},
RejectOriginDomains: []string{"invalidomain.com"}, RejectOriginDomains: []string{"invalidomain.com", "*.otherinvaliddomain.com"},
Timeout: 5, Timeout: 5,
}, },
} }

View File

@@ -74,3 +74,40 @@ func MakePathPrefixer(prefix string) func(string) string {
return prefix + path return prefix + path
} }
} }
// Test if a "s" string match a "p" pattern with wildcards (*, ?)
func MatchWithWildcards(p string, s string) bool {
runeInput := []rune(s)
runePattern := []rune(p)
lenInput := len(runeInput)
lenPattern := len(runePattern)
isMatchingMatrix := make([][]bool, lenInput+1)
for i := range isMatchingMatrix {
isMatchingMatrix[i] = make([]bool, lenPattern+1)
}
isMatchingMatrix[0][0] = true
if lenPattern > 0 {
if runePattern[0] == '*' {
isMatchingMatrix[0][1] = true
}
}
for j := 2; j <= lenPattern; j++ {
if runePattern[j-1] == '*' {
isMatchingMatrix[0][j] = isMatchingMatrix[0][j-1]
}
}
for i := 1; i <= lenInput; i++ {
for j := 1; j <= lenPattern; j++ {
if runePattern[j-1] == '*' {
isMatchingMatrix[i][j] = isMatchingMatrix[i-1][j] || isMatchingMatrix[i][j-1]
}
if runePattern[j-1] == '?' || runeInput[i-1] == runePattern[j-1] {
isMatchingMatrix[i][j] = isMatchingMatrix[i-1][j-1]
}
}
}
return isMatchingMatrix[lenInput][lenPattern]
}

View File

@@ -76,3 +76,49 @@ func TestMakePathPrefixer(t *testing.T) {
}) })
} }
} }
func TestMatchWithWildcards(t *testing.T) {
testCases := []struct {
pattern, input string
want bool
}{
{pattern: "", input: "", want: true},
{pattern: "", input: "qwerty", want: false},
{pattern: "qw*ty", input: "qwerty", want: true},
{pattern: "qw?ty", input: "qwerty", want: false},
{pattern: "qwe*ty", input: "qwerty", want: true},
{pattern: "*erty", input: "qwerty", want: true},
{pattern: "?erty", input: "qwerty", want: false},
{pattern: "?werty", input: "qwerty", want: true},
{pattern: "qwer*", input: "qwerty", want: true},
{pattern: "qwer?", input: "qwerty", want: false},
{pattern: "qwert?", input: "qwerty", want: true},
{pattern: "qw**ty", input: "qwerty", want: true},
{pattern: "qw??ty", input: "qwerty", want: true},
{pattern: "qwe??ty", input: "qwerty", want: false},
{pattern: "**erty", input: "qwerty", want: true},
{pattern: "??erty", input: "qwerty", want: true},
{pattern: "??werty", input: "qwerty", want: false},
{pattern: "qwer**", input: "qwerty", want: true},
{pattern: "qwer??", input: "qwerty", want: true},
{pattern: "qwert??", input: "qwerty", want: false},
{pattern: "q?er?y", input: "qwerty", want: true},
{pattern: "q?r?y", input: "qwerty", want: false},
{pattern: "q*er*y", input: "qwerty", want: true},
{pattern: "q*r*y", input: "qwerty", want: true},
{pattern: "q*?werty", input: "qwerty", want: false},
{pattern: "q*?erty", input: "qwerty", want: true},
{pattern: "q?*werty", input: "qwerty", want: false},
{pattern: "q?*erty", input: "qwerty", want: true},
{pattern: "?*rty", input: "qwerty", want: true},
{pattern: "*?rty", input: "qwerty", want: true},
{pattern: "qwe?*", input: "qwerty", want: true},
{pattern: "qwe*?", input: "qwerty", want: true},
}
for _, tc := range testCases {
got := stringutil.MatchWithWildcards(tc.pattern, tc.input)
if got != tc.want {
t.Errorf("Test %s with pattern %s, Got: %v, want: %v", tc.input, tc.pattern, got, tc.want)
}
}
}