-
Notifications
You must be signed in to change notification settings - Fork 0
/
qmail-sdkim.sh
95 lines (84 loc) · 4.11 KB
/
qmail-sdkim.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#********************************************************************************
# DKIM signing for openqmail/eQmail/(net)qmail & derivatives #
# #
# Author: Kai Peter, ©2013-©2017 (kp@openqmail.org) #
# (based on work by Joerg Backschues & Kyle Wheeler) #
# Version: 0.58 #
# Licence: See LICENSE file #
# #
# Description: Add DKIM signature to outgoing messages #
#********************************************************************************
shopt -q -s extglob
PATH="QMAILHOME/bin:$PATH"
HOST="$1" # recipient host (will never used below)
SENDER="$2" # HAVE TO be valid!
# check for config file and include it
[ -f "QMAILHOME/etc/qdkim.conf" ] && . "QMAILHOME/etc/qdkim.conf"
# these files HAVE TO exists from *qmail, else - bummer
# (Hint: if 'qmail-remote' was renamed, set it in config file!)
[ -f "$QMAILREMOTE" ] || QMAILREMOTE=`dirname $0`"/qmail-remote"
# do not use 'test -f' because $LOGGER could have params
[ "$LOGGER" ] || LOGGER="QMAILHOME/bin/splogger"
[ "$DOSIGN" ] || DOSIGN=0 # have to be initialized
DelTmpFiles() { rm -f "$InMsg" "$OutMsg"; }
DoLog() { echo "$LogMsg" | "$LOGGER" qmail-dkim; }
# Important: After the message was signed, send it immediatily!
DoSend() { exec "$QMAILREMOTE" "$@"; exit 0; }
# just for backwards compatibility, but libqdkim is recommended
[ "$DKLIB" ] || DKLIB="QMAILHOME/bin/libqdkim"
if [ ! -f "$DKLIB" ] && [ "$DOSIGN" = "1" ] ; then
# print a warning, but send the message w/o signature
LogMsg="warning: couldn't find $DKLIB - message not signed!"
DoLog ; DOSIGN=0; fi
# if $DOSIGN is NOT set, then signing is disabled at all
if [ ! "$DOSIGN" = "1" ] ; then DoSend "$@" ; fi
# wildcard path to the DKIM/domain keys
[ "$DKSIGN" ] || DKSIGN="QMAILHOME/etc/dkimkeys/%/default"
GetSender() {
# get domainpart of sender ("$DEFAULTDOMAIN" have to be set by *qmail)
[[ -z "$SENDER" && "$DEFAULTDOMAIN" ]] && SENDER="@$DEFAULTDOMAIN"
[ -z "$SENDER" ] && SENDER=@`hostname -f`
DOMAIN="${SENDER##*@}"
# sanity-check of the sender - abort sending on failure (RfC 2049)
# (seems to be a bit outdated(?) as of internationalization (IDN's))
if [[ $DOMAIN = !(+([a-zA-Z0-9\!\#$%*/?|^{}\`~&\'+=_.-])) ]] ; then
LogMsg="alert: Address $SENDER contains illegal characters."
DoLog ; exit 0 ; fi # log and don't send
}
SubDomain() {
if [ "$DOMAIN" ] ; then
# try parent domains
while [ ! -r "${DKSIGN//\%/$DOMAIN}" ] ; do
DOMAIN=${DOMAIN#*.}
DPARTS=( ${DOMAIN//./ } )
[ ${#DPARTS[*]} -eq 1 ] && DOMAIN="${SENDER##*@}" && break
done
fi
DKSIGN="${DKSIGN//\%/$DOMAIN}"
}
GetSender
SubDomain
# last try to get the domainkey file (if function SubDomain fails)
if [[ $DKSIGN = *%* ]] ; then DKSIGN="${DKSIGN%%%*}${DOMAIN}${DKSIGN#*%}" ; fi
# the signing process itself ****************************************************
if [ -f "$DKSIGN" ] ; then
[ -d "QMAILHOME/tmp" ] && TMPDIR="QMAILHOME/tmp" || TMPDIR="/tmp"
InMsg=`mktemp -p "$TMPDIR" -t sdkim.XXXXXXXXXXXXXXX`
OutMsg=`mktemp -p "$TMPDIR" -t sdkim.XXXXXXXXXXXXXXX`
# sign the message: add CRLF ("\r\n") to every line of the message before
cat - | sed 's/$'"/`echo \\\r`/" >"$InMsg"
FLDR=`dirname $DKSIGN` # needed for file 'selector' below
# this works (in most cases) fine (even with libdkim-1.0.21):
$DKLIB -y`cat $FLDR/selector` -d"$DOMAIN" -i"$SENDER" \
-l -b2 -ct -z2 -s "$InMsg" "$DKSIGN" "$OutMsg" 2>/dev/null
# remove 'CR' and handover to (real) qmail-remote (do 'tr -d' in any case!!!)
(cat "$OutMsg" | tr -d '\015') | DoSend "$@"
EC=$?
DelTmpFiles
# write to system log
LogMsg="created DKIM signature for $2 ($DOMAIN)" ; DoLog
exit $EC
else # no domainkey found for (sub)domain
LogMsg="No DKIM key found for $2" ; DoLog
DoSend "$@"
fi