diff -uNr simscan-1.3.1.org/config.h.in simscan-1.3.1/config.h.in --- simscan-1.3.1.org/config.h.in Fri Nov 10 09:16:30 2006 +++ simscan-1.3.1/config.h.in Mon Sep 17 16:06:59 2007 @@ -12,6 +12,18 @@ /* run ripmime program */ #undef DO_RIPMIME +/* enable bogofilter scanning */ +#undef ENABLE_BOGOFILTER + +/* "bogofilter program" */ +#undef BOGOFILTER + +/* "bogofilter user" */ +#undef BOGOFILTER_DB + +/* "bogofilter user" */ +#undef BOGOFILTER_MAXSIZE + /* "dspam program" */ #undef DSPAM @@ -35,6 +47,9 @@ /* dspam --user user@domain option. */ #undef ENABLE_DSPAM_USER + +/* dspam default user. */ +#define DSPAM_DEFAULT_USER "vpopmail" /* enable per domain checking */ #undef ENABLE_PER_DOMAIN diff -uNr simscan-1.3.1.org/configure simscan-1.3.1/configure --- simscan-1.3.1.org/configure Fri Nov 10 09:16:26 2006 +++ simscan-1.3.1/configure Mon Sep 17 16:07:21 2007 @@ -860,9 +860,13 @@ --enable-dropmsg=y|n Drop message in case of virus/spam found. Don't return error to sender. --enable-dspam=y|n Turn on dspam scanning. default no. --enable-spam-passthru=y|n Pass spam email thru or reject (default disable, reject). - --enable-dspam-user=y|n Set user option to spamc. + --enable-dspam-user=y|n Set user option to dspam. --enable-dspam-path=PATH Full path to spamc program. - --enable-dspam-args="args" Override the default dspam arguments. + --enable-dspam-args="args" Override the default dspam arguments not implemented now. + --enable-dspam-default-user= dspam default user default vpopmail. + --enable-bogofilter=y|n Turn on bogofilter scanning. default no. + --enable-bogofilter-db=PATH Path to DB directory Set option to bogofilter -d default /home/vpopmail/.bogofilter. + --enable-bogofilter-maxsize=SIZE Maximum size to scan by bogofilter. --enable-spam=y|n Turn on spam scanning. default no. --enable-spamc-user=y|n Set user option to spamc. --enable-spam-auth-user=y|n Turn on spam scanning for authenticated users (default no). @@ -872,7 +876,8 @@ --enable-qmaildir=DIR Base qmail directory /var/qmail. --enable-workdir=DIR Directory to unpack emails /var/qmail/simscan. --enable-controldir=DIR Directory to place control files /var/qmail/control. - --enable-quarantinedir=DIR Directory to keep spam and/or infected emails /var/qmail/quarantine. + --enable-quarantine=y|n Turn on to keep spam infected emails into quarantinedir. default no. + --enable-quarantinedir=DIR Directory to keep spam and/or infected emails default /var/qmail/quarantine. --enable-qmail-queue=PATH Full path to qmail-queue program. --enable-trophie-socket=PATH Full path to the trophie socket. --enable-trophie-path=PATH Full path to the trophie binary. @@ -4130,6 +4135,135 @@ #define DSPAM_ARGS "$ENABLE_DSPAM_ARGS" _ACEOF + + # Check whether --enable-dspam-default-user or --disable-dspam-default-user was given. +if test "${enable_dspam_default_user+set}" = set; then + enableval="$enable_dspam_default_user" + DSPAM_DEFAULT_USER="$enableval" +else + + if test "$DSPAM_DEFAULT_USER" = "" + then + DSPAM_DEFAULT_USER="vpopmail" + fi + + +fi; + +cat >>confdefs.h <<_ACEOF +#define DSPAM_DEFAULT_USER "$DSPAM_DEFAULT_USER" +_ACEOF + + ;; + +esac + +#---------------------------------------------------------------------- + +# Check whether --enable-bogofilter or --disable-bogofilter was given. +if test "${enable_bogofilter+set}" = set; then + enableval="$enable_bogofilter" + ENABLE_BOGOFILTER="$enableval" +else + + ENABLE_BOGOFILTER=no + +fi; +case $ENABLE_BOGOFILTER in +1*|y*|Y*) + ENABLE_BOGOFILTER=1 + +cat >>confdefs.h <<_ACEOF +#define ENABLE_BOGOFILTER $ENABLE_BOGOFILTER +_ACEOF + + ;; +*) + ENABLE_BOGOFILTER=0 + ;; +esac + +case $ENABLE_BOGOFILTER in + 1*|y*|Y*) + + # Check whether --enable-spam-passthru or --disable-spam-passthru was given. +if test "${enable_spam_passthru+set}" = set; then + enableval="$enable_spam_passthru" + ENABLE_SPAM_PASSTHRU="$enableval" +else + + ENABLE_SPAM_PASSTHRU=no + +fi; + case $ENABLE_SPAM_PASSTHRU in + 1*|y*|Y*) + ENABLE_SPAM_PASSTHRU=1 + +cat >>confdefs.h <<\_ACEOF +#define ENABLE_SPAM_PASSTHRU +_ACEOF + + ;; + *) + ENABLE_SPAM_PASSTHRU=0 + ;; + esac + ;; +esac + +#---------------------------------------------------------------------- + +case $ENABLE_BOGOFILTER in +1*|y*|Y*) + + echo "$as_me:$LINENO: checking whether we can locate the bogofilter program" >&5 +echo $ECHO_N "checking whether we can locate the bogofilter program... $ECHO_C" >&6 + bogofilter="" + for f in /usr/bin/bogofilter /usr/local/bin/bogofilter + do + if test -f $f + then + bogofilter=$f + break + fi + done + + # Check whether --enable-bogofilter-db or --disable-bogofilter-db was given. +if test "${enable_bogofilter_db+set}" = set; then + enableval="$enable_bogofilter_db" + ENABLE_BOGOFILTER_DB="$enableval" +else + + ENABLE_BOGOFILTER_DB="/home/vpopmail/.bogofilter" + +fi; + +cat >>confdefs.h <<_ACEOF +#define BOGOFILTER_DB "$ENABLE_BOGOFILTER_DB" +_ACEOF + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +cat >>confdefs.h <<_ACEOF +#define BOGOFILTER "$bogofilter" +_ACEOF + + + # Check whether --enable-bogofilter-maxsize or --disable-bogofilter-maxsize was given. +if test "${enable_bogofilter_maxsize+set}" = set; then + enableval="$enable_bogofilter_maxsize" + ENABLE_BOGOFILTER_MAXSIZE="$enableval" +else + + ENABLE_BOGOFILTER_MAXSIZE=600000 + +fi; + +cat >>confdefs.h <<_ACEOF +#define BOGOFILTER_MAXSIZE $ENABLE_BOGOFILTER_MAXSIZE +_ACEOF + ;; esac @@ -4420,41 +4554,60 @@ #---------------------------------------------------------------------- -# Check whether --enable-quarantinedir or --disable-quarantinedir was given. -if test "${enable_quarantinedir+set}" = set; then - enableval="$enable_quarantinedir" +# Check whether --enable-quarantine or --disable-quarantine was given. +if test "${enable_quarantine+set}" = set; then + enableval="$enable_quarantine" ENABLE_QUARANTINE="$enableval" else ENABLE_QUARANTINE=no fi; +case $ENABLE_QUARANTINE in +1*|y*|Y*) + ENABLE_QUARANTINE=1 + ;; +*) + ENABLE_QUARANTINE=0 + ;; +esac - case $ENABLE_QUARANTINE in - 0*|n*|N*) - ;; - *) - echo "$as_me:$LINENO: checking setting the quarantine directory" >&5 +#---------------------------------------------------------------------- + +case $ENABLE_QUARANTINE in +1*|y*|Y*) + ENABLE_QUARANTINEDIR="" + # Check whether --enable-quarantinedir or --disable-quarantinedir was given. +if test "${enable_quarantinedir+set}" = set; then + enableval="$enable_quarantinedir" + ENABLE_QUARANTINEDIR="$enableval" +else + + ENABLE_QUARANTINEDIR="" + +fi; + + echo "$as_me:$LINENO: checking setting the quarantine directory" >&5 echo $ECHO_N "checking setting the quarantine directory... $ECHO_C" >&6 - quarantinedir="$qmaildir/quarantine" - if test "$quarantinedir" = "" - then - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - { { echo "$as_me:$LINENO: error: Unable to find your quarantinedir directory, specify --enable-quarantinedir." >&5 -echo "$as_me: error: Unable to find your quarantinedir directory, specify --enable-quarantinedir." >&2;} - { (exit 1); exit 1; }; } - fi + if test "$ENABLE_QUARANTINEDIR" = "" + then + quarantinedir="$qmaildir/quarantine" + else + quarantinedir="$ENABLE_QUARANTINEDIR" + fi cat >>confdefs.h <<_ACEOF #define QUARANTINEDIR "$quarantinedir" _ACEOF - echo "$as_me:$LINENO: result: done" >&5 + echo "$as_me:$LINENO: result: done" >&5 echo "${ECHO_T}done" >&6 - ;; - esac + ;; +*) + ;; +esac + #---------------------------------------------------------------------- @@ -7118,6 +7271,7 @@ echo " dspam scanning = ON" echo " dspam program = $dspam" echo " dspam arguments = $ENABLE_DSPAM_ARGS" + echo " dspam default user = $DSPAM_DEFAULT_USER" case $ENABLE_SPAM_PASSTHRU in 0*|n*|N*) echo " spam passthru = OFF" @@ -7139,6 +7293,28 @@ *) echo " dspam scanning = OFF" + ;; +esac + +case $ENABLE_BOGOFILTER in + 1*|y*|Y*) + echo " bogofilter scanning = ON" + echo " bogofilter program = $bogofilter" + echo " bogofilter db = $ENABLE_BOGOFILTER_DB" + echo " bogofilter maxsize = $ENABLE_BOGOFILTER_MAXSIZE" + case $ENABLE_SPAM_PASSTHRU in + 0*|n*|N*) + echo " spam passthru = OFF" + ;; + *) + echo " spam passthru = ON" + ;; + esac + + ;; + + *) + echo " bogofilter scanning = OFF" ;; esac diff -uNr simscan-1.3.1.org/configure.in simscan-1.3.1/configure.in --- simscan-1.3.1.org/configure.in Fri Nov 10 09:15:39 2006 +++ simscan-1.3.1/configure.in Mon Sep 17 16:07:12 2007 @@ -214,7 +214,7 @@ fi done - AC_ARG_ENABLE(dspam-user, [ --enable-dspam-user=y|n Set user option to spamc.], + AC_ARG_ENABLE(dspam-user, [ --enable-dspam-user=y|n Set user option to dspam.], ENABLE_DSPAM_USER="$enableval", [ ENABLE_DSPAM_USER=no @@ -243,12 +243,96 @@ AC_MSG_RESULT(yes) AC_DEFINE_UNQUOTED(DSPAM,"$dspam","dspam program") - AC_ARG_ENABLE(dspam-args, [ --enable-dspam-args="args" Override the default dspam arguments.], + AC_ARG_ENABLE(dspam-args, [ --enable-dspam-args="args" Override the default dspam arguments not implemented now.], ENABLE_DSPAM_ARGS="$enableval", [ ENABLE_DSPAM_ARGS="" ]) AC_DEFINE_UNQUOTED(DSPAM_ARGS,"$ENABLE_DSPAM_ARGS","dspam arguments") + + AC_ARG_ENABLE(dspam-default-user, + [ --enable-dspam-default-user= dspam default user default vpopmail.], + DSPAM_DEFAULT_USER="$enableval", + [ + if test "$DSPAM_DEFAULT_USER" = "" + then + DSPAM_DEFAULT_USER="vpopmail" + fi + ] + ) + AC_DEFINE_UNQUOTED(DSPAM_DEFAULT_USER,"$DSPAM_DEFAULT_USER","dspam default user") + ;; + +esac + +#---------------------------------------------------------------------- + +AC_ARG_ENABLE(bogofilter, [ --enable-bogofilter=y|n Turn on bogofilter scanning. default no.], + ENABLE_BOGOFILTER="$enableval", + [ + ENABLE_BOGOFILTER=no + ] ) +case $ENABLE_BOGOFILTER in +1*|y*|Y*) + ENABLE_BOGOFILTER=1 + AC_DEFINE_UNQUOTED([ENABLE_BOGOFILTER], $ENABLE_BOGOFILTER, [enable bogofilter scanning]) + ;; +*) + ENABLE_BOGOFILTER=0 + ;; +esac + +case $ENABLE_BOGOFILTER in + 1*|y*|Y*) + + AC_ARG_ENABLE(spam-passthru, [ --enable-spam-passthru=y|n Pass spam email thru or reject (default disable, reject).], + ENABLE_SPAM_PASSTHRU="$enableval", + [ + ENABLE_SPAM_PASSTHRU=no + ] ) + case $ENABLE_SPAM_PASSTHRU in + 1*|y*|Y*) + ENABLE_SPAM_PASSTHRU=1 + AC_DEFINE([ENABLE_SPAM_PASSTHRU], [], [pass spam through to user]) + ;; + *) + ENABLE_SPAM_PASSTHRU=0 + ;; + esac + ;; +esac + +#---------------------------------------------------------------------- + +case $ENABLE_BOGOFILTER in +1*|y*|Y*) + + AC_MSG_CHECKING(whether we can locate the bogofilter program) + bogofilter="" + for f in /usr/bin/bogofilter /usr/local/bin/bogofilter + do + if test -f $f + then + bogofilter=$f + break + fi + done + + AC_ARG_ENABLE(bogofilter-db, [ --enable-bogofilter-db=PATH Path to DB directory Set option to bogofilter -d default /home/vpopmail/.bogofilter.], + ENABLE_BOGOFILTER_DB="$enableval", + [ + ENABLE_BOGOFILTER_DB="/home/vpopmail/.bogofilter" + ] ) + AC_DEFINE_UNQUOTED(BOGOFILTER_DB,"$ENABLE_BOGOFILTER_DB","bogofilter db directory") + AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED(BOGOFILTER,"$bogofilter","bogofilter program") + + AC_ARG_ENABLE(bogofilter-maxsize, [ --enable-bogofilter-maxsize=SIZE Maximum size to scan by bogofilter.], + ENABLE_BOGOFILTER_MAXSIZE="$enableval", + [ + ENABLE_BOGOFILTER_MAXSIZE=600000 + ] ) + AC_DEFINE_UNQUOTED(BOGOFILTER_MAXSIZE,$ENABLE_BOGOFILTER_MAXSIZE,"bogofilter maximum scan size") ;; esac @@ -443,29 +527,47 @@ #---------------------------------------------------------------------- -AC_ARG_ENABLE(quarantinedir, - [ --enable-quarantinedir=DIR Directory to keep spam and/or infected emails [/var/qmail/quarantine].], - ENABLE_QUARANTINE="$enableval", - [ +AC_ARG_ENABLE(quarantine, [ --enable-quarantine=y|n Turn on to keep spam infected emails into quarantinedir. default no.], + ENABLE_QUARANTINE="$enableval", + [ ENABLE_QUARANTINE=no - ]) + ] ) +case $ENABLE_QUARANTINE in +1*|y*|Y*) + ENABLE_QUARANTINE=1 + ;; +*) + ENABLE_QUARANTINE=0 + ;; +esac + +#---------------------------------------------------------------------- + +case $ENABLE_QUARANTINE in +1*|y*|Y*) + ENABLE_QUARANTINEDIR="" + AC_ARG_ENABLE(quarantinedir, + [ --enable-quarantinedir=DIR Directory to keep spam and/or infected emails default /var/qmail/quarantine.], + ENABLE_QUARANTINEDIR="$enableval", + [ + ENABLE_QUARANTINEDIR="" + ]) + + AC_MSG_CHECKING(setting the quarantine directory) + if test "$ENABLE_QUARANTINEDIR" = "" + then + quarantinedir="$qmaildir/quarantine" + else + quarantinedir="$ENABLE_QUARANTINEDIR" + fi + AC_DEFINE_UNQUOTED(QUARANTINEDIR,"$quarantinedir","quarantine directory") + AC_SUBST(quarantinedir) + AC_MSG_RESULT(done) + ;; +*) + ;; +esac - case $ENABLE_QUARANTINE in - 0*|n*|N*) - ;; - *) - AC_MSG_CHECKING(setting the quarantine directory) - quarantinedir="$qmaildir/quarantine" - if test "$quarantinedir" = "" - then - AC_MSG_RESULT(no) - AC_MSG_ERROR([Unable to find your quarantinedir directory, specify --enable-quarantinedir.]) - fi - AC_DEFINE_UNQUOTED(QUARANTINEDIR,"$quarantinedir","quarantine directory") - AC_SUBST(quarantinedir) - AC_MSG_RESULT(done) - ;; - esac #---------------------------------------------------------------------- @@ -894,6 +996,7 @@ echo " dspam scanning = ON" echo " dspam program = $dspam" echo " dspam arguments = $ENABLE_DSPAM_ARGS" + echo " dspam default user = $DSPAM_DEFAULT_USER" case $ENABLE_SPAM_PASSTHRU in 0*|n*|N*) echo " spam passthru = OFF" @@ -915,6 +1018,28 @@ *) echo " dspam scanning = OFF" + ;; +esac + +case $ENABLE_BOGOFILTER in + 1*|y*|Y*) + echo " bogofilter scanning = ON" + echo " bogofilter program = $bogofilter" + echo " bogofilter db = $ENABLE_BOGOFILTER_DB" + echo " bogofilter maxsize = $ENABLE_BOGOFILTER_MAXSIZE" + case $ENABLE_SPAM_PASSTHRU in + 0*|n*|N*) + echo " spam passthru = OFF" + ;; + *) + echo " spam passthru = ON" + ;; + esac + + ;; + + *) + echo " bogofilter scanning = OFF" ;; esac diff -uNr simscan-1.3.1.org/simscan.c simscan-1.3.1/simscan.c --- simscan-1.3.1.org/simscan.c Fri Nov 10 09:16:56 2006 +++ simscan-1.3.1/simscan.c Mon Sep 17 16:07:32 2007 @@ -46,6 +46,10 @@ #ifdef ENABLE_REGEX #include #endif +/* For Solaris 8 */ +#ifndef INADDR_NONE +#define INADDR_NONE INADDR_BROADCAST +#endif /* qmail-queue error codes */ #define EXIT_0 0 /* Success */ #define EXIT_11 11 /* address too long */ @@ -89,6 +93,9 @@ #define MAX_DSPAM_ARGS 20 char *dspam_args[MAX_DSPAM_ARGS]; +#define MAX_BOGOFILTER_ARGS 20 +char *bogofilter_args[MAX_BOGOFILTER_ARGS]; + #define MAX_SPAMC_ARGS 20 char *spamc_args[MAX_SPAMC_ARGS]; @@ -111,6 +118,8 @@ char *replace(char *string, char *oldpiece, char *newpiece); int DebugFlag = 0; +long _msg_size = 0; + /* To/From address processing globals */ #define MAX_RCPT_TO 255 #define MAX_EMAIL 500 @@ -204,6 +213,15 @@ int is_dspam(char *spambuf); #endif +/* BOGOFILTER scanning globals */ +#if defined(ENABLE_BOGOFILTER) +int InHeaders; +int IsSpam; +char spam_message_name[BUFFER_SIZE]; +int check_bogofilter(); +int is_bogofilter(char *spambuf); +#endif + float SpamHits; float ReqHits; @@ -365,7 +383,9 @@ write(fd, buffer, strlen(buffer)); */ /* read the email into the new file */ + _msg_size = 0; while( (ret = read(0, buffer, sizeof(buffer))) > 0 ) { + _msg_size += ret; if ( write(fd, buffer,ret) == -1 ) { if ( DebugFlag > 0 ) { fprintf(stderr, "simscan: error writing msg error: %d\n", errno); @@ -496,6 +516,85 @@ } #endif +#if defined(ENABLE_BOGOFILTER) +/* The following code is copied from the Spamassassin check below, with the proper adjustments */ + + /* re-open the file read only */ + if ( (fd = open(message_name, O_RDONLY)) == -1 ) { + if ( DebugFlag > 0 ) { + fprintf(stderr, "simscan: spam can not open file: %s\n", message_name); + } + exit_clean(EXIT_400); + } + + /* set the standard input to be the new file */ + if ( fd_move(0,fd) == -1 ) { + if ( DebugFlag > 0 ) { + fprintf(stderr, "simscan: spam could not fd_move\n"); + } + exit_clean(EXIT_400); + } + + /* optionally check for spam with BOGOFILTER */ + snprintf(spam_message_name, sizeof(spam_message_name), "bogo.msg.%s", unique_ext); + IsSpam = 0; + ret = check_bogofilter(); + switch ( ret ) { + /* bogofilter not enabled for this domain */ + case 2: + /* re-open the message file file read only */ + /* do nothing, message_name gets openend in any case*/ + break; + + /* spam detected, refuse message */ + case 1: + if ( DebugFlag > 0 ) { + fprintf(stderr, "simscan: BOGOFILETR reported message as being SPAM\n"); + } + close(fd); + +#ifdef QUARANTINEDIR + quarantine_msg(spam_message_name); + /* put message in quarantine */ +#endif + +#ifdef ENABLE_DROPMSG + if ( DebugFlag > 0 ) { + fprintf(stderr, "simscan: droping the message\n"); + } + exit_clean(EXIT_0); + /* Drop the message, returning success to sender. */ +#else + #ifdef ENABLE_CUSTOM_SMTP_REJECT + snprintf(RejectMsg,sizeof(RejectMsg), "DYour email is considered spam (%.4f probability)", SpamProbability ); + write(4,RejectMsg, strlen(RejectMsg)); + exit_clean(EXIT_MSG); + #else + exit_clean(EXIT_500); + #endif +#endif + break; + + /* bogofilter processed message and no spam detected */ + case 0: + if ( DebugFlag > 0 ) { + fprintf(stderr, "simscan: BOGOFILTER reported message as NOT being SPAM\n"); + } + /* open the spam file read only */ + strncpy(message_name,spam_message_name,BUFFER_SIZE); + break; + /* errors , return temporary error */ + default: + if ( DebugFlag > 0 ) { + fprintf(stderr, "simscan: check_bogofilter had an error ret: %d\n", ret); + } + close(fd); + exit_clean(EXIT_400); + } + +#endif + + #if defined(ENABLE_DSPAM) /* The following code is copied from the Spamassassin check below, with the proper adjustments */ @@ -516,7 +615,7 @@ } /* optionally check for spam with DSPAM */ - snprintf(spam_message_name, sizeof(spam_message_name), "spamc.msg.%s", unique_ext); + snprintf(spam_message_name, sizeof(spam_message_name), "dspam.msg.%s", unique_ext); IsSpam = 0; ret = check_dspam(); switch ( ret ) { @@ -1091,7 +1190,6 @@ int rmstat; int pim[2]; int spam_fd; - char *tmpbuf; FILE *spamfs; int i; @@ -1119,9 +1217,6 @@ fprintf(stderr, "simscan: calling dspam\n"); } - tmpbuf = malloc(strlen(DSPAM_ARGS)+1); - strcpy(tmpbuf, DSPAM_ARGS); - /* setup the dspam args dspam_args[0] = "dspam"; dspam_args[1] = "--stdout"; @@ -1144,15 +1239,15 @@ #ifdef ENABLE_DSPAM_USER if ( MaxRcptTo==1 ) { dspam_args[i++] = "--user"; - //dspam_args[i++] = "vpopmail"; + //dspam_args[i++] = DSPAM_DEFAULT_USER; dspam_args[i++] = RcptTo[0]; } else { dspam_args[i++] = "--user"; - dspam_args[i++] = "vpopmail"; + dspam_args[i++] = DSPAM_DEFAULT_USER; } #else dspam_args[i++] = "--user"; - dspam_args[i++] = "vpopmail"; + dspam_args[i++] = DSPAM_DEFAULT_USER; #endif dspam_args[i++] = NULL; @@ -1213,6 +1308,180 @@ /* check if the child died on a signal */ if ( WIFSIGNALED(rmstat) ) return(-1); + /* check exit code != 0 */ + if ( WEXITSTATUS(rmstat) ) return(-1); + +#ifdef ENABLE_SPAM_PASSTHRU + #ifdef ENABLE_PER_DOMAIN + if ( PerDomainSpamPassthru == 1) { + if ( IsSpam == 1 ) { + if (DebugFlag > 0) { + fprintf(stderr, + "simscan: delivering spam because spam-passthru is defined in this domain\n"); + } + log_message("PASSTHRU", Subject,1); + } else { + log_message("CLEAN", Subject,1); + } + return(0); + } else { + if ( IsSpam == 1 ) { +#ifdef ENABLE_DROPMSG + log_message("SPAM DROPPED", Subject, 1); +#else + log_message("SPAM REJECT", Subject,1); +#endif + return(1); + } else { + log_message("CLEAN", Subject,1); + } + } + #else + if ( IsSpam == 1 ) { + log_message("PASSTHRU", Subject,1); + } else { + log_message("CLEAN", Subject,1); + } + return(0); + #endif +#else + if ( IsSpam == 1 ) { +#ifdef ENABLE_DROPMSG + log_message("SPAM DROPPED", Subject, 1); +#else + log_message("SPAM REJECT", Subject,1); +#endif + return(1); + } else { + log_message("CLEAN", Subject,1); + } +#endif + + return(0); + +} +#endif + +/* + * optionally check for spam + * + * Returns: 2 if email should not be spam checked + * 1 if it is spam + * 0 if not spam + <0 on errors + */ +#if defined(ENABLE_BOGOFILTER) +int check_bogofilter() +{ + int pid; + int rmstat; + int pim[2]; + int spam_fd; +FILE *spamfs; + int i; + + if ( _msg_size > BOGOFILTER_MAXSIZE ) return(2); + +#ifdef ENABLE_PER_DOMAIN + if ( PerDomainSpam == 0 ) return(2); +#endif + +#ifndef ENABLE_SPAM_AUTH_USER + /* don't scan email from authenticated senders */ + if (getenv("RELAYCLIENT")) { + log_message("RELAYCLIENT", "-", 0); + return 2; + } +#endif + + if ( (spam_fd=open(spam_message_name, O_RDWR|O_CREAT|O_TRUNC,0644)) ==- 1) { + if ( DebugFlag > 0 ) { + fprintf(stderr, "simscan: check_spam could not open spam file: %s\n", + spam_message_name); + } + return(-1); + } + + if ( DebugFlag > 0 ) { + fprintf(stderr, "simscan: calling bogofilter\n"); + } + + /* setup the bogofilter args + */ + + i = 0; + bogofilter_args[i++] = "bogofilter"; + bogofilter_args[i++] = "-e"; + bogofilter_args[i++] = "-p"; + + bogofilter_args[i++] = "-d"; +#ifdef BOGOFILTER_DB + bogofilter_args[i++] = BOGOFILTER_DB; +#else + bogofilter_args[i++] = "/home/vpopmail/.bogofilter"; +#endif + + bogofilter_args[i++] = NULL; + + if ( DebugFlag > 0 ) { + fprintf(stderr, "simscan: calling %s ", BOGOFILTER); + i=0; + while(bogofilter_args[i] != NULL){ + fprintf(stderr, " %s", bogofilter_args[i]); + ++i; + } + fprintf(stderr, "\n"); + } + if ( pipe(pim) == 0 ) { + /* fork bogofilter */ + switch(pid = vfork()) { + case -1: + close(pim[0]); + close(pim[1]); + close(spam_fd); + return(-1); + case 0: + close(pim[0]); + dup2(pim[1],1); + close(pim[1]); + i = execve(BOGOFILTER, bogofilter_args, 0); + fprintf(stderr, "execve returned %d/%d\n", i, errno); + _exit(-1); + } + close(pim[1]); + dup2(pim[0],0); + close(pim[0]); + } else { + close(spam_fd); + return(0); + } + + InHeaders=1; + SpamProbability = 0; + memset(buffer,0,sizeof(buffer)); + + spamfs = fdopen(0,"r"); + IsSpam = 0; + while(fgets(buffer,sizeof(buffer)-1,spamfs) != NULL ) { + if ( InHeaders == 1 ) { + is_bogofilter(buffer); + } + write(spam_fd, buffer,strlen(buffer)); + memset(buffer,0,sizeof(buffer)); + } + + close(spam_fd); + /* wait for bogofilter to finish */ + if (waitpid(pid,&rmstat, 0) == -1) { + return(-1); + } + + /* check if the child died on a signal */ + if ( WIFSIGNALED(rmstat) ) return(-1); + + /* check exit code != 0 */ + if ( WEXITSTATUS(rmstat) ) return(-1); + #ifdef ENABLE_SPAM_PASSTHRU #ifdef ENABLE_PER_DOMAIN if ( PerDomainSpamPassthru == 1) { @@ -1983,6 +2252,49 @@ #endif +#if defined(ENABLE_BOGOFILTER) +/* Check for a spam message + * This is done by checking for a matching line + * in the email headers for X-DSPAM-Result: which + * we put in each spam email + * + * Return 1 if spam + * Return 0 if not spam + * Return -1 on error + */ +int is_bogofilter(char *spambuf) +{ + int l; + + if ( spambuf[0] == '\n' || spambuf[1] == '\n' ) { + InHeaders = 0; + return(0); + } + + if (strstr(spambuf, "X-Bogosity:")) { + if ( strstr(spambuf, "X-Bogosity: Spam")) { + IsSpam=1; + } + } else if ( strncmp(spambuf, "Subject:", 8 ) == 0 ) { + strncpy(Subject, &spambuf[9], sizeof(Subject)-1); + + /* replace : char with _ and null terminate on + * newline or carrage return + */ + for(l=0;Subject[l]!=0 && l