################### Virus Snaggers, ver. 2.2.2a; 24-Nov-04 ################### ##################### by Dallman Ross ##################### #################### Copyright (c) 2003-04 by the author ##################### ########### See vsnag.readme for full information on user license ############ ##################### NO WARRANTIES, EXPRESS OR IMPLIED ###################### ####################### Tech Support Available for Fee ####################### ############################################################################## ### LICENCE DOES NOT PERMIT YOU TO PORT MY CODE TO OTHER COMMERCIAL APPS! #### ############################################################################## # Virus Snaggers ("Still the Best!") :-) plug-in for procmail can be found at # vsnag.spamless.us. See also www.procmail.org. ## ## Please read accompanying vsnag.readme file for instructions and a full ## discussion of the significant changes found in this version. ############################################################################## ################## I RECOMMEND THAT YOU NOT EDIT THIS FILE! ################## ######### YOU CAN CUSTOMIZE BY EDITING THE "MYVARS" ENV FILE INSTEAD ######### ############## IN ANY CASE, PLEASE COMMENT ANY CHANGES AS YOURS ############## ############################################################################## ### Initiate some pre-sets ### VS_OLDVERBOSE = "$VERBOSE" VERBOSE = "${VS_DEBUG:-$VERBOSE}" VS_OLDTRAP = "$TRAP" TRAP = 'echo "======>> $logtext <<======"' ### Bail now if procmail version too old ### MATCH :0 # 040902 () use weighted conditions to decide if our version's okay * 9876543210 ^0 ! PROCMAIL_VERSION ?? ()\/[0-9]*[.][0-9]* * $ -${MATCH:-0}^0 * 3.15^0 * LINEBUF ?? ^^()^^ { # users running procmail with the -p option need a fallback for nulled # $PROCMAIL_VERSION. Voila: ver. 3.15 has $LINEBUF, but 3.10 doesn't. # for such old procmails, unsetting SWITCHRC won't work :-( LOG = " ======>> YOUR PROCMAIL IS TOO OLD! VER. 3.15 IS MINIMUM <====== " # set VERBOSE, change logfiles to hammer home the point VERBOSE = "YOUR PROCMAIL VERSION IS DEPRECATED" # should equate to "y" LOGFILE = VSNAG_SAYS:_PROCMAIL_VERSION_DEPRECATED } ### Give us room to work ### VS_MINBUF = "${VS_MINBUF:-24576}" :0 # 040513 () make sure we have enough space in which to work * $ $VS_MINBUF^0 * $ -${LINEBUF:-0}^0 { LINEBUF = $VS_MINBUF } # N.B.: meaningless in deprecated procmail versions ### Read in configurable variables ### VS_HOME MATCH = $_ :0 # 040410 () find directory where Virus Snaggers lives * MATCH ?? ^^\/.*/ { VS_HOME = "$MATCH" } _SELF VS_PATHFINDER = "$VS_HOME" :0 # 040410 () set $VS_MYVARS path * VS_MYVARS ?? / { VS_PATHFINDER } INCLUDERC = "$VS_PATHFINDER${VS_MYVARS:-vsnag.myvars.rc}" :0 # 040423 () did we run? * _SELF ?? ^^()^^ { logtext = "THE VIRUS SNAGGERS MYVARS FILE DIDN'T RUN! BAILING" SWITCHRC # bailing now; will run $TRAP } _SELF VS_PATHFINDER = "$VS_HOME" :0 # 040410 () set $VS_GENVARS path * VS_GENVARS ?? / { VS_PATHFINDER } INCLUDERC = "$VS_PATHFINDER${VS_GENVARS:-vsnag.genvars.rc}" :0 # 040423 () did we run? * $ _SELF ?? $FALSE { logtext = "THE VIRUS SNAGGERS GENVARS FILE DIDN'T RUN! BAILING" SWITCHRC # bailing now; will run $TRAP } ### Set some dependencies ### :0 # 040409 () parse $HOST to get local domain "stub" unless preset * $ MYDOMAINSTUB ?? $FALSE { MATCH :0 # 040412 () for a host of mail.foo.com, the "stub" will be "foo" * $ $GO^0 HOST ?? ()\/[^.]+[.][^.][^.][.][^.][^.]^^ * $ $GO^0 HOST ?? ()\/[^.]+[.][^.]+^^ * MATCH ?? ^^\/[^.]* { } MYDOMAINSTUB = "${MATCH:-$HOST}" } ### Collect header information ### MATCH :0 # 040330 () find asserted From: line, if exists * $ H_FROM ?? $FALSE * $ ^From:.*\/[^$WS].* { H_FROM = $MATCH } MATCH :0 # 040323 () save the value of Content-Type: * $ H_CTYPE ?? $FALSE * $ ^Content-Type:.*\/[^$WS][^;]+ { H_CTYPE = $MATCH } MATCH :0 # 040327 () assign the Message-ID header if it exists * $ H_MSGID ?? $FALSE * $ ^Message-ID:.*\/[^$WS].* { H_MSGID = $MATCH } MATCH :0 # 040327 () assign the X-Mailer header if it exists * $ H_XMAILER ?? $FALSE * $ ^X-Mailer:.*\/[^$WS].* { H_XMAILER = $MATCH } MATCH H_RCVD_COUNT = 0 :0 # 040525 () find sending client in bottom Received, count Receiveds * $ 1^1 ^Received:[$WS]*from[$WS]+\/[^$WS].+[$WS]by[$WS] * MATCH ?? ^^\/.+b * $ MATCH ?? ^^\/.+[^b$WS] { H_BTM_CLIENT = ${MATCH:-DUMMY} H_RCVD_COUNT = $= } MATCH :0 # 040522 () guess at receiving server's IP address if not preset * $ MYDOMAIN_IP ?? $FALSE { MYDOMAIN_IP = DUMMY :0 # 040523 () if one Received only, discard IP if hostname mismatched * $ 2^0 ! H_BTM_CLIENT ?? ()\<$MYDOMAINSTUB\> * $ -$H_RCVD_COUNT^0 { } :0 E # 040525 () else, we'll look for an IP address in top Received * $ ^Received:[$WS]*from[$WS]+\/[^$WS].+[$WS]by[$WS] * $ $GO^0 MATCH ?? [[]\/$DOTQUAD * $ $GO^0 MATCH ?? ()\/$DOTQUAD * MATCH ?? ^^\/.*[.] { MYDOMAIN_IP = "$\MATCH$OCTET" } } :0 # 040331 () parse MYDOMAIN_IP for quoting of non-regex strings * ! MYDOMAIN_IP ?? ([[|(\]|DUMMY) { MYDOMAIN_IP = "$\MYDOMAIN_IP" } :0 # 040928 () Attachment? * $ $GO^0 H_CTYPE ?? ^^(attachment|multipart) * $ $STOP^0 H_CTYPE ?? /report * $ $STOP^0 H_BTM_CLIENT ?? ()\<$MYDOMAIN_IP * $ $H_RCVD_COUNT^0 ^FROM_MAILER # local-only admin messages defanged * $ -1^0 H_BTM_CLIENT ?? ()\<(localhost|root|$LOCALHOST)\> { VS_ATTACH = $TRUE } ### "Snag" Section ### :0 # 040330 () descend into nested tests if attachment or $AGGRESSIVE * $ $GO^0 VS_ATTACH ?? $TRUE * $ $GO^0 ^Content-Transfer-Encoding:(.*\<)?base64 * $ $STOP^0 AGGRESSIVE ?? $VAROFF * $ $GO^0 B ?? ()\<(http|www|$DOTQUAD)\> { :0 # 041003 () look for characteristic bogus mail client * $ H_BTM_CLIENT ?? ^^(.*(\ * $ ! H_BTM_CLIENT ?? ()\<$MYDOMAIN_IP * $ ! H_BTM_CLIENT ?? ()\<($LOCALHOST|$PRIVATE_IP)\> { VS_OUT = "$VS_VER:sending_client=host-spoof" } MATCH :0 E # 040411 () else, Message-ID markers of common viruses/worms * $ ^Content-Type:.*\(.+$*)*\ * $ $GO^0 VS_EXT ?? =zip^^ { VS_OUT = "$VS_VER:$VS_EXT" } :0 E # 040924 () check $AGGRESSIVE state to block certain $ZIPs * $ AGGRESSIVE ?? $VARON * $ B ?? > $VS_ZIPMIN * $ B ?? < $VS_ZIPMAX { VS_OUT = "$VS_VER:aggressive=on+$VS_EXT" } :0 E # 040924 () else, no X-Mailer + low Received count * $ H_XMAILER ?? $FALSE * $ $STOP^0 H_RCVD_COUNT ?? ^^1^^ * $ ${RCVD_THRESHOLD:-2}^0 ! H_BTM_CLIENT ?? ()\<$MYDOMAIN_IP * $ $SMALL^0 * $ -$H_RCVD_COUNT^0 { VS_OUT = "$VS_VER:low_rcvd_count+!xmailer+$VS_EXT" } :0 E # 040924 () else, no space in From: or To: is atomic * $ ! H_FROM ?? [$WS>] * $ ! ^To:.*[^$WS][$WS>] # N.B.: We've left in the possibility of a missing To: * ! ^X-Sender { VS_OUT = "$VS_VER:from_atomic+to_atomic+$VS_EXT" } :0 E # 040924 () block ZIPs that are within DAEMONs * $ $GO^0 ^FROM_MAILER * $ $STOP^0 AGGRESSIVE ?? $FALSE * $ $GO^0 ^FROM_DAEMON { VS_OUT = "$VS_VER:mailer-daemon+$VS_EXT" } } :0 # 040830 () debug: set VBELL to enable ding on virus identification * $ $GO^0 ! VBELL ?? $VAROFF * $ $GO^0 VS_DIAGS ?? $TRUE * $ VS_OUT ?? $TRUE * ? echo  { } ### Delivery Section ### TRAP = "$VS_OLDTRAP" INCLUDERC = $VS_HOOK # let users tweak the logs via an optional INCLUDERC VS_DELIVER = $MYVIRUS :0 # 040903 () does it seem to be a virus, or just spam? * VS_OUT ?? spammy^^ * $ VS_SPAMMY ?? $TRUE { VS_DELIVER = "$VS_SPAMMY" } :0 # 040829 () exit now if we're not delivering; run self-test if indicated * $ $GO^0 NONDELIVER ?? $VARON * $ $GO^0 VS_OUT ?? $FALSE * $ $GO^0 VS_DIAGS ?? $TRUE { VERBOSE = "$VS_OLDVERBOSE" SWITCHRC = "$VS_DIAGS" } :0 D # 040320 () bulletproof $h: it must be unset, null, or lower-case "h" * h ?? ^^([^h]|h.) { h } ALOCK = : :0 D # 040322 () check for maildir delivery; otherwise create lockfile * $ $GO^0 VS_DELIVER ?? /^^ * $ $GO^0 VS_DELIVER ?? ^^/dev/null^^ { ALOCK } # N.B.: deprecated procmail versions didn't grok our "SWITCHRC" :0 $h $ALOCK # 040513 () for headers only, $h will have been set to "h" * $ VS_OUT ?? $TRUE $VS_DELIVER VERBOSE = "$VS_OLDVERBOSE"