#!/bin/bash
# version 6
PATH=/bin:/usr/bin:/usr/local/bin
shopt -q -s extglob
host="$1"
sender="$2"
dktest="`which dktest`"
dkimsign="`which dkimsign.pl 2>/dev/null`"
senderroutes=/var/qmail/control/senderroutes
# We want to prevent bounce messages to remote receipients
if [ "$sender" == "" ]; then
echo -e "KDropping remote bounce message to prevent backscatter.\0"
exit 0
fi
# First, figure out who the sending domain is:
[[ -z "$sender" && "$DEFAULTDOMAIN" ]] && sender="@$DEFAULTDOMAIN"
[ -z "$sender" ] && sender=@`hostname -f`
DOMAIN="${sender##*@}"
# Sanity-check the sender
#if [[ $DOMAIN == !(+([a-zA-Z0-9\!\#$%*/?|^{}\`~&\'+=_.-])) ]] ; then
# ' fix vim quote logic
# echo "DSender address contains illegal characters."
# exit 0
#fi
#Check for sender routes
if [ -f $senderroutes ]; then
if grep -q "^$DOMAIN:" $senderroutes ; then
host=`awk -F: "/^$DOMAIN:/{print \\$2}" $senderroutes`
set -- "$host" "${@:2:3}"
msg="Sender routes redirected message to $host"
fi
fi
# Now, fill in the basic variables (if they don't exist already)
[ "$DKREMOTE" ] || DKREMOTE="/var/qmail/bin/qmail-remote.orig"
[ "$DKSIGN" ] || DKSIGN="/etc/domainkeys/%/default"
# Now try and find the right subdomain, per RFC 4871
# (you can eliminate this loop if you don't want parent domains signing child
# domain's email)
if [ "$DOMAIN" ] ; then
while [ ! -r "${DKSIGN//\%/$DOMAIN}" ] && [ "$DOMAIN" != "" ]; do
# try parent domains, per RFC 4871, section 3.8
# Old/new length check filters out mangled senders and prevents
# this loop from getting stuck.
old_length=${#DOMAIN}
DOMAIN=${DOMAIN#*.}
new_length=${#DOMAIN}
[ "$old_length" == "$new_length" ] && DOMAIN="${sender##*@}" && break
DPARTS=( ${DOMAIN//./ } )
[ ${#DPARTS[*]} -eq 1 ] && DOMAIN="${sender##*@}" && break
done
fi
DKSIGN="${DKSIGN//\%/$DOMAIN}"
# Now that we have the correct DKSIGN value (i.e. the filename of the key to
# use to sign email), check to see if this file exists
if [ -r "$DKSIGN" ] ; then
# The key does exist, so now use it to generate signatures!
tmp=`mktemp -t dk.sign.XXXXXXXXXXXXXXXXXXX`
tmp2=`mktemp -t dk2.sign.XXXXXXXXXXXXXXXXXXX`
cat - >"$tmp"
# compute the DomainKey signature
error=`($dktest -s "$DKSIGN" -c nofws -h <"$tmp" | \
sed 's/; d=.*;/; d='"$DOMAIN"';/' > "$tmp2") 2>&1`
if [ "$error" ] ; then
# Communicate the problem to qmail (that's why the 'Z')
echo "ZDomainKey error: $error"
rm "$tmp" "$tmp2"
exit -1
fi
if [[ "$dkimsign" != "" ]]; then
# compute the DKIM signature
error=`($dkimsign --type=dkim --selector=default --domain="$DOMAIN" \
--key="$DKSIGN" --method=relaxed <"$tmp" | \
tr -d '\r' >> "$tmp2") 2>&1`
if [ "$error" ] ; then
# Communicate the problem to qmail (that's why the 'Z')
echo "ZDKIM error: $error"
rm "$tmp" "$tmp2"
exit -2
fi
fi
# feed the signatures and the original message to the real qmail-remote
# I'm combining to a third temp file to allow the file to be "rewound",
# since some folks like that ability
tmp3=`mktemp -t dk3.sign.XXXXXXXXXXXXXXXXXXX`
cat "$tmp2" "$tmp" > "$tmp3"
rm "$tmp" "$tmp2"
"$DKREMOTE" "$@" < "$tmp3" | sed 's/\x0$/ /'
retval=$?
printf "$msg\0"
rm "$tmp3"
exit $retval
else
# No signature added
"$DKREMOTE" "$@" | sed 's/\x0$/ /'
printf "$msg\0"
fi
|