#! /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=x86_64-linux-gnu

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

# Get a command to set chroot off (ignoring simple ones but
# include custom if any).
# If it is empty, no interesting services are chrooted
need_chroot=$($daemon_directory/postfix-script chroot -n -Sc off)

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* dev/random dev/urandom
    rmdir lib/* dev 2>/dev/null || :
fi
if [ -f lib/libnss_files.so.2 ] # <<3.9.1-7. Modules from glibc aren't needed in chroot
then
    rm -f lib/libnss_*.so.2
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" ] && /usr/lib/postfix/syncfiles.pl $queue_directory $cp

if [ -z "$need_chroot" ]; then
    [ ! -d etc/ssl/certs ] || rm -rf etc/ssl/certs
    rm -f lib/libnss_*.so.2
    exit 0
fi

# put just the right nsswitch libraries ($multiarch/libnss_*.so.2)
# directly to lib/ (no subdirs). Modules from glibc aren't needed (built-in).
# nss stuff is needed for "native" smtp host lookups (smtp_host_lookup)
# and might be used by other pieces (SASL et al)
nss=$(find -L /usr/lib/$multiarch/ -mindepth 1 -maxdepth 1 \
	-name 'libnss_*.so.2' \
	! -regex '.*/libnss_\(compat\|dns\|files\|hesiod\)\.so\..' \
	-type f)
if [ -n "$nss" ]; then
    mkdir -p lib
    cp -pLuv -t lib -- $nss || :
    #XXX ldd?  We should have a way to load whole nss stuff before chroot(),
    #     and avoid all of this entirely
fi

case "$chroot_extra_CAdir" in # ensure CAdir is absolute
    ( /* ) ;;
    ( ?* ) chroot_extra_CAdir=/$chroot_extra_CAdir ;;
esac

# Copy certificate dirs
# There are 2 types of certs storage: ca-certificates.crt file (smtp_tls_CAfile)
# and a directory with xxxxxxxx.N files (smtp_tls_CAdir)
# It is best to use just CAfile (/etc/ssl/certs/ca-certificates.crt) which is read
# before chrooting, - usually it isn't large, and requires no processing.
# Can show a warning here suggesting to switch to smtp_tls_CAfile.
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 "$cadirs_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 hashed cert or ca-certificates.crt (#1003982) (to process later),
	# delete everything else..
	find . -mindepth 1 -maxdepth 1 \( \
		\( \( -name '[0-9a-f]*[0-9a-f].[0-9]' -o -name ca-certificates.crt \) -type f -print \) \
		-o -delete \
	    \) | while read file; do
		# ..and remove files which don't exist in source anymore
		[ -f "$cadir/$file" ] || rm -f "$file"
	    done
    ) fi
    find -L $cadir -maxdepth 1 -name '[0-9a-f]*.[0-9]' -type f \
	    -exec /usr/lib/postfix/syncfiles.pl $queue_directory '{}' +
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 || :
