qmail and DKIM

May 4, 2007 · Posted in Email, security 

DomainKeys Identified Mail (DKIM) is a method for validating the identity associated with a message using using public-key cryptography and key server technology. DKIM is an enhanced version of Yahoo's Domain Keys and Cisco's Identified Internet Mail methods. As of February 2007 an IETF draft was accepted as "Proposed standard", it may take some more time till this will be a standard but the current version is stable ( according to dkim.org ).

Implementations of DKIM in email servers is not available as much as DomainKeys.
For qmail there is a patch that uses libdomainkeys to implement a replacement for qmail-queue that will verify and sign messages but this only works for DomainKeys not DKIM. I have developed a solution for qmail to be able to verify and sign messages with DKIM.

My solution was inspired by a post on the qmail list http://article.gmane.org/gmane.mail.qmail.general/52049 that used two shell scripts one as a qmail-queue wrapper for verifying the messages and one as a qmail-remote wrapper for signing the messages. Both scripts call dktest, a test program that comes with libdomainkeys, to do the signing and verification.

Libdkim is a portable implementation of the DKIM drafts and it comes with a test program, libdkimtest somehow similar to dktest so I'm using this to do the signing and verification.

Although libdkim developers claim it is portable it needed some patching to make it compile on Linux, mainly some macro definitions that are only available in windows header files. I found those definitions in a file macros.h from mono and I added it to libdkim's source and included it in dkim.h .

I also added some small features and enhancements like a help / usage message for libdkimtest, the ability to specify the domain and selector in the command line. I removed some hard coded defaults that blocked options specified on the command line and I made it be able to process messages that had bare LF as line terminators instead of CR/LF.

The shell scripts that used dktest also needed some small modifications because libdkimtest does not read the message on it's standard input and it does not output the message to the standard output.

Here is the shell script that does the verification:

#!/bin/sh
 
[ "$DKIMQUEUE" ] || DKIMQUEUE="/var/qmail/bin/qmail-dk"
 
if printenv | grep -q '^DKIMVERIFY=' ; then
 
tmp=`mktemp /tmp/dkim.verify.XXXXXXXXXXXXXXX`
tmp2=`mktemp /tmp/dkim.verify.XXXXXXXXXXXXXXX`
cat - > "$tmp"
 
/usr/local/bin/libdkimtest -v "$tmp"  > "$tmp2" 2> /dev/null
 
(
if [ "$(cat "$tmp2"|grep "Success")" != "" ] ; then
echo "DKIM-Status: good"
else
if [ "$(cat "$tmp2"|grep "Fail")" != "" ] ; then
echo "DKIM-Status: failed"
fi
fi
) | /bin/cat - "$tmp" | $DKIMQUEUE
retval=$?
rm "$tmp" "$tmp2"
exit $retval
else
exec $DKIMQUEUE
fi

This should replace qmail-queue and to make it verify the messages you have to set the DKIMVERIFY environmental variable. This script calls qmail-dk because I want to also verify the DomainKeys signature.

and here is the script that should replace qmail-remote:

#!/usr/local/bin/bash
 
[ "$DKSIGN" ] || DKSIGN="/etc/domainkeys/%/default"
[ "$DKREMOTE" ] || DKREMOTE="/var/qmail/bin/qmail-remote.orig"
 
if [[ $DKSIGN == *%* ]] ; then
DOMAIN=${2##*@}
DKSIGN="${DKSIGN%%%*}${DOMAIN}${DKSIGN#*%}"
fi
if [ -f "$DKSIGN" ] ; then
tmp=`mktemp -t dkim.sign.XXXXXXXXXXXXXXX`
tmp2=`mktemp -t dkim.sign.XXXXXXXXXXXXXXX`
 
/bin/cat - > "$tmp"
/usr/local/bin/libdkimtest -ydefault -s "$tmp" "$DKSIGN" "$tmp2" 2> /dev/null
 
(/bin/cat "$tmp2" |tr -d "\\015") | "$DKREMOTE" "$@"
retval=$?
rm "$tmp" "$tmp2"
exit $retval
else
exec "$DKREMOTE" "$@"
fi

copy qmail-remote to qmail-remote.orig and then name this script qmail-remote

get libdkim, unzip it, get these patches : libdkim linux compile patch and libdkim extra options patch

and apply then like this

cd libdkim
patch -p1 < libdkim.patch
patch -p1 < libdkim2.patch
 
cd src
make LINUX=y
cp libdkimtest /usr/local/bin
 

If you had qmail-dk working before then the scripts will just use the private keys in /etc/domainkeys/{domain_name}/default just like qmail-dk .

Update:

because some people had troubles applying the patches to newer versions of libdkim I have added the patched source code here: libdkim-patched.tar.gz

It would still be a good idea to patch the newer versions and I might do that when I find some time.

Comments

100 Comments

    Leave a Reply




    Trackbacks/Pingbacks