On my setup here I am using relay-ctrl (http://untroubled.org/relay-ctrl/) so that I can control SMTP relaying from users that authenticate thru pop3/pop3-ssl and imap/imap-ssl. (yes vpopmail roaming works as well but it doesn't do anything for my imap users).
I've also attached my patch to qmail-scanner-1.15 a friend of mine already posted it to the sourceforge site in the patches section.. guess noone really took notice ;) anyways it Works-for-Me(tm) I use mysql to store all of the spamassassin prefs which makes it easy for my users to come in via the web to change their own whitelists etc.. I also disable the sitewide AWL cause all I need is one user doing "blacklist_from *.com" to make a huge mess of things. <SNIP> 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. 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.. Has only been tested with user-prefs stored in mysql database (but other ways "should" work ;) ). 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 This patch has only been tested on a couple servers and no warranty is expressed or implied. Questions/comments should be forwarded to "wwong at blackstar.net" Patch to qmail-scanner-1.15 and run ./configure .. it "should work" New options to ./configure: --vpop-domains "one.domain,two.domain" Defaults to nothing Comma-separated list (no spaces!) of domains that are vpopmail domains. 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 ;) </SNIP> - 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.new/configure --- qmail-scanner-1.15/configure Tue Oct 29 17:44:37 2002 +++ qmail-scanner-1.15.new/configure Tue Nov 12 01:49:03 2002 @@ -96,6 +96,7 @@ --notify) if [ "$2" != "" ]; then shift ; fi ; NOTIFY_ADDRESSES="$1" ;; --silent-viruses) if [ "$2" != "" ]; then shift ; fi ; FIND_SILENT_VIRUSES="$1" ;; --local-domains) if [ "$2" != "" ]; then shift ; fi ; LOCAL_DOMAINS_ARRAY="$1" ;; + --vpop-domains) if [ "$2" != "" ]; then shift ; fi ; VPOP_DOMAINS_ARRAY="$1" ;; --lang) if [ "$2" != "" ]; then shift ; fi ; QSLANG="$1" ;; --debug) if [ "$2" != "" ] ; then shift ; fi ; DEBUG_LEVEL="$1" ;; --unzip) if [ "$2" != "" ] ; then shift ; fi ; FORCE_UNZIP="$1" ;; @@ -146,6 +147,14 @@ is chosen. This will drastically reduce the chance of alerts being sent to mailing-lists. + --vpop-domains "one.domain,two.domain" Defaults to nothing + Comma-separated list (no spaces!) + of domains that are vpopmail domains. + 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". --silent-viruses "virus1,virus2" Defaults to "auto". This option allows you to tell Qmail-Scanner *not* to notify @@ -773,7 +782,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 +--vpop-domains=$VPOP_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\"" @@ -974,6 +983,17 @@ LOCAL_DOMAINS_ARRAY="`echo $LDA|sed 's/^,//g'`" fi +VPOP_DOMAINS_ARRAY="`echo $VPOP_DOMAINS_ARRAY|sed -e 's/\"//g' -e 's/ //g'`" + +if [ "$VPOP_DOMAINS_ARRAY" ]; then + VDA="" + for dom in `echo $VPOP_DOMAINS_ARRAY|sed 's/,/ /g'` + do + VDA="$VDA,'$dom'" + done + VPOP_DOMAINS_ARRAY="`echo $VDA|sed 's/^,//g'`" +fi + if [ "$REFORMIME_BINARY" = "" ] then cat<<EOF @@ -1192,6 +1212,7 @@ fi echo "virus-admin=$USERNAME@$MAILDOMAIN" echo "local-domains=$LOCAL_DOMAINS_ARRAY" +echo "vpop-domains=$VPOP_DOMAINS_ARRAY" echo "silent-viruses=$FIND_SILENT_VIRUSES_ARRAY" echo "scanners=$SCANNER_ARRAY" @@ -1296,6 +1317,7 @@ s?FQDN?$FQDN?g; s?MAILDOMAIN?$MAILDOMAIN?g; s?LOCAL_DOMAINS_ARRAY?$LOCAL_DOMAINS_ARRAY?g; +s?VPOP_DOMAINS_ARRAY?$VPOP_DOMAINS_ARRAY?g; s?NOTIFY_ADDRESSES?$NOTIFY_ADDRESSES?g; s?FIND?$FIND?g; s?GREP?$GREP?g; diff -ruN qmail-scanner-1.15/qmail-scanner-aliases qmail-scanner-1.15.new/qmail-scanner-aliases --- qmail-scanner-1.15/qmail-scanner-aliases Wed Dec 31 17:00:00 1969 +++ qmail-scanner-1.15.new/qmail-scanner-aliases Tue Nov 12 03:41:28 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.new/qmail-scanner-queue.template --- qmail-scanner-1.15/qmail-scanner-queue.template Tue Oct 15 06:34:04 2002 +++ qmail-scanner-1.15.new/qmail-scanner-queue.template Tue Nov 12 02:01:03 2002 @@ -95,6 +95,14 @@ #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=(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); diff -ruN qmail-scanner-1.15/sub-spamassassin.pl qmail-scanner-1.15.new/sub-spamassassin.pl --- qmail-scanner-1.15/sub-spamassassin.pl Mon Oct 7 14:25:43 2002 +++ qmail-scanner-1.15.new/sub-spamassassin.pl Wed Nov 13 01:18:55 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/) {