base-trixie: the image on Debian trixie, Postfix 3.10.13; Received: hidden on 465/587
test / test (push) Canceled after 0s

The runtime base is debian:trixie-slim, the build stage golang:1.26-trixie:
Postfix 3.10.13 with upstream's 2026 security fixes up to the August
batch, libmilter 8.18.1, OpenSSL 3.5. Every citation of another program in
code, scripts and documents was re-read against the trixie sources
(dev/upstream; bookworm's kept in dev/upstream-bookworm) and updated;
development.md's cited-package table holds the trixie versions.

What the re-reading changed in behaviour:
- logtail: reject lines with sasl_method/sasl_username/sasl_sender
  (smtpd_check.c:1019-1026); cleanup's "removed (canceled)" forgets a
  port-25 id (cleanup_api.c:363-364).
- internal/postfix/retry.go reads postconf's stdout only: since 3.9 a
  deprecated-parameter warning on stderr made one value too many and the
  panel fell back to the compiled-in retry policy.
- logrotate-loop.sh: logrotate 3.22 exits 1 when it ignores a config;
  the loop refuses on that output whatever the status.
- postfix-config.sh: cyrus_sasl_config_path set explicitly (bookworm's
  07_sasl_config.diff is gone); maillog_file_permissions=0640; mynetworks
  explicit; Dockerfile: SYNC_CHROOT= in /etc/default/postfix,
  opendkim-tools dropped, openssl named, systemd-standalone-sysusers so
  cron does not bring the whole of systemd.
- The selfpost group is 10998, outside the system range 100-999: in
  trixie a package took 998 and the build failed (owner's decision:
  a conflict-free id, the distribution's own ids untouched). The
  entrypoint hands /data back by name when the user or the group differs.
  Guide, backup refusal text, help (design commit 68ec8b2), e2e.
- smtpd_hide_client_session=yes on smtps and submission (owner's
  decision): Received: names no client, TLS, login or protocol; port 25
  keeps the full header. e2e checks both.
- test/upstream/opendkim-probe.sh makes keys with openssl genrsa.

Tests: on the server, make e2e exit 0 (674 s, the image built on trixie),
go vet + go test 27 packages ok. CHANGELOG [Unreleased], guide,
architecture.md, security.md, roadmap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mix
2026-10-15 19:31:35 +03:00
co-authored by Claude Opus 5.5
parent 68ec8b274c
commit 1c6e04b7d3
80 changed files with 970 additions and 454 deletions
+15 -3
View File
@@ -272,7 +272,7 @@ func testInboundRelay(t *testing.T, sc *scenario) {
// Port 25's limit is the whole limit: a 12 MB message - over the
// 10240000 bytes cleanup would hold it to on its own, under the 25 MiB the
// listener says - is accepted and passed on (Postfix 3.7.11,
// listener says - is accepted and passed on (Postfix 3.10.13,
// src/cleanup/cleanup_init.c, cleanup_post_jail(); assumptions C-P31).
big := uniqueToken("inbound-12mb")
line := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ab\r\n"
@@ -365,7 +365,7 @@ func testInboundRelay(t *testing.T, sc *scenario) {
t.Fatalf("the Inbound log holds %d rows, want the two relayed messages alone:\n%s", len(rows), strings.Join(rows, "\n"))
}
// Postfix 3.7.11, src/smtpd/smtpd_check.c: "User unknown in relay recipient
// Postfix 3.10.13, src/smtpd/smtpd_check.c: "User unknown in relay recipient
// table" (check_rcpt_maps(); unknown_relay_recipient_reject_code,
// DEF_RELAY_RCPT_CODE 550) and "Relay access denied"
// (reject_unauth_destination(); DEF_RELAY_CODE 554).
@@ -464,7 +464,8 @@ func testInboundRelay(t *testing.T, sc *scenario) {
// smuggling sequence, with a second transaction's commands behind it - is
// body, and the one message delivered carries all of it; nothing is read as
// a second transaction (smtpd_forbid_bare_newline=normalize on smtp/inet,
// build/postfix-config.sh; Postfix 3.7.11, src/smtpd/smtpd.c:3649-3652).
// build/postfix-config.sh; Postfix 3.10.13, src/smtpd/smtpd.c:3713-3716,
// receive_data_message()).
// Runs after testInboundRelay, whose domain, upstream and recipient it uses.
func testInboundBareNewline(t *testing.T, sc *scenario) {
token := uniqueToken("inbound-bare")
@@ -484,6 +485,17 @@ func testInboundBareNewline(t *testing.T, sc *scenario) {
if !bytes.Contains(raw, []byte(smuggled)) {
t.Fatalf("the message was cut at the bare-newline \".\": what followed it is not in the delivered message\n%s", raw)
}
// Port 25 keeps RFC 5321's trace: smtpd_hide_client_session is set on
// the submission ports only (build/postfix-config.sh; Postfix 3.10.13,
// proto/postconf.proto:19587-19589, "must be used for the port 25 MTA
// service"), so this Received: header opens with "from" and the HELO.
recv, err := postfixReceived(raw)
if err != nil {
t.Fatal(err)
}
if len(recv) != 1 || !strings.HasPrefix(recv[0], "from mx.stranger.e2e.test ") {
t.Fatalf("port 25's Received: header should name the sending server, got %q", recv)
}
// A second transaction, had Postfix read one, would be delivered right
// behind the first: give it the time and count the files that carry the
// smuggled token.