1
0
mirror of https://blitiri.com.ar/repos/chasquid synced 2025-12-16 14:27:01 +00:00
Files
go-chasquid-smtp/etc/chasquid/hooks/post-data
Alberto Bertogli 270a071c1e hooks: Add dkimpy support
This patch adds support in the default hook for using dkimpy for DKIM
signing.

Unfortunately, dkimpy binaries have the same name as driusan/dkim's, so
we need to use --help to disambiguate. It's not pretty but it should
work, and is quite self contained.

Also, for the integration tests, we still need driusan/dkim because
dkimpy lacks the features needed. Specifically, dkimpy's dkimverify
can't be made to use custom DNS, or override the TXT values in any way,
so we can't verify that the generated signature is reasonable.

Thanks to ne9z@github for suggesting this change and providing an
alternative patch in https://github.com/albertito/chasquid/pull/19.
2021-07-21 02:06:20 +01:00

124 lines
3.7 KiB
Bash
Executable File

#!/bin/bash
#
# This file is an example post-data hook that will run standard filtering
# utilities if they are available.
#
# - greylist (from greylistd) to do greylisting.
# - spamc (from Spamassassin) to filter spam.
# - rspamc (from rspamd) or chasquid-rspamd to filter spam.
# - clamdscan (from ClamAV) to filter virus.
# - dkimsign (from driusan/dkim or dkimpy) to do DKIM signing.
#
# If it exits with code 20, it will be considered a permanent error.
# Otherwise, temporary.
set -e
# Note greylistd needs you to add the user to the "greylist" group:
# usermod -a -G greylist mail
if [ "$AUTH_AS" == "" ] && [ "$SPF_PASS" == "0" ] && \
command -v greylist >/dev/null && \
groups | grep -q greylist;
then
REMOTE_IP=$(echo "$REMOTE_ADDR" | rev | cut -d : -f 2- | rev)
if ! greylist update "$REMOTE_IP" "$MAIL_FROM" 1>&2; then
echo "greylisted, please try again"
exit 75 # temporary error
fi
echo "X-Greylist: pass"
fi
TF="$(mktemp --tmpdir post-data-XXXXXXXXXX)"
trap 'rm "$TF"' EXIT
# Save the message to the temporary file, so we can pass it on to the various
# filters.
cat > "$TF"
if command -v spamc >/dev/null; then
if ! SL=$(spamc -c - < "$TF") ; then
echo "spam detected"
exit 20 # permanent
fi
echo "X-Spam-Score: $SL"
fi
# Spam filter through rspamd.
#
# Use chasquid-rspamd (from https://github.com/Thor77/chasquid-rspamd) if
# available, otherwise fall back to rspamc.
if command -v chasquid-rspamd >/dev/null; then
chasquid-rspamd < "$TF" 2>/dev/null
elif command -v rspamc >/dev/null; then
# Note the actions emitted by rspamc come from the thresholds
# configured in /etc/rspamd/actions.conf.
# The ones handled here are common defaults, but they might require
# adjusting to match your rspamd configuration.
# Note that greylisting is disabled in rspamc by design, so the
# "greylist" action is ignored here to prevent false rejections.
ACTION=$( rspamc < "$TF" 2>/dev/null | grep Action: | cut -d " " -f 2- )
case "$ACTION" in
reject)
echo "spam detected"
exit 20 # permanent error
;;
esac
echo "X-Spam-Action:" "$ACTION"
fi
if command -v clamdscan >/dev/null; then
if ! clamdscan --no-summary --infected - < "$TF" 1>&2 ; then
echo "virus detected"
exit 20 # permanent
fi
echo "X-Virus-Scanned: pass"
fi
# DKIM sign with either driusan/dkim or dkimpy.
#
# Do it only if all the following are true:
# - User has authenticated.
# - dkimsign binary exists.
# - domains/$DOMAIN/dkim_selector file exists.
# - certs/$DOMAIN/dkim_privkey.pem file exists.
#
# Note this has not been thoroughly tested, so might need further adjustments.
if [ "$AUTH_AS" != "" ] && command -v dkimsign >/dev/null; then
DOMAIN=$( echo "$MAIL_FROM" | cut -d '@' -f 2 )
if [ -f "domains/$DOMAIN/dkim_selector" ] \
&& [ -f "certs/$DOMAIN/dkim_privkey.pem" ];
then
# driusan/dkim and dkimpy both provide the same binary (dkimsign) but
# take different arguments, so we need to tell them apart.
# This is awful but it should work reasonably well.
if dkimsign --help 2>&1 | grep -q -- --identity; then
# dkimpy
dkimsign \
"$(cat "domains/$DOMAIN/dkim_selector")" \
"$DOMAIN" \
"certs/$DOMAIN/dkim_privkey.pem" \
< "$TF" > "$TF.dkimout"
# dkimpy doesn't provide a way to just show the new
# headers, so we have to compute the difference.
# ALSOCHANGE(test/t-19-dkimpy/config/hooks/post-data)
! diff --changed-group-format='%>' \
--unchanged-group-format='' \
"$TF" "$TF.dkimout"
rm "$TF.dkimout"
else
# driusan/dkim
dkimsign -n -hd \
-key "certs/$DOMAIN/dkim_privkey.pem" \
-s "$(cat "domains/$DOMAIN/dkim_selector")" \
-d "$DOMAIN" \
< "$TF"
fi
fi
fi