#! /bin/sh -e # This helper script is run by postfix-script with all # postfix instance specific environment variables set. # It is used mostly to update chroot setup for a given # instance. Run every time any instance starts, from # /usr/lib/postfix/sbin/postfix-script # safety [ -f "$MAIL_CONFIG/main.cf" ] && [ -d "$queue_directory/pid" ] && [ -x "$command_directory/postconf" ] && [ $# = 0 ] || { echo "E: This is internal script used by postfix" >&2 [ $# != 1 ] || echo "E: old postfix initscript will not work with this postfix package version" >&2 exit 1 } chroot_extra_files= chroot_extra_CAdir= SYNC_CHROOT="y" if test -r /etc/default/postfix; then . /etc/default/postfix fi # multiarch triplet for the host this package is built for # (substituted at package build time) multiarch=@MULTIARCH@ POSTCONF="$command_directory/postconf" # if you set myorigin to 'ubuntu.com' or 'debian.org', it is wrong # and annoys the admins of those domains. See also sender_canonical_maps. myorigin=$($POSTCONF -hx myorigin) [ "X${myorigin#/}" = "X${myorigin}" ] || myorigin=$(head -n1 -- "$myorigin") case "$(echo "$myorigin" | tr A-Z a-z)" in (ubuntu.com | debian.org) echo "Invalid \$myorigin ($myorigin), refusing to start" exit 1 ;; esac [ -n "$SYNC_CHROOT" ] || exit 0 compat=$($POSTCONF -xh compatibility_level) [ ${compat%%.*} -ge 1 ] && chroot_test="[y]" || chroot_test="[-y]" # parse master.cf and find out which amount of chroot setup do we need need_chroot=$($POSTCONF -M | awk '# $5=chroot $8=cmd BEGIN { need="" } $5 !~ /'$chroot_test'/ { next } # skip non-chrooted services $8 ~ /^(anvil|bounce|discard|error|flush|pickup|[no]?qmgr|scache|showq|tlsmgr|trivial-rewrite|verify)$/ { next } # internal simple safe services which need no extra chroot setup $8 ~ /^(dnsblog|postscreen)$/ { need="dns"; next } $8 ~ /^(qmqpd)$/ { need="dns"; next } # does it need dns? $8 ~ /^(cleanup)$/ { print "y"; exit } # #948321 - to move to safe list $8 ~ /^(local|pipe|postlogd|proxymap|virtual)$/ { print "y"; exit } # non-chrootable? $8 ~ /^(smtp|smtpd|lmtp)$/ { print "y"; exit } # the interesting ones { print "y"; exit } # by default assume chroot is needed END { print need } ') cd "$queue_directory" # Make sure that the chroot environment is set up correctly. umask 022 # some users keep actual files in /var/spool/postfix/{etc,lib,usr} # (as primary place) because the chroot setup doesn't work right if [ -d usr/lib/zoneinfo ] # unused, <<3.9.1-4 then rm -f usr/lib/zoneinfo/* rmdir usr/lib/zoneinfo 2>/dev/null || : fi if [ -f lib/$multiarch/libgcc_s.so.1 ] # <<3.9.1-5 then # we now place libnss_*.so.2 directly to lib/ (below), but this rm is a one-time op rm -fv lib/libgcc_s*.so* lib/libnss*.so* lib/libresolv*.so* # very old cruft rm -f lib/*/libgcc_s*.so* lib/*/libnss*.so* lib/*/libresolv*.so* rmdir lib/* 2>/dev/null || : fi if [ -f etc/ssl/cert/GlobalSign_Root_CA.pem ] # arbitrary, <<3.9.1-5 then # we re-created everything each run before 3.9.1-5 # remove just the most common dir rm -rf etc/ssl/cert fi # always copy/update small stuff so simple services works too mkdir -p etc cp= rm= for file in \ etc/localtime etc/services etc/resolv.conf etc/hosts \ etc/host.conf etc/nsswitch.conf etc/nss_mdns.config \ $chroot_extra_files do [ -f /$file ] && cp="$cp /$file" || rm="$rm ./$file" done [ -n "$rm" ] && rm -f $rm [ -n "$cp" ] && cp -pLuf --parents -t . -- $cp [ -n "$need_chroot" ] || exit 0 # put just the right nsswitch libraries ($multiarch/libnss_*.so.2) # directly to lib/ (no subdirs) # nss stuff is needed for "native" smtp host lookups (smtp_host_lookup) cp -pLuv -t lib /usr/lib/$multiarch/libnss_*.so.2 || : case "$chroot_extra_CAdir" in # ensure CAdir is absolute ( /* ) ;; ( ?* ) chroot_extra_CAdir=/$chroot_extra_CAdir ;; esac # Copy certificate dirs cadirs_copied= for cadir in \ $($POSTCONF -hx smtp_tls_CApath smtpd_tls_CApath) \ $chroot_extra_CAdir do # strip trailing / while [ "x${cadir%/}" != "x${cadir}" ]; do cadir=${cadir%/}; done case "$cadir" in ($queue_directory/*) continue;; # skip stuff already in chroot (/*) [ -d $cadir ] || continue;; (*) continue;; esac case "$cadis_copied " in (*" $cadir "*) continue ;; esac cadirs_copied="$cadirs_copied $cadir" # only copy already hashed names. This means we only trust # what's trusted on the system, not everything present # Before 3.9.1-5 we truested everything dest=$queue_directory$cadir if [ -d $dest ]; then ( cd $dest # cp does not write over dangling symlinks (#1089836). # walk through the dest dir, print names of regular files looking # like a cert (to process later), delete everything else.. find . -mindepth 1 -maxdepth 1 \( \ \( -name '[0-9a-f]*[0-9a-f].[0-9]' -type f -print \) \ -o -delete \ \) | while read file; do # ..and remove files which don't exist in source anymore [ -f "$caddr/$file" ] || rm -f "$file" done ) fi mkdir -p $dest ( cd $cadir find -L . -name '[0-9a-f]*.[0-9]' -type f \ -exec cp -pLuf -t $dest '{}' + ) done mkdir -p usr/lib/sasl2 # https://bugs.debian.org/426338 ## ldaps needs this. debian bug 572841 (Mar-2010) # let's omit this for now (in Dec-2024) for new installs and see what happens # Having device nodes in /var causes numerous issues # If anything, it can be bind-mounted from actual /dev, # or better yet, just use proxy: map types. # Might as well remove existing dev/*random from old chroot #cp -a -n --parents /dev/random /dev/urandom . 2>/dev/null || :