#! /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 <lamont@debian.org>, 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
