mirror of
https://blitiri.com.ar/repos/chasquid
synced 2026-10-29 15:02:30 +00:00
Reject invalid characters in domains
Domains in addresses had very lax validation, which allowed them to include characters like "/". That could be exploited to trigger a daemon panic: a MAIL FROM "x@evil/foo" could be accepted and, on failed delivery, a DSN queued. Attempting to deliver the DSN would cause an MTA-STS cache lookup, which would panic because the domain includes a "/" and crash the server. Because the DSN would be queued, the server would crash again on restarts, and only self-recover after give_up_send_after (20h by default). To fix this, we now explicitly validate the domain when normalizing it, make MTA-STS cache not panic on invalid domains, and also make the SMTP courier fail permanently on invalid domains. Thanks to John JEAN <john@wargan.com> for finding and reporting this problem. The detailed report can be found in https://johnjean.io/advisories/chasquid-unauthenticated-remote-dos/.
This commit is contained in:
@@ -473,6 +473,16 @@ func (c *Conn) MAIL(params string) (code int, msg string) {
|
||||
return 501, "5.1.7 Sender address too long"
|
||||
}
|
||||
|
||||
// Normalize (and validate) the address before doing any lookups.
|
||||
// Note SPF and the security level check use the address as given,
|
||||
// and we only use the normalized version from then on.
|
||||
normAddr, err := normalize.DomainToUnicode(addr)
|
||||
if err != nil {
|
||||
maillog.Rejected(c.remoteAddr, addr, nil,
|
||||
fmt.Sprintf("malformed address: %v", err))
|
||||
return 501, "5.1.8 Malformed sender domain"
|
||||
}
|
||||
|
||||
// SPF check - https://tools.ietf.org/html/rfc7208#section-2.4
|
||||
// We opt not to fail on errors, to avoid accidents from preventing
|
||||
// delivery.
|
||||
@@ -491,12 +501,7 @@ func (c *Conn) MAIL(params string) (code int, msg string) {
|
||||
return 550, "5.7.3 Security level check failed"
|
||||
}
|
||||
|
||||
addr, err = normalize.DomainToUnicode(addr)
|
||||
if err != nil {
|
||||
maillog.Rejected(c.remoteAddr, addr, nil,
|
||||
fmt.Sprintf("malformed address: %v", err))
|
||||
return 501, "5.1.8 Malformed sender domain (IDNA conversion failed)"
|
||||
}
|
||||
addr = normAddr
|
||||
}
|
||||
|
||||
c.mailFrom = addr
|
||||
@@ -595,7 +600,7 @@ func (c *Conn) RCPT(params string) (code int, msg string) {
|
||||
|
||||
addr, err := normalize.DomainToUnicode(e.Address)
|
||||
if err != nil {
|
||||
return 501, "5.1.2 Malformed destination domain (IDNA conversion failed)"
|
||||
return 501, "5.1.2 Malformed destination domain"
|
||||
}
|
||||
|
||||
// https://tools.ietf.org/html/rfc5321#section-4.5.3.1.3
|
||||
|
||||
Reference in New Issue
Block a user