Qmail
[Top] [All Lists]

DomainKey Shell Scripts

To: qmail@list.cr.yp.to
Subject: DomainKey Shell Scripts
From: Kyle Wheeler <kyle-qmail@memoryhole.net>
Date: Wed, 4 Apr 2007 22:36:08 -0600
Comment: DomainKeys? See http://domainkeys.sourceforge.net/
Delivered-to: sp-com-lists@consult.net
Delivered-to: gmail-qmail@securepoint.com
Delivered-to: sp.com.list@gmail.com
Delivered-to: mailing list qmail@list.cr.yp.to
Domainkey-signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=memoryhole.net; b=hfClng3GZ4pv6M16ebT9wjDf3xHPOsI4oG5QCzJY/vztyoxH3K8l3Q80iHl49yxr++Yf2fxJ+38gnsOt+vOEbBOVioQZ4YajQ5ZGieegXJBb7TIacS9G7ZBIPt0w3kuHraI7Eh3PX8m0nsgREJqNAbjd/8B3RcvLTULFKoB4h5o=; h=Received:Received:Date:From:To:Subject:Message-ID:Mail-Followup-To:MIME-Version:Content-Type:Content-Disposition:User-Agent;
Domainkey-status: good
Mail-followup-to: qmail@list.cr.yp.to
Mailing-list: contact qmail-help@list.cr.yp.to; run by ezmlm
User-agent: Mutt/1.5.14 (2007-04-03)
Hello,

I whipped up some shell scripts to do DomainKey verification and signing, using the dktest program that comes with libdomainkeys. The verifier is a qmail-queue wrapper, and the signer is a qmail-remote wrapper. They aren't *optimal*, because they use temporary files, rather than operating on just pipes. If you use `seek0`, you can avoid that, but I figured being general was better than adding more dependencies.

I've tested these scripts briefly, and they seem to work well. YMMV.

They do *not* block email based on DomainKey signature status; just tag. For blocking and/or using policy information, you'll have to modify them (for the sake of the rest of us, please post such modifications).

The first one is dkverifier.sh:

    #!/bin/sh
    [ "$DKQUEUE" ] || DKQUEUE=/var/qmail/bin/qmail-queue
    if printenv | grep -q '^DKVERIFY=' ; then
        tmp=`mktemp -t dk.verify.XXXXXXXXXXXXXXX`
        cat - >"$tmp"
        ( /usr/local/bin/dktest -v <"$tmp" 2>/dev/null | \
            /bin/awk 'NR>1'; /bin/cat "$tmp" ) | \
            $DKQUEUE
        retval=$?
        rm "$tmp"
        exit $retval
    else
        exec $DKQUEUE
    fi

The second one is a qmail-remote wrapper; it assumes that you've moved qmail-remote to qmail-remote.orig, and that this script is stored in /var/qmail/bin/qmail-remote. To set the environment variables to control this, add them to your qmail-send run script. The script is a little simplistic; it assumes all domains will be signed with the same key:

    #!/bin/sh
    [ "$DOMAIN" ] || DOMAIN=`head -n 1 /var/qmail/control/me`
    [ "$DKREMOTE" ] || DKREMOTE=/var/qmail/bin/qmail-remote.orig
    [ "$DKSIGN" ] || DKSIGN="/etc/domainkeys/$DOMAIN/default"
    tmp=`mktemp -t dk.sign.XXXXXXXXXXXXXXX`
    cat - >"$tmp"
    ( /usr/local/bin/dktest -s "$DKSIGN" -c nofws -h <"$tmp" \
        2>/dev/null | \
        /bin/sed 's/; d=.*;/; d='"$DOMAIN"';/'; \
        /bin/cat "$tmp" ) | \
        "$DKREMOTE" "$@"
    retval=$?
    rm "$tmp"
    exit $retval

We can add a little more intelligence to they key choice, at the expense of making it a little less readable (and bash-dependent).
Like so:

    #!/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 dk.sign.XXXXXXXXXXXXXXX`
        cat - >"$tmp"
        ( /usr/local/bin/dktest -s "$DKSIGN" -c nofws -h <"$tmp" \
            2>/dev/null | \
            /bin/sed 's/; d=.*;/; d='"$DOMAIN"';/'; \
            /bin/cat "$tmp" ) | \
            "$DKREMOTE" "$@"
        retval=$?
        rm "$tmp"
        exit $retval
    else
        exec "$DKREMOTE" "$@"
    fi

I hope that helps someone. :)

~Kyle
--
Those who do not understand Unix are condemned to reinvent it, poorly.
                                                      -- Henry Spencer

Attachment: pgpb0PjygUu0a.pgp
Description: PGP signature

<Prev in Thread] Current Thread [Next in Thread>