sender check: the sender map read and looked up as Postfix does it
Postfix 3.7.11 takes the owners of the first key mail_addr_find() finds -
the address, then without its extension, then @domain, each tried only
when the one before is absent (src/global/mail_addr_find.c,
mail_addr_find_opt()) - and compares the login with them by
strcasecmp_utf8() (src/smtpd/smtpd_check.c,
reject_auth_sender_login_mismatch()). The check accepted a From: address
when any of the three keys named the application: an application holding
@domain could write an address listed for another application of the
domain, which Postfix refuses it in the envelope, and have it signed
(assumptions B-PS1).
The table is now read as dict_thash_open() reads it: continuation lines,
owners split on commas and blanks (B-PS4), the key ending at the first
blank outside quotes, keys folded; a key given twice makes Postfix refuse
the whole table (no DICT_FLAG_DUP_* flag), and the check then defers too.
The writer folds keys, so two cases of one address cannot be two lines.
e2e on the stand (2026-10-14, make e2e, exit 0): the wildcard application
is refused billing@ - listed for app-list - in From: (550 5.7.1), and in
the envelope by Postfix at RCPT ("553 5.7.1 <billing@...>: Sender address
rejected: not owned by user"). go vet and go test ./... pass on the
server (23 packages).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -50,6 +50,22 @@ func TestRenderSenderLoginMapsDedupesLogin(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Keys differing only in case are one key to Postfix, which folds them, and
|
||||
// two of them would make it refuse the whole table (dict_thash_open() with no
|
||||
// DICT_FLAG_DUP_* flag): they are written as one line.
|
||||
func TestRenderSenderLoginMapsFoldsKeys(t *testing.T) {
|
||||
got, err := renderSenderLoginMaps([]Binding{
|
||||
{"Billing@Example.org", "billing"},
|
||||
{"billing@example.org", "billing2"},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(got) != "billing@example.org billing,billing2\n" {
|
||||
t.Errorf("map = %q, want one folded key", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAssertMapSafeRejectsInjection(t *testing.T) {
|
||||
bad := []struct{ addr, login string }{
|
||||
{"@exa mple.com", "log"},
|
||||
|
||||
Reference in New Issue
Block a user