I've finally sat down and taken the time to get a TMDA fingprint
checker working. 99% of it is pure theivery from the tmda-inject code.
(Which is why I left Jason's original copyright in there.)
The purpose of this program is to allow me to take my own email address
out of my whitelists. I'm in my own whitelists because I like to send
myself email. Unfortunately, I've been getting a few spam here and there
that are using my own email address as the from/sender address. This is
getting past TMDA because I'm in my own whitelist.
So I wanted a way to verify that when I send myself email, I'm really me.
Jason gave me the idea of using X-TMDA-Fingerprint as that mechanism.
In order to generate a correct X-TMDA-Fingerprint, I must have access to
my ~/tmda/crypt_key file. So any email that comes in from me with a valid
X-TMDA-Fingerprint header, must have been sent *by* me and not a spammer.
So that's the basic idea. Unfortunately, the only way that I could
think of to get this to work is using procmail. I've put some dumb code
in there for the non-procmail situations, but I don't honestly know
how to integrate this thing w/out procmail. So, I've also attached
my .procmailrc. I know most of the qmail'ers on the list won't want
to pursue using procmail. So, I'm submitting this to tmda-workers for
constructive criticism and/or suggestions on how this might be made to
work more generically.
This is a pretty simple thing. All it does is check X-TMDA-Fingerprint
in the original message. Then it recalculates it. If the recalculated
fingerprint matches the original fingerprint, then it creates a
new header, X-TMDA-Fingerprint-Match, and sets it to "Yes". If the
fingerprints don't match, then it sets that header to "No".
So what you have to do to get this to work, is as follows:
1) You MUST have outgoing email pass through TMDA
2) Set the FINGERPRINT variable in ~/.tmda/config. See Defaults.py
for more details.
3) Configure procmail to accept email with the header:
X-TMDA-Fingerprint-Match: Yes
Cheers,
- Mark
P.S. There is one caveat: when setting FINGERPRINT, I'd avoid using
"body". When I had it set, there was something that would occasionally
(but not all the time) append an extra CRLF at the end of my email body,
after the original fingerprint calculation was done. This would, of
course, cause the fingerprint verification to occasionally fail... but
not always. If I were to guess at the culprit I'd blame postfix (my MTA).
But I don't actually know what's doing it.
#!/usr/bin/env python
#
# Copyright (C) 2001,2002 Jason R. Mastaler <[EMAIL PROTECTED]>
# Modifications made by Mark Horn to make a fingerprint checker
#
# This file is part of TMDA.
#
# TMDA is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version. A copy of this license should
# be included in the file COPYING.
#
# TMDA is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with TMDA; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Tag and send outgoing messages.
Usage: %(program)s [OPTIONS]
OPTIONS:
-h
--help
Print this help message and exit.
-V
--version
Print TMDA version information and exit.
-c <file>
--config-file <file>
Specify a different configuration file other than ~/.tmda/config.
-p
--procmail
Use with procmail. The message will be sent to standard output
with an additional header (X-TMDA-Fingerprint-Match) set to
"Yes" if the fingerprints match and "No" if they don't.
"""
import getopt
import os
import sys
try:
import paths
except ImportError:
# Prepend /usr/lib/python2.x/site-packages/TMDA/pythonlib
sitedir = os.path.join(sys.prefix, 'lib', 'python'+sys.version[:3],
'site-packages', 'TMDA', 'pythonlib')
sys.path.insert(0, sitedir)
from TMDA import Version
procmail = None
program = sys.argv[0]
def usage(code, msg=''):
print __doc__ % globals()
if msg:
print msg
sys.exit(code)
try:
opts, args = getopt.getopt(sys.argv[1:],
'c:Vhp', ['config-file=',
'version',
'help',
'procmail'])
except getopt.error, msg:
usage(1, msg)
for opt, arg in opts:
if opt in ('-h', '--help'):
usage(0)
if opt == '-V':
print Version.ALL
sys.exit()
if opt == '--version':
print Version.TMDA
sys.exit()
elif opt in ('-c', '--config-file'):
os.environ['TMDARC'] = arg
elif opt in ('-p', '--procmail'):
procmail = 1
from TMDA import Defaults
from TMDA import Cookie
from TMDA import Util
import email
import string
msgout = email.message_from_file(sys.stdin)
orig_msgout_as_string = msgout.as_string()
orig_msgout_size = len(orig_msgout_as_string)
orig_msgout_body_as_raw_string = Util.body_as_raw_string(msgout)
orig_fingerprint = msgout.get("X-TMDA-Fingerprint")
if procmail:
del msgout['X-TMDA-Fingerprint-Match']
if Defaults.FINGERPRINT:
hdrlist = []
for hdr in Defaults.FINGERPRINT:
if hdr == 'body':
hdrval = orig_msgout_body_as_raw_string
else:
hdrval = msgout.get(hdr)
if hdrval:
hdrlist.append(hdrval)
if hdrlist:
new_fingerprint = Cookie.make_fingerprint(hdrlist)
if orig_fingerprint == new_fingerprint:
if procmail:
msgout['X-TMDA-Fingerprint-Match'] = "Yes"
print msgout
else:
print "Fingerprints match"
else:
if procmail:
msgout['X-TMDA-Fingerprint-Match'] = "No"
print msgout
else:
print "Fingerprints don't match"
sys.exit(-1)
PATH="/home/mark/ftpin/tmda/cvs/tmda/bin:$PATH"
# TMDA takes care of final delivery
DEFAULT=/dev/null
:0
* ^From.*mark.*@hornclan.com
{
:0fw
|$HOME/tmdacvs/bin/tmda-fingerprint -p
:0
* ^X-TMDA-Fingerprint-Match:.Yes
$HOME/Maildir/
:0
$HOME/Maildir/.SPAM/
}
# Run the message through tmda-filter.
:0w
| /home/mark/ftpin/tmda/cvs/tmda/bin/tmda-filter
# Take the exit code from TMDA.
EXITCODE=$?