#! /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 # It was originally part of the postfix init script, which # was written by LaMont Jones , and based # off of the sendmail init 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 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 } ') # might remove/cleanup chroot here [ -n "$need_chroot" ] || exit 0 # Sigh. Because reasons, files is relative, CAdir not [ "$chroot_extra_CAdir" != '' ] && [ ! "${chroot_extra_CAdir%${chroot_extra_CAdir#?}}"x = '/x' ] && chroot_extra_CAdir=/$chroot_extra_CAdir if [ "$chroot_extra_files" != '' ]; then files='' for file in $chroot_extra_files do [ "${file%${file#?}}"x = '/x' ] && file=${file#?} files="$files $file" done chroot_extra_files=$files fi # Make sure that the chroot environment is set up correctly. umask 022 cd "$queue_directory" #XXX lib=>usr/lib? mkdir -p dev etc lib usr mkdir -p usr/lib/sasl2 # https://bugs.debian.org/426338 # 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" dest=$queue_directory$cadir rm -rf $dest.NEW; mkdir -p $dest.NEW ( cd $cadir # *.pem are mostly symlinks to /usr/share/ca-certificates/ #XXX we can copy just [0-9a-f]{8}\.r?[0-9] files and omit rehash - # do we really want pem and nothing else? find -L . -maxdepth 1 -name '*.pem' -type f -print0 | cpio -p -L0 $dest.NEW ) openssl rehash $dest.NEW rm -rf $dest mv $dest.NEW $dest done FILES="etc/localtime etc/services etc/resolv.conf etc/hosts \ etc/host.conf etc/nsswitch.conf etc/nss_mdns.config \ $chroot_extra_files" for file in $FILES; do [ -d ${file%/*} ] || mkdir -p ${file%/*} if [ -f /${file} ]; then rm -f ${file} && cp /${file} ${file}; fi if [ -f ${file} ]; then chmod a+rX ${file}; fi done # ldaps needs this. debian bug 572841 (echo /dev/random; echo /dev/urandom) | cpio -pdL --quiet . 2>/dev/null || true LIBLIST=$(for name in gcc_s nss resolv; do for f in /lib/*/lib${name}*.so* /lib/lib${name}*.so*; do if [ -f "$f" ]; then echo ${f#/}; fi; done; done) if [ -n "$LIBLIST" ]; then for f in $LIBLIST; do rm -f "$f" done tar cf - -C / $LIBLIST 2>/dev/null |tar xf - fi