Attached you will find my updated vpopmail spamassassin userprefs patch.. now
with superior vpop domain detection powers ;) thanks to the vpopmail perl
module. http://search.cpan.org/search?module=vpopmail you no longer have to
specify your vpopmail domains at ./configure time. Any vpopdomains will be
automatically added on the end of --local-domains at runtime.
This patch allows per-user configuration rules for spamassassin. It
supports real as well as virtual domains (via vpopmail). .qmail aliases
can also be aliased to the real account so that only one set of rules needs
to be maintained.
I have also included the patch from Chris Hine which adds support for ripmime
(http://pldaniels.com/ripmime/) as a configure option. This is based on a
patch written by MURATA Nobuhiro and sent to the list in November last year.
It defaults to current behaviour, but if you specify
"--mime-unpacker ripmime" on the ./configure line, ripmime" is used. If
ripmime is used tnef is no longer detected as ripmime includes tnef support.
It has only been tested with user-prefs stored in mysql database (but other
ways "should" work ;) ). I use mysql for storing SA user-prefs because it
makes it easy for all my users to come in thru a PHP page and change their
prefs. (If any one is interesed I have adapted the php-sa pages to be a
SquirrelMail plugin http://www.squirrelmail.org).
I personally disable the sitewide AWL cause all I need is one user doing
"blacklist_from *.com" to make a huge mess of things.
It grabs the username to pass to spamc from the RCPTTO:
* Note that broken spammers do things like:
RCPTTO: [EMAIL PROTECTED],[EMAIL PROTECTED],[EMAIL PROTECTED]
and this will be parsed incorrectly, not that it matters cause qmail will
bounce this anyways.
In addition to checking for RELAYCLIENT to see if message should be
scanned, now also checks QMAILLOCALUSER. This is to prevent outgoing mail
sent via the shell from being scanned. QMAILLOCALUSER should be set in the
/etc/profile or in a script in /etc/profile.d
Patch to qmail-scanner-1.15 and run ./configure .. it "should work"
The --vpopmail-domains option is depricated instead use --use-vpop:
--use-vpop [yes|no] Defaults to "no". Enable VPOP domain support for
SpamAssassin. You will need the vpopmail module from
CPAN for this to work:
http://search.cpan.org/search?module=vpopmail
This controls the behavior of SpamAssassin's user prefs any mail checked
for a vpopmail domain SA will be passed -u "[EMAIL PROTECTED]" all
other domains SA will only be passed -u "user".
To do alias mappings see the example qmail-scanner-aliases file that is
included, create a /var/qmail/users/qmail-scanner-aliases file to suit your
own needs, make sure it is chown qmailq and chmod 0600, this is because
there is basically almost no sanity checks on this file ;) and potentially
using this file you can pass spamc extra arguments.. maybe.. could be a
security hazard.
What is really needed is a suid program that does the sanity checking and
adds and removes line in this file. If you look at the example
qmail-scanner-aliases file you will see why the sanity checking should be
in another program.. too much over head ;)
This patch has only been tested on a couple servers and no warranty is
expressed or implied.. basically Works-for-Me(TM)
Questions/comments should be forwarded to "wwong at blackstar.net"
-Wilton
----[ Wilton William Wong ]---------------------------------------------
16127-57 Street Ph : 01-780-456-0344
Edmonton, Alberta FAX: 01-780-456-0344 Cell: 01-780-975-2880
T5Y 2T1, Canada URL: https://www.blackstar.net/
---------------------------------------------[ BlackStar Communications ]----
diff -ruN qmail-scanner-1.15/configure qmail-scanner-1.15.vpopmail/configure
--- qmail-scanner-1.15/configure Tue Oct 29 17:44:37 2002
+++ qmail-scanner-1.15.vpopmail/configure Fri Nov 22 02:16:43 2002
@@ -73,6 +73,7 @@
QMAILDIR="/var/qmail"
BINDIR="$QMAILDIR/bin"
QMAILQUEUE_BIN="$BINDIR/qmail-queue"
+USE_VPOP="0"
ARCHIVEIT="0"
ARCHIVEDIR="archives"
REDUNDANT="0"
@@ -106,7 +107,9 @@
--log-details) LOG_DETAILS="0" ; if [ "$2" != "" -a "`echo $2|grep '\-'`" =
"" ] ; then shift ; LOG_DETAILS="$1" ; fi ;;
--fix-mime) FIX_MIME=1 ; if [ "$2" != "" -a "`echo $2|grep '\-'`" = "" ] ;
then shift ; if [ "`echo $1|egrep -i '^1|^yes'`" = "" ]; then FIX_MIME="1" ; fi ; if
[ "`echo $1|egrep -i '^0|^no'`" != "" ]; then FIX_MIME="0" ; fi ; fi ;;
--no-QQ-check) MANUAL_INSTALL="1";;
+ --use-vpop) USE_VPOP=1 ; if [ "$2" != "" -a "`echo $2|grep '\-'`" = "" ] ;
+then shift ; if [ "`echo $1|egrep -i '^1|^yes'`" = "" ]; then USE_VPOP="1" ; fi ;
+if [ "`echo $1|egrep -i '^0|^no'`" != "" ]; then USE_VPOP="0" ; fi ; fi ;;
--qmail-queue-binary) if [ "$2" != "" ] ; then shift ; fi ;
QMAILQUEUE_BIN="$1" ;;
+ --mime-unpacker) if [ "$2" != "" ] ; then shift ; fi ; MIME_UNPACKER="$1" ;;
--install) INSTALLIT="1" ; if [ "$2" != "" -a "`echo $2|grep '\-'`" = "" ] ;
then shift ; fi ;;
*) cat <<EOF >&2
invalid option: $1
@@ -163,6 +166,10 @@
$SILENT_VIRUSES
--lang "$LANGUAGES"
Defaults to $QSLANG.
+ --use-vpop [yes|no] Defaults to "no". Enable VPOP domain support for
+ SpamAssassin. You will need the vpopmail module from
+ CPAN for this to work:
+ http://search.cpan.org/search?module=vpopmail
--archive [yes|no] Defaults to "no". Whether to archive mail after
it as been processed. If "yes", all copies of
processed mail will be moved into the maildir
@@ -189,6 +196,7 @@
by default to help perlscanner.
--install Create directory paths, install perl script,
and change ownerships to match.
+ --mime-unpacker "reformime|ripmime" Defaults to reformime. Allow ripmime.
****************
Rarely Used
@@ -297,6 +305,28 @@
PATH="$PATH:$QMAILDIR/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/etc/iscan:/usr/local/uvscan:/usr/lib/AntiVir:/usr/lib/uvscan:/usr/local/av:/opt/AV:/opt/AVP:/usr/local/f-prot:/usr/local/rav8/bin"
export PATH
+if [ "$MIME_UNPACKER" != "" ]; then
+ if [ "`echo $MIME_UNPACKER |egrep -v '^(reformime|ripmime)$'`" != "" ]; then
+ cat<<EOF
+
+
+ *************************
+
+Sorry, but your "--mime-unpacker" definition contains invalid options.
+
+The only valid options are:
+
+reformime
+ripmime
+
+ **************************
+EOF
+ exit
+ fi
+else
+ MIME_UNPACKER="reformime"
+fi
+
NOTIFY_ADDRESSES="`echo $NOTIFY_ADDRESSES|sed -e 's/\"//g' -e 's/ //g'`"
if [ "$NOTIFY_ADDRESSES" = "all" ]; then
@@ -411,14 +441,15 @@
STRINGS="${STRINGS:-$dir/strings}"
fi
+if [ "$MIME_UNPACKER" = "reformime" ]; then
if test -x $dir/reformime
then
- REFORMIME_BINARY="${REFORMIME_BINARY:-$dir/reformime}"
+ UNMIME_BINARY="${UNMIME_BINARY:-$dir/reformime}"
DD=`reformime -s1.2 -xTEST- < ./contrib/reformime-test.eml`
if [ "`grep hello TEST-hello.txt`" = "" ]; then
echo "** FATAL ERROR ***"
echo ""
- echo "$REFORMIME_BINARY contains bugs. Please upgrade to a release"
+ echo "$UNMIME_BINARY contains bugs. Please upgrade to a release"
echo "that post-dates Mar 22 2002 (e.g. 1.3.8)"
echo ""
rm -f TEST-hello.txt
@@ -430,19 +461,6 @@
then
MAILDROP_BINARY="${MAILDROP_BINARY:-$dir/maildrop}"
fi
- if test -x $dir/unzip
- then
- UNZIP_BINARY="${UNZIP_BINARY:-$dir/unzip}"
- #Now check for password support
- touch file.zip
- DD=`unzip -Pxxxxx file.zip 2>&1|grep '^Archive:'`
- if [ "$DD" != "" ]; then
- UNZIP_OPTIONS="-Pxxxxx"
- else
- UNZIP_OPTIONS=""
- fi
- rm -f file.zip
- fi
if test -x $dir/tnef
then
TNEF_BINARY="${TNEF_BINARY:-$dir/tnef}"
@@ -462,7 +480,38 @@
exit 1
fi
LANG=$OLD_LANG export LANG
+ fi
+fi
+if [ "$MIME_UNPACKER" = "ripmime" ]; then
+ if test -x $dir/ripmime
+ then
+ UNMIME_BINARY="${UNMIME_BINARY:-$dir/ripmime}"
+ DD=`ripmime -i - < ./contrib/reformime-test.eml`
+ if [ "`grep hello hello.txt`" = "" ]; then
+ echo "** FATAL ERROR ***"
+ echo ""
+ echo "$UNMIME_BINARY contains bugs. Please upgrade to a newer release."
+ echo ""
+ rm -f hello.txt textfile*
+ exit 1
+ fi
+ rm -f hello.txt textfile*
+ fi
+fi
+ if test -x $dir/unzip
+ then
+ UNZIP_BINARY="${UNZIP_BINARY:-$dir/unzip}"
+ #Now check for password support
+ touch file.zip
+ DD=`unzip -Pxxx file.zip 2>&1|grep '^Archive:'`
+ if [ "$DD" != "" ]; then
+ UNZIP_OPTIONS="-Pxxxxx"
+ else
+ UNZIP_OPTIONS=""
+ fi
+ rm -f file.zip
fi
+
if test -x $dir/uvscan
then
if [ "`echo $FIND_SCANNERS|grep ' uvscan '`" != "" ]; then
@@ -773,7 +822,7 @@
MAILDOMAIN=${MAILDOMAIN:-$FQDN}
LOCAL_DOMAINS_ARRAY=${LOCAL_DOMAINS_ARRAY:-$MAILDOMAIN}
-CMDLINE="$0 --spooldir $AS_QQ --qmaildir $QMAILDIR --bindir $BINDIR
--qmail-queue-binary $QMAILQUEUE_BIN --admin $USERNAME --domain $MAILDOMAIN --notify
$NOTIFY_ADDRESSES --local-domains $LOCAL_DOMAINS_ARRAY --silent-viruses
$SILENT_VIRUSES --lang $QSLANG --debug $DEBUG_LEVEL --unzip $FORCE_UNZIP
--add-dscr-hdrs $DESCRIPTIVE_HEADERS --archive $ARCHIVEIT --redundant $REDUNDANT
--log-details $LOG_DETAILS --fix-mime $FIX_MIME --scanners \"$SCANNERS\""
+CMDLINE="$0 --spooldir $AS_QQ --qmaildir $QMAILDIR --bindir $BINDIR
+--qmail-queue-binary $QMAILQUEUE_BIN --admin $USERNAME --domain $MAILDOMAIN --notify
+$NOTIFY_ADDRESSES --local-domains $LOCAL_DOMAINS_ARRAY --silent-viruses
+$SILENT_VIRUSES --lang $QSLANG --debug $DEBUG_LEVEL --unzip $FORCE_UNZIP
+--add-dscr-hdrs $DESCRIPTIVE_HEADERS --use-vpop $USE_VPOP --archive $ARCHIVEIT
+--redundant $REDUNDANT --log-details $LOG_DETAILS --fix-mime $FIX_MIME --scanners
+\"$SCANNERS\""
@@ -867,7 +916,27 @@
exit
fi
+if [ "$USE_VPOP" = "1" ]; then
+DD=`$PERL5 -e 'use vpopmail;' 2>&1`
+if [ "$?" != "0" ]; then
+ cat<<EOF
+
+ **************************
+
+ perl doesn't have vpopmail module - cannot continue.
+
+Get it from CPAN:
+http://search.cpan.org/search?query=vpopmail
+
+ **************************
+
+EOF
+ exit
+fi
+fi
+
+if [ "$MIME_UNPACKER" = "reformime" ]; then
#Check version of maildrop to ensure it's not the buggy version
DD="`$MAILDROP_BINARY -v 2>&1|grep '^maildrop'|grep '1\.0'`"
@@ -888,6 +957,7 @@
EOF
exit
fi
+fi
#Find out if their uudecoder is supported
if [ "$UUDECODE_BINARY" != "" ]; then
@@ -974,7 +1044,8 @@
LOCAL_DOMAINS_ARRAY="`echo $LDA|sed 's/^,//g'`"
fi
-if [ "$REFORMIME_BINARY" = "" ]
+if [ "$MIME_UNPACKER" = "reformime" ]; then
+if [ "$UNMIME_BINARY" = "" ]
then
cat<<EOF
@@ -991,7 +1062,7 @@
EOF
exit
fi
-
+fi
if [ "$UNZIP_BINARY" = "" ]; then
cat<<EOF
@@ -1022,10 +1093,10 @@
echo "
The following binaries and scanners were found on your system:
"
-if [ "$REFORMIME_BINARY" != "" ]
+if [ "$UNMIME_BINARY" != "" ]
then
- echo "reformime=$REFORMIME_BINARY"
- MIMEUNPACKER="$REFORMIME_BINARY "
+ echo "mimeunpacker=$UNMIME_BINARY"
+ MIMEUNPACKER="$UNMIME_BINARY "
fi
if [ "$UUDECODE_BINARY" != "" ]
then
@@ -1190,6 +1261,9 @@
if [ "$ARCHIVEIT" != "0" ]; then
echo "archiving into $AS_QQ/$ARCHIVEDIR/"
fi
+if [ "$USE_VPOP" != "" ]; then
+ echo "use-vpop=$USE_VPOP"
+fi
echo "virus-admin=$USERNAME@$MAILDOMAIN"
echo "local-domains=$LOCAL_DOMAINS_ARRAY"
echo "silent-viruses=$FIND_SILENT_VIRUSES_ARRAY"
@@ -1251,7 +1325,7 @@
. ./.locale_vars
-perl -p -e "s?REFORMIME_BINARY?$REFORMIME_BINARY?g;
+perl -p -e "s?UNMIME_BINARY?$UNMIME_BINARY?g;
s?PERLRELEASE_DETAILS?$PERLRELEASE_DETAILS?g;
s?HOST_OS?$HOST_OS?g;
s?HOST_RELEASE?$HOST_RELEASE?g;
@@ -1302,6 +1376,7 @@
s?UUDECODE_BINARY?$UUDECODE_BINARY?g;
s?UUDECODE_PIPE?$UUDECODE_PIPE?g;
s?AS_QQ?$AS_QQ?g;
+s?USE_VPOP?$USE_VPOP?g;
s?ARCHIVEIT?$ARCHIVEIT?g;
s?ARCHIVEDIR?$ARCHIVEDIR?g;
s?REDUNDANT?$REDUNDANT?g;
diff -ruN qmail-scanner-1.15/qmail-scanner-aliases
qmail-scanner-1.15.vpopmail/qmail-scanner-aliases
--- qmail-scanner-1.15/qmail-scanner-aliases Wed Dec 31 17:00:00 1969
+++ qmail-scanner-1.15.vpopmail/qmail-scanner-aliases Fri Nov 22 01:24:35 2002
@@ -0,0 +1,12 @@
+# This is a sample /var/qmail/users/qmail-scanner-aliases file it must be owned
+# by qmailq and chown 0600 for security reasons, errors in this file can really
+# mess up SpamAssassin. example follow:
+
+# this is a comment line
+
+# [EMAIL PROTECTED] is actually [EMAIL PROTECTED]
[EMAIL PROTECTED] [EMAIL PROTECTED]
+
+# these are silly but is still valid
+"this is a silly email address"@domain.com [EMAIL PROTECTED]
[EMAIL PROTECTED] "this is a silly email address@ really braindead"@domain.com
diff -ruN qmail-scanner-1.15/qmail-scanner-queue.template
qmail-scanner-1.15.vpopmail/qmail-scanner-queue.template
--- qmail-scanner-1.15/qmail-scanner-queue.template Tue Oct 15 06:34:04 2002
+++ qmail-scanner-1.15.vpopmail/qmail-scanner-queue.template Fri Nov 22 01:57:50
+2002
@@ -95,6 +95,20 @@
#deciding whether or not to send recipient alerts to
my @local_domains_array=(LOCAL_DOMAINS_ARRAY);
+#Array of vpopmail domains this is used by spamassassin
+#to properly retrive user settings.
+my @vpop_domains_array=('');
+my $use_vpop=USE_VPOP;
+if ($use_vpop) {
+ use vpopmail;
+ @vpop_domains_array=vlistdomains();
+ push (@local_domains_array, @vpop_domains_array);
+}
+
+#Hash of aliases read from /var/qmail/users/qmail-scanner-aliases
+#this file must be owned by qmailq and chowned 0600 for security
+my %alias;
+
# Array of virus that we want to inform the sender of.
my @silent_viruses_array=(SILENT_VIRUSES_ARRAY);
@@ -290,6 +304,8 @@
if ($mimeunpacker_binary =~ /reformime/) {
$mimeunpacker_binary .= " -x$scandir/$file_id/";
+} elsif ($mimeunpacker_binary =~ /ripmime/) {
+ $mimeunpacker_binary .= " --syslog_on --stderr_off -i - -d $scandir/$file_id/";
}
@@ -566,12 +582,12 @@
my ($new_filename,$MAYBETNEF,$tnef_status);
&debug("d_m: starting $mimeunpacker_binary <$scandir/$wmaildir/new/$file_id
[",&deltatime,"]");
- open(MIME,"$mimeunpacker_binary
<$scandir/$wmaildir/new/$file_id|")||&tempfail("cannot call mimeunpacker - $!");
+ open(MIME,"$mimeunpacker_binary
+<$scandir/$wmaildir/new/$file_id|")||&tempfail("cannot call $mimeunpacker_binary -
+$!");
while (<MIME>) {
next if (/exists\./);
- &tempfail("d_m: output spotted from reformime - that shouldn't happen!");
+ &tempfail("d_m: output spotted from $mimeunpacker_binary - that shouldn't
+happen!");
}
- close(MIME)||&tempfail("cannot close mimeunpacker - $!");
+ close(MIME)||&tempfail("cannot close $mimeunpacker_binary - $!");
my $unpacker='';
opendir(DIR,"$scandir/$file_id/")||&tempfail("cannot open dir $scandir/$file_id/ -
$!");
@@ -712,12 +728,14 @@
#append any ORIGINAL uuencoded filenames to this directory array
#so that perlscanner can match on uuencoded filenames
foreach $file (@allfiles,@uufile_list,@zipfile_list) {
- #skip files that reformime generates.
+ #skip files that reformime/ripmime generates.
#This will potentially allow baddies to smuggle files through
#by using filenames like this... Nothing can be done about that:-(
#Reformime generates filenames of the form:
# 967067231.24320-X.host.name (where X is a number)
- if ($file =~ /^[0-9]+\.[0-9]+\-[0-9]+\.|^$file_id/) {
+ #Ripmime generates filenames of the form:
+ # textfileX (where X is a number)
+ if ($file =~ /^[0-9]+\.[0-9]+\-[0-9]+\.|^$file_id|^textfile[0-9]+/) {
&debug("p_s: skipping auto-generated file $file");
$ps_skipfile=1;
} else {
diff -ruN qmail-scanner-1.15/sub-spamassassin.pl
qmail-scanner-1.15.vpopmail/sub-spamassassin.pl
--- qmail-scanner-1.15/sub-spamassassin.pl Mon Oct 7 14:25:43 2002
+++ qmail-scanner-1.15.vpopmail/sub-spamassassin.pl Fri Nov 22 01:24:35 2002
@@ -2,14 +2,67 @@
#Only run SA if mail is from a "remote" SMTP client, or QS_SPAMASSASSIN
#is defined via tcpserver...
return if (defined($ENV{'RELAYCLIENT'}) && !defined($ENV{'QS_SPAMASSASSIN'}));
+ #SA should not be run on local shell users either set the environment
+ #variable QMAILLOCALUSER=1 for local shell users in profile.d
+ return if (defined($ENV{'QMAILLOCALUSER'}));
+
+ #Read in the aliases database from /var/qmail/users/qmail-scanner-aliases
+ my $aliasdb = '/var/qmail/users/qmail-scanner-aliases';
+ if ((-e $aliasdb && -f $aliasdb && -o $aliasdb) &&
+ ("0600" eq sprintf("%04lo", ((stat($aliasdb))[2]) & 07777))) {
+ open(ALIASDB, '<', "$aliasdb"); # we should really handle an error here
+ while(<ALIASDB>) {
+ chomp;
+ # skip comments
+ if (/^#/) {
+ next;
+ }
+ # alias
+ if ((/(.*\@.*)\s+(\".*\"\@.*)/) || (/(.*\@.*)\s+(.*\@.*)/)) {
+ $alias{lc($1)} = lc($2);
+ next;
+ }
+ # shouldn't reach this point
+ }
+ close(ALIASDB);
+ }
+
+ #grab the user from the RCPTTO qmail should have already checked this for any
+ #potential security hazards
+ my ($spamassassin_user) = lc($headers{'RCPTTO'});
+
+ # check for an aliased user profile
+ if (exists $alias{$spamassassin_user}) {
+ $spamassassin_user = $alias{$spamassassin_user};
+ }
+
+ my ($dom);
+ my ($is_vpop)=0;
+ foreach $dom (@vpop_domains_array) {
+ if ($spamassassin_user =~ /.*\@$dom$/i) {
+ $is_vpop=1;
+ last;
+ }
+ }
+ #if the domain is not vpopmail strip off the domain information
+ if (!$is_vpop) {
+ foreach $dom (@local_domains_array) {
+ last if ($spamassassin_user =~ s/\@$dom$//i);
+ }
+ }
+ #fail safe fall back to qmailq
+ if($spamassassin_user eq '') {
+ $spamassassin_user = 'qmailq';
+ }
+
#SpamAssassin client scanner
my ($spamassassin_found,$spamassassin_status);
my ($start_spamassassin_time)=[gettimeofday];
my ($DD,$spamassassin_status,$stop_spamassassin_time,$spamassassin_time);
my ($sa_status)=0;
my ($sa_score)=0; my ($sa_max)=0;
- &debug("SA: run $spamc_binary $spamc_options < $scandir/$wmaildir/new/$file_id");
- open(SA,"$spamc_binary $spamc_options <
$scandir/$wmaildir/new/$file_id|")||&tempfail("cannot run $spamc_binary <
$scandir/$wmaildir/new/$file_id - $!");
+ &debug("SA: run $spamc_binary $spamc_options -u \"$spamassassin_user\" <
+$scandir/$wmaildir/new/$file_id");
+ open(SA,"$spamc_binary $spamc_options -u \"$spamassassin_user\" <
+$scandir/$wmaildir/new/$file_id|")||&tempfail("cannot run $spamc_binary <
+$scandir/$wmaildir/new/$file_id - $!");
open(SOUT,">$scandir/$wmaildir/new/$file_id.spamc")||&tempfail("cannot open for
write $scandir/$wmaildir/new/$file_id.spamc - $!");
while (<SA>) {
if ($spamc_options =~ /\-c/) {