diff --git a/cmake/Directories.cmake b/cmake/Directories.cmake index 26c491c..eff099e 100644 --- a/cmake/Directories.cmake +++ b/cmake/Directories.cmake @@ -27,6 +27,10 @@ set(XPL_DEFAULT_STATE_DIR ${BONGO_STATE_DIR}) set(BONGO_RUNTIME_DIR /run/bongo CACHE PATH "Volatile Bongo runtime directory") set(XPL_DEFAULT_RUNTIME_DIR ${BONGO_RUNTIME_DIR}) +set(BONGO_MAILDROP_DIR /var/spool/bongo/maildrop CACHE PATH + "Protected local mail submission directory") +get_filename_component(BONGO_MAILDROP_ROOT + "${BONGO_MAILDROP_DIR}" DIRECTORY) set(XPL_DEFAULT_BIN_DIR ${CMAKE_INSTALL_PREFIX}/sbin) set(XPL_DEFAULT_LIB_DIR ${CMAKE_INSTALL_PREFIX}/${LIB_DIR_NAME}) @@ -63,7 +67,7 @@ set(XPL_DEFAULT_WORK_DIR ${XPL_DEFAULT_STATE_DIR}/work) set(XPL_DEFAULT_CACHE_DIR ${XPL_DEFAULT_STATE_DIR}/cache) set(XPL_DEFAULT_SCMS_DIR ${XPL_DEFAULT_STATE_DIR}/scms) set(XPL_DEFAULT_SPOOL_DIR ${XPL_DEFAULT_STATE_DIR}/spool) -set(XPL_DEFAULT_MAILDROP_DIR ${XPL_DEFAULT_STATE_DIR}/maildrop) +set(XPL_DEFAULT_MAILDROP_DIR ${BONGO_MAILDROP_DIR}) set(XPL_DEFAULT_STORE_SYSTEM_DIR ${XPL_DEFAULT_STATE_DIR}/system) set(XPL_DEFAULT_SYSTEM_DIR ${XPL_DEFAULT_STATE_DIR}/system) set(XPL_DEFAULT_MAIL_DIR ${XPL_DEFAULT_STATE_DIR}/users) diff --git a/contrib/testing/runtime-path-check.sh b/contrib/testing/runtime-path-check.sh index e86a668..2dbe7a6 100755 --- a/contrib/testing/runtime-path-check.sh +++ b/contrib/testing/runtime-path-check.sh @@ -5,6 +5,8 @@ SERVICE=${BONGO_TEST_SERVICE:-bongo.service} PACKAGE=${BONGO_TEST_PACKAGE:-mail-mta/bongo} RUNTIME_DIR=${BONGO_TEST_RUNTIME_DIR:-/run/bongo} STATE_DIR=${BONGO_TEST_STATE_DIR:-/var/lib/bongo} +MAILDROP_ROOT=${BONGO_TEST_MAILDROP_ROOT:-/var/spool/bongo} +MAILDROP_DIR=${BONGO_TEST_MAILDROP_DIR:-$MAILDROP_ROOT/maildrop} TMPFILES_NAME=${BONGO_TEST_TMPFILES_NAME:-bongo.conf} if [ "${BONGO_ALLOW_LIVE_RUNTIME_TEST:-}" != 1 ]; then @@ -95,7 +97,8 @@ assert_path "$RUNTIME_DIR" 750 bongo:bongo assert_path "$STATE_DIR" 750 bongo:bongo assert_path "$STATE_DIR/dbf" 750 bongo:bongo assert_path "$STATE_DIR/dbf/cookies" 700 bongo:bongo -assert_path "$STATE_DIR/maildrop" 1730 bongo:bongopostdrop +assert_path "$MAILDROP_ROOT" 710 bongo:bongopostdrop +assert_path "$MAILDROP_DIR" 1730 bongo:bongopostdrop assert_path /etc/bongo/ssl.d 750 root:bongo echo "PASS tmpfiles recreated volatile and persistent directory ownership" diff --git a/contrib/testing/systemd-runtime-check.sh b/contrib/testing/systemd-runtime-check.sh index 455d81f..8ea7863 100755 --- a/contrib/testing/systemd-runtime-check.sh +++ b/contrib/testing/systemd-runtime-check.sh @@ -58,8 +58,10 @@ assert_equal "$SERVICE" ProtectKernelTunables yes assert_equal "$SERVICE" RestrictSUIDSGID yes assert_contains "$SERVICE" RequiresMountsFor /etc/bongo assert_contains "$SERVICE" RequiresMountsFor /var/lib/bongo +assert_contains "$SERVICE" RequiresMountsFor /var/spool/bongo/maildrop assert_contains "$SERVICE" ReadWritePaths /run/bongo assert_contains "$SERVICE" ReadWritePaths /var/lib/bongo +assert_contains "$SERVICE" ReadWritePaths /var/spool/bongo/maildrop assert_contains "$SERVICE" RestrictAddressFamilies AF_INET assert_contains "$SERVICE" RestrictAddressFamilies AF_INET6 assert_contains "$SERVICE" RestrictAddressFamilies AF_UNIX diff --git a/debian/tests/installed-smoke b/debian/tests/installed-smoke index 79cbc9a..512a28b 100755 --- a/debian/tests/installed-smoke +++ b/debian/tests/installed-smoke @@ -9,6 +9,10 @@ test -x /usr/sbin/bongopostdrop [ "$(stat -c '%a %U:%G' /usr/sbin/bongopostdrop)" = \ "2755 root:bongopostdrop" ] getent group bongopostdrop >/dev/null +[ "$(stat -c '%a %U:%G' /var/spool/bongo)" = \ + "710 bongo:bongopostdrop" ] +[ "$(stat -c '%a %U:%G' /var/spool/bongo/maildrop)" = \ + "1730 bongo:bongopostdrop" ] python3 -c 'import bongo, bongo_web, libbongo' test -f /lib/systemd/system/bongo.service || test -f /usr/lib/systemd/system/bongo.service diff --git a/debian/tests/package-lifecycle b/debian/tests/package-lifecycle index 83114fb..ecf662f 100755 --- a/debian/tests/package-lifecycle +++ b/debian/tests/package-lifecycle @@ -32,6 +32,8 @@ assert_state() system-store-preserved assert_marker /var/lib/bongo/spool/lifecycle-test \ queue-state-preserved + assert_marker /var/spool/bongo/maildrop/lifecycle-test \ + local-submission-preserved } [ "$(id -u)" -eq 0 ] || die "this test must run as root" @@ -51,6 +53,9 @@ install -d -m 0750 -o root -g bongo \ install -d -m 0750 -o bongo -g bongo \ /var/lib/bongo/users/lifecycle-test \ /var/lib/bongo/system /var/lib/bongo/spool +install -d -m 0710 -o bongo -g bongopostdrop /var/spool/bongo +install -d -m 1730 -o bongo -g bongopostdrop \ + /var/spool/bongo/maildrop printf '%s\n' configuration-preserved > \ /etc/bongo/config.d/lifecycle-test printf '%s\n' private-key-preserved > \ @@ -62,9 +67,12 @@ printf '%s\n' system-store-preserved > \ /var/lib/bongo/system/lifecycle-test printf '%s\n' queue-state-preserved > \ /var/lib/bongo/spool/lifecycle-test +printf '%s\n' local-submission-preserved > \ + /var/spool/bongo/maildrop/lifecycle-test chown -R bongo:bongo /var/lib/bongo/users/lifecycle-test \ /var/lib/bongo/system/lifecycle-test \ /var/lib/bongo/spool/lifecycle-test +chown bongo:bongopostdrop /var/spool/bongo/maildrop/lifecycle-test # A same-version reinstall must leave administrator configuration, keys, # mailboxes, Store data, and a possibly non-empty queue untouched. diff --git a/docs/directory-layout.md b/docs/directory-layout.md index 78612c2..b0c4c04 100644 --- a/docs/directory-layout.md +++ b/docs/directory-layout.md @@ -24,6 +24,7 @@ configuration under `/etc`, not `/usr/etc`. | `/var/lib/bongo/web` | Web session, task, and identity databases. | | `/var/lib/bongo/work` | Persistent diagnostics, traces, and recovery data. | | `/var/lib/bongo/cache` | Regenerable caches. | +| `/var/spool/bongo/maildrop` | Protected setgid hand-off for unprivileged local mail submission. | | `/run/bongo` | Volatile PID and agent recovery files. | | `/usr/sbin` | Server agents and administration programs. | | `/usr/libexec/bongo` | Private administration helpers. | @@ -52,7 +53,8 @@ cmake -S . -B build \ -DSYSCONF_INSTALL_DIR=/etc \ -DBONGO_CONFIG_DIR=/etc/bongo \ -DBONGO_STATE_DIR=/srv/bongo \ - -DBONGO_RUNTIME_DIR=/run/bongo + -DBONGO_RUNTIME_DIR=/run/bongo \ + -DBONGO_MAILDROP_DIR=/var/spool/bongo/maildrop ``` Absolute paths are compiled into agents and generated service/configuration @@ -63,8 +65,9 @@ or supplying matching package overrides. Packages should not ship a populated `/var/run` or `/run` tree. systemd-tmpfiles or the service script creates `/run/bongo` at boot. -Persistent empty directories below `/var/lib/bongo` are created during setup -or package installation with the appropriate owner. +Persistent empty directories below `/var/lib/bongo` and the protected local +submission path below `/var/spool/bongo` are created during setup or package +installation with the appropriate owner. TLS, DKIM, DMARC and SRS material below `/etc/bongo` must be included in backup and permission reviews. ACME deployments may point configuration at paths @@ -76,15 +79,16 @@ the Store remain protected state below `/var/lib/bongo`. Distribution upgrades and same-version reinstalls preserve all administrator-created configuration and key material below `/etc/bongo` and all persistent mail, Store, queue, account, Web, and worker state below -`/var/lib/bongo`. +`/var/lib/bongo`. Accepted local submissions below `/var/spool/bongo` are +preserved as well. On Debian, a normal package removal deletes Bongo programs and service units but retains package-owned conffiles as well as both Bongo trees. A purge also deletes the package-owned Fail2ban filter and disabled jail template. It still does **not** delete `/etc/bongo` or `/var/lib/bongo`: destroying keys, server configuration, queued messages, or user mail as a side effect of package -removal would be unsafe. Remove those two trees explicitly only after making -and verifying any required backup. +removal would be unsafe. The same rule applies to `/var/spool/bongo`. Remove +these trees explicitly only after making and verifying any required backup. `/run/bongo` contains no persistent state. Its contents can remain until the next boot after a package removal and must never be relied upon for recovery. diff --git a/init/bongo.service.in b/init/bongo.service.in index d1d3ae7..60fd064 100644 --- a/init/bongo.service.in +++ b/init/bongo.service.in @@ -24,7 +24,7 @@ Description=Bongo mail and calendar server Documentation=https://gitea.disconnected-by-peer.at/geos_one/bongo Wants=network-online.target After=network-online.target nss-lookup.target local-fs.target systemd-tmpfiles-setup.service clamd.service clamav-daemon.service spamassassin.service spamd.service -RequiresMountsFor=@XPL_DEFAULT_STATE_DIR@ @XPL_DEFAULT_CONF_DIR@ +RequiresMountsFor=@XPL_DEFAULT_STATE_DIR@ @XPL_DEFAULT_MAILDROP_DIR@ @XPL_DEFAULT_CONF_DIR@ [Service] Type=simple @@ -58,7 +58,7 @@ RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX RestrictRealtime=true RestrictSUIDSGID=true SystemCallArchitectures=native -ReadWritePaths=@XPL_DEFAULT_STATE_DIR@ @XPL_DEFAULT_RUNTIME_DIR@ @XPL_DEFAULT_SSL_DIR@ @XPL_DEFAULT_CONFIG_DIR@ +ReadWritePaths=@XPL_DEFAULT_STATE_DIR@ @XPL_DEFAULT_MAILDROP_DIR@ @XPL_DEFAULT_RUNTIME_DIR@ @XPL_DEFAULT_SSL_DIR@ @XPL_DEFAULT_CONFIG_DIR@ [Install] WantedBy=multi-user.target diff --git a/init/bongo.tmpfiles.in b/init/bongo.tmpfiles.in index fce8313..234e78c 100644 --- a/init/bongo.tmpfiles.in +++ b/init/bongo.tmpfiles.in @@ -27,6 +27,7 @@ d @XPL_DEFAULT_CACHE_DIR@ 0750 @BONGO_USER@ @BONGO_USER@ - d @XPL_DEFAULT_CACHE_DIR@/mta-sts 0750 @BONGO_USER@ @BONGO_USER@ - d @XPL_DEFAULT_SCMS_DIR@ 0750 @BONGO_USER@ @BONGO_USER@ - d @XPL_DEFAULT_SPOOL_DIR@ 0750 @BONGO_USER@ @BONGO_USER@ - +d @BONGO_MAILDROP_ROOT@ 0710 @BONGO_USER@ bongopostdrop - d @XPL_DEFAULT_MAILDROP_DIR@ 1730 @BONGO_USER@ bongopostdrop - d @XPL_DEFAULT_SYSTEM_DIR@ 0750 @BONGO_USER@ @BONGO_USER@ - d @XPL_DEFAULT_MAIL_DIR@ 0750 @BONGO_USER@ @BONGO_USER@ -