2
0
forked from drew/smtprelay

Expand allowedUsers email field to support comma-separated and domains (#9)

* Expand allowedUsers email field to support comma-separated and domains

Closes #8

* Refactor AuthFetch() to return AuthUser struct

Also, this breaks out a parseLine() function which can be easily tested.

* Ignore empty addrs after splitting commas

This ignores a trailing comma

* Add tests for auth parseLine()

* Update documentation in smtprelay.ini

* Fix bug where addrAllowed() was incorrectly case-sensitive

* Update allowedUsers allowed domain format to require leading @

This disambiguates a local user ('john.smith') from a domain ('example.com')
This commit is contained in:
Jonathon Reinhart
2021-02-14 16:16:18 -05:00
committed by GitHub
parent 5c2e28ac36
commit 0e8986ca79
5 changed files with 278 additions and 23 deletions

47
main.go
View File

@@ -36,15 +36,58 @@ func connectionChecker(peer smtpd.Peer) error {
return smtpd.Error{Code: 421, Message: "Denied"}
}
func addrAllowed(addr string, allowedAddrs []string) bool {
if allowedAddrs == nil {
// If absent, all addresses are allowed
return true
}
addr = strings.ToLower(addr)
// Extract optional domain part
domain := ""
if idx := strings.LastIndex(addr, "@"); idx != -1 {
domain = strings.ToLower(addr[idx+1:])
}
// Test each address from allowedUsers file
for _, allowedAddr := range allowedAddrs {
allowedAddr = strings.ToLower(allowedAddr)
// Three cases for allowedAddr format:
if idx := strings.Index(allowedAddr, "@"); idx == -1 {
// 1. local address (no @) -- must match exactly
if allowedAddr == addr {
return true
}
} else {
if idx != 0 {
// 2. email address (user@domain.com) -- must match exactly
if allowedAddr == addr {
return true
}
} else {
// 3. domain (@domain.com) -- must match addr domain
allowedDomain := allowedAddr[idx+1:]
if allowedDomain == domain {
return true
}
}
}
}
return false
}
func senderChecker(peer smtpd.Peer, addr string) error {
// check sender address from auth file if user is authenticated
if *allowedUsers != "" && peer.Username != "" {
_, email, err := AuthFetch(peer.Username)
user, err := AuthFetch(peer.Username)
if err != nil {
return smtpd.Error{Code: 451, Message: "Bad sender address"}
}
if email != "" && strings.ToLower(addr) != strings.ToLower(email) {
if !addrAllowed(addr, user.allowedAddresses) {
return smtpd.Error{Code: 451, Message: "Bad sender address"}
}
}