#! /bin/bash -e
# postinst script for zdkimfilter
# (use bash for arithmetic expantion)

# use dbconfig-common; see:
# https://www.debian.org/doc/manuals/dbconfig-common/ch-develguide.html
# The relevant install and upgrade files are created by the
# rule 'override_dh_auto_install' in debian/rules.
. /usr/share/debconf/confmodule
. /usr/share/dbconfig-common/dpkg/postinst.mysql

# debconf protocol 2.0
db_version 2.0
dbc_go zdkimfilter "$@"

# sysconfdir --courier-config must exist!
eval $(courier-config | grep -E '^(sysconfdir|libexecdir)')

# mail user and group (should use courier-config?)
mailuser="$(source ${sysconfdir}/esmtpd; echo "$MAILUSER")"
mailgroup="$(source ${sysconfdir}/esmtpd; echo "$MAILGROUP")"

CONFIGFILE=${sysconfdir}/filters/zdkimfilter.conf

# Write to stderr (not to confuse debconf)
OUTPUT="&2"
echo "zdkimfilter.postinst:" > $OUTPUT

db_get zdkimfilter/install-setuid
if [ "$RET" = true ]; then
	chown $mailuser:$mailgroup /usr/bin/zdkimsign
	chmod u+s /usr/bin/zdkimsign
	echo "setuid zdkimsign" >> $OUTPUT
fi
chown $mailuser:$mailgroup ${libexecdir}/filters/zdkimfilter

if [ "$1" = "configure" ]; then

	## List of files to be prepared under this condition:
	##  * a config file in /usr/share/zdkimfilter,
	##  * a script to trim database entries,
	##  * a script to send DMARC reports,
	##  * a DKIM signing key for the domain, and
	##  * a cron snippet to call dmarc_send.
	## --

	## a config file in /usr/share/zdkimfilter
	USRCONFIG=/usr/share/zdkimfilter/zdkimfilter.conf
	cat /usr/share/zdkimfilter/zdkimfilter.conf.orig.dist > $USRCONFIG

	# there are less pitfalls with relaxed canonicalization
	echo "header_canon_relaxed" >> $USRCONFIG
	echo "body_canon_relaxed" >> $USRCONFIG
	echo "" >> $USRCONFIG
	if [ "$dbc_install" = "true" ]; then
		echo "# DB" >> $USRCONFIG
		echo "#" >> $USRCONFIG

		# DB access, and prepare mysql args
		echo "db_backend mysql" >> $USRCONFIG
		chown $mailuser:$mailgroup $USRCONFIG
		chmod u=rw,go= $USRCONFIG

		if [ -z "$dbc_dbserver" ]; then
			dbc_dbserver=127.0.0.1
			mysql_args=""
		elif [ -s "$dbc_dbserver" ]; then
			# FIXME: does dbconfig support this? (OpenDBX does)
			mysql_args="--socket=$dbc_dbserver"
		else
			mysql_args="--host=$dbc_dbserver"
		fi
		echo "db_host $dbc_dbserver" >> $USRCONFIG

		if [ -n "$dbc_dbport" ]; then
			echo "db_port $dbc_dbport" >> $USRCONFIG
			mysql_args="$mysql_args --port=$dbc_dbport"
		fi

		echo "db_user $dbc_dbuser" >> $USRCONFIG
		mysql_args="$mysql_args --user=$dbc_dbuser"

		if [ -n "$dbc_dbpass" ]; then
			echo "db_password $dbc_dbpass" >> $USRCONFIG
			mysql_args="$mysql_args --password=$dbc_dbpass"
		fi

		echo "db_database $dbc_dbname" >> $USRCONFIG
		mysql_args="$mysql_args $dbc_dbname"

		# db_opt_multi_statements seems to be needed because of db_sql_insert_message
		echo "db_opt_multi_statements" >> $USRCONFIG
	fi

	# public suffix list
	echo "" >> $USRCONFIG
	echo "publicsuffix /usr/share/publicsuffix/effective_tld_names.dat" >> $USRCONFIG

	# mixed options not already present in the example
	echo "" >> $USRCONFIG
	echo "no_signlen" >> $USRCONFIG
	echo "key_choice_header from *" >> $USRCONFIG

	echo "" >> $USRCONFIG

	if [ "$dbc_install" = "true" ]; then
		echo "# DB SQL" >> $USRCONFIG
		echo "#" >> $USRCONFIG
		cat /usr/share/zdkimfilter/db_sql.conf >> $USRCONFIG
	fi

	ucf --debconf-ok --three-way $USRCONFIG $CONFIGFILE
	ucfr zdkimfilter $CONFIGFILE

	if [ "$dbc_install" = "true" ]; then
		## a script to trim database entries
		DELOLDSCRIPT=/etc/cron.daily/zdkimfilter
		echo "#! /bin/sh" > $DELOLDSCRIPT
		chown root:root $DELOLDSCRIPT
		chmod u=rw,go= $DELOLDSCRIPT

		echo "# delete old messages (not domains) from the database" >> $DELOLDSCRIPT
		echo "# incoming" >> $DELOLDSCRIPT
		echo "mysql $mysql_args <<EOQUERY" >> $DELOLDSCRIPT
		echo " DELETE r, m FROM msg_ref AS r, message_in AS m" >> $DELOLDSCRIPT
		echo " WHERE r.message_in = m.id AND" >> $DELOLDSCRIPT
		echo " m.mtime < UNIX_TIMESTAMP(NOW() - INTERVAL 1 MONTH);" >> $DELOLDSCRIPT
		echo "EOQUERY" >> $DELOLDSCRIPT
		echo "" >> $DELOLDSCRIPT
		echo "# outgoing" >> $DELOLDSCRIPT
		echo "mysql $mysql_args <<EOQUERY" >> $DELOLDSCRIPT
		echo " DELETE r, m FROM msg_out_ref AS r, message_out AS m" >> $DELOLDSCRIPT
		echo " WHERE r.message_out = m.id AND" >> $DELOLDSCRIPT
		echo " m.mtime < UNIX_TIMESTAMP(NOW() - INTERVAL 1 MONTH);" >> $DELOLDSCRIPT
		echo "EOQUERY" >> $DELOLDSCRIPT

		chmod u=rx,go= $DELOLDSCRIPT
		echo "Installed $DELOLDSCRIPT" >> $OUTPUT

		## a script to send DMARC reports
		DMARC_SEND=/usr/share/zdkimfilter/dmarc_send

		if [ -s ${sysconfdir}/defaultdomain ]; then
			org_domain=$(<${sysconfdir}/defaultdomain)
		elif [ -s ${sysconfdir}/dsnfrom ]; then
			org_domain=$(sed -nr 's/[^@]*@([^>]*).*/\1/p' ${sysconfdir}/dsnfrom)
		fi

		chmod a+x $DMARC_SEND
		if [ -n "$org_domain" ]; then
			# The "organization" item is usually set to the domain name
			# see https://us.dmarcian.com/dmarc-data-providers/
			sed -ri -e "s/example\.com/$org_domain/" \
				-e "s/This is an example/$org_domain/" $DMARC_SEND
			chown $mailuser:$mailgroup $DMARC_SEND
			chmod a+x $DMARC_SEND

			## a DKIM signing key for the domain
			# let size=1148 so that the whole string will be less than 256 bytes
			# a string length believed to be supported by all DNS tools.
			#
			if [ ! -f ${sysconfdir}/filters/keys/deb.private ]; then
				zdkimgenkey -D /usr/share/zdkimfilter -s deb -d $org_domain -b 1148
				mkdir -p ${sysconfdir}/filters/keys
				mv /usr/share/zdkimfilter/deb.private ${sysconfdir}/filters/keys
				chown $mailuser:$mailgroup ${sysconfdir}/filters/keys/deb.private
				if [ ! -f ${sysconfdir}/filters/keys/$org_domain ]; then
					ln -n -s -T deb.private "${sysconfdir}/filters/keys/$org_domain"
					unset unlinked
				else
					unlinked=" (not linked)"
				fi
				echo "Created DKIM signing key pair$unlinked in ${sysconfdir}/filters/keys" >> $OUTPUT
				echo "public key in /usr/share/zdkimfilter/deb.txt"  >> $OUTPUT
			fi

			## a cron snippet to call dmarc_send
			DMARCFILE=/etc/cron.d/zdkimfilter
			echo "# crontab fragment to send DMARC aggregate reports" > $DMARCFILE
			echo "# send reports once a day, somewhere after midnight UTC" >> $DMARCFILE
			echo "# if sending more often, set honored_report_interval in" >> $DMARCFILE
			echo "# $CONFIGFILE" >> $DMARCFILE
			echo "#" >> $DMARCFILE

			# compute a suitable time for a cron job after midnight UTC
			# check DST and use largest offset
			typeset -i summer winter after hour minute
			summer=$(date --date '2022/07/10' +%z |sed -rn 's/([-+])0{0,3}([0-9]*)/\1\2/p')
			winter=$(date --date '2022/01/10' +%z |sed -rn 's/([-+])0{0,3}([0-9]*)/\1\2/p')
			if test $summer -gt $winter ; then
				after=$summer
			else
				after=$winter
			fi

			# map [-1200, +1200] to [0, 2400]
			hour=$(($after/100))
			minute=$(($after%100))
			if test $after -lt 0 ; then
				let $((hour+=24)) || true
				if test $minute -lt 0 ; then
					let $((minute+=60)) || true
					let $((hour-=1)) || true
				fi
			fi

			# add some 15~45 minutes 
			let RANDOM=$(($(date +%s)%32767)) || true
			let minute+=$((15+$RANDOM%32767*30/32767)) || true
			if test $minute -ge 60 ; then
				let $((minute-=60)) || true
				let $((hour+=1)) || true
				if test $hour -ge 24; then
					hour=0
				fi
			fi

			echo "$minute $hour * * * $mailuser test ! -x $DMARC_SEND || $DMARC_SEND" >> $DMARCFILE
			echo "Installed $DMARCFILE"  >> $OUTPUT
		fi
	fi
fi

# It would seem to be a neat idea to enable filtering, since we're installing one.
# Is there a Debian policy about this?
if [ ! -e ${sysconfdir}/enablefiltering ]; then
	echo "esmtp" > ${sysconfdir}/enablefiltering
	chown $mailuser:$mailgroup ${sysconfdir}/enablefiltering
	echo "Mail filtering enabled" >> $OUTPUT
fi

# if we stopped filters, then restart them, otherwise run zdkimfilter anew
if [ -e ${sysconfdir}/filters/active/zdkimfilter ]; then
	courierfilter start
	echo "Courier filter started" >> $OUTPUT
else
	filterctl start zdkimfilter
	echo "Zdkimfilter enabled"  >> $OUTPUT
fi

# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.

#DEBHELPER#

exit 0

