diff -rcN sendmail-8.8.8-orig/COPYING.SPAMCAN sendmail-8.8.8-spamcan-96/COPYING.SPAMCAN *** sendmail-8.8.8-orig/COPYING.SPAMCAN Wed Dec 31 16:00:00 1969 --- sendmail-8.8.8-spamcan-96/COPYING.SPAMCAN Wed Oct 29 21:38:04 1997 *************** *** 0 **** --- 1,2 ---- + + This version is hereby in the public domain. There is no warranty. diff -rcN sendmail-8.8.8-orig/COPYRIGHT.SPAMCAN sendmail-8.8.8-spamcan-96/COPYRIGHT.SPAMCAN *** sendmail-8.8.8-orig/COPYRIGHT.SPAMCAN Wed Dec 31 16:00:00 1969 --- sendmail-8.8.8-spamcan-96/COPYRIGHT.SPAMCAN Wed Oct 29 21:38:04 1997 *************** *** 0 **** --- 1,8 ---- + For all software in this distribution: + + Copyright 1997 Timothy Berger -- All Rights Reserved + + This program is free software; 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. + diff -rcN sendmail-8.8.8-orig/INSTALL.SPAMCAN sendmail-8.8.8-spamcan-96/INSTALL.SPAMCAN *** sendmail-8.8.8-orig/INSTALL.SPAMCAN Wed Dec 31 16:00:00 1969 --- sendmail-8.8.8-spamcan-96/INSTALL.SPAMCAN Wed Oct 29 23:30:23 1997 *************** *** 0 **** --- 1,36 ---- + + The Distribution and documentation is available from + http://consult.ml.org/~timb/spamcan + + 1) Apply context diff to clean Sendmail 8.8.8 distribution. + You might need gnu patch. + + Eg: + tar xzvf sendmail.8.8.8.tar.gz + tar xzvf spamcan.tar.gz + cd sendmail-8.8.8 + patch -p1 < ../spamcan_for_v888_diff.patch + + 2) Do NOT use gnu rx unless your system is missing some form + of regex. I have observed segmentation faults in the rx + library on systems with regexec and regcomp in the system's + libc. Sorry for previously recommending this on solaris. + + 3) Tailor spamcan.c to suit your environment. Chose the type + of messages you'd like to pass through un-scanned. This is documented + in the source code. + + 4) Copy sample-spamcan.cf to /etc/spamcan.cf and edit to suit. + Some expressions may not be appropriate for your site. + Be sure to review them. + + 5) Create /etc/spamcan-exceptins.cf. Optionally put some regular expressions + there. Note, this exceptions file does not understand header names. Because + of added overhead, I decided this did not add much value. + + 6) Touch /var/spool/mail/spamcan on linux or /var/mail/spamcan on Solaris. + Make it writable by daemon or root on solaris or by mail on linux. + + 7) Make and install sendmail. + + -tim diff -rcN sendmail-8.8.8-orig/NEWS.SPAMCAN sendmail-8.8.8-spamcan-96/NEWS.SPAMCAN *** sendmail-8.8.8-orig/NEWS.SPAMCAN Wed Dec 31 16:00:00 1969 --- sendmail-8.8.8-spamcan-96/NEWS.SPAMCAN Wed Oct 29 23:17:15 1997 *************** *** 0 **** --- 1,54 ---- + + Since spamcan .95 + ----------------- + * Version .96 is released to support sendmail-8.8.8. + * There are no other changes other than the bundled + spam filters are a bit newer; edit to suit. They + may not be approprite for your site. + + Since spamcan .94 + ----------------- + * Version .95 is a pretty minor release for sendmail-8.8.7. + It will not be back-patched for 8.8.6. + * Has an exceptions list feature. + * Fixes a buffer overflow problem. + * Conversion from net byte order to host byte order for hosts where this + differs. Contributed by toivo@ucs.uwa.edu.au. + + Since spamcan .92 + ----------------- + * There were some spam catching problems with this version. + Fixed this. + * Added user-ownable spamcan support. If a user touches + /var/spool/mail/username.spam, caught spam will be + sent there. As with .nospamcan.username, this has to + be owned by the appropriate user. + * Added support for using the header name in the regular + expression. + + Since spamcan .90 + ----------------- + * Fixed possible segmentation fault problem if ctladdr is NULL + + Since spamcan .87 + ----------------- + * users can now disable spam catching if they touch + /var/spool/mail/.nospamcan.username + * fixed possible problem where delivery to the spamcan would not + work if the recipient was a file. + * misc. bug fixes. + * added logging all over the place. commented much of it out though. + this should be #ifdef'd + * learned not to use the rx package. yes, this bit me. + * seems over-all much more stable + + Since spamcan .86 + ----------------- + * got rid of x-spamcan-to and x-spamcan-from headers; not useful for much + * included simple report script + * make context diff + * small change to use the right path for spamcan file + + Since spamcan .85 + ------------------- + * fixed documentation bug diff -rcN sendmail-8.8.8-orig/TODO.SPAMCAN sendmail-8.8.8-spamcan-96/TODO.SPAMCAN *** sendmail-8.8.8-orig/TODO.SPAMCAN Wed Dec 31 16:00:00 1969 --- sendmail-8.8.8-spamcan-96/TODO.SPAMCAN Wed Oct 29 21:38:04 1997 *************** *** 0 **** --- 1,37 ---- + spamcan TODO list + ------------------ + + * Impliment a scoring system. Assign points to regular expressions. + Add up the points for a mail message; if this number reaches some + threashold, identify the message as spam. Otherwise deliver mail + with an X-Spamlevel header with the number of points as the header + value. For example, procmail's ~/.procmailrc would look like so: + + :0 h + SPAMLEVEL=|formail -xX-Spamlevel: + + :0 + * ? test $SPAMLEVEL -gt 60 + Mail/spamorama + + :0 + * ? test $SPAMLEVEL -gt 40 + Mail/spam + :0 + + * ? test $SPAMLEVEL -gt 30 + Mail/junk + + :0 + * ? test $SPAMLEVLE -gt 20 + Mail/junk_lists + + :0 + * ? test $SPAMLEVEL -gt 10 + Mail/lists + + * Assign spamlevel on a per message basis rather than on a per-recipient + basis. This should speed things up slightly for multiple hits. + + * Fix X-Spamcan-Reason header. Sometimes the wrong recipient is shown if + there were multiple hits. diff -rcN sendmail-8.8.8-orig/sample-spamcan.cf sendmail-8.8.8-spamcan-96/sample-spamcan.cf *** sendmail-8.8.8-orig/sample-spamcan.cf Wed Dec 31 16:00:00 1969 --- sendmail-8.8.8-spamcan-96/sample-spamcan.cf Wed Oct 29 23:12:04 1997 *************** *** 0 **** --- 1,118 ---- + (^(From|To): [0-9]{8}@) + x-advertisement + ((ireport|amailformetoo|mis-mail|novatechsolutions|notthere|lostvegas|dollar|tnlb|hitmasters|universe|fortune|datablast|myownemail|pleaseread|workathome|getonthe|quadxzad|jimsonstin|1stfamily|fundsrecovery|contactdata|outgoing|internetmedia|websites|4younow|hitsrus|bonghits|onestopshop|thisitscook|success|ldelivery|willametteweb|first\.amendment|showplaceintl|thehitman|NaturalInstincts|cprvid|mailermachine|just4u|owlsnest|45neter!|anywhere|killer9780home|sixdegrees|everywhere|24hrplaymates|asianmktplace|getrichclick|idp|contestsource|mary-world|globaltech2000|shoppingplanet|answerme|yourdomain|ispam|devotion|quantcom|savetrees|anydomain|nowhere)\.(com|org|net|edu)) + ((timeisnow|INVALID_ADDRESS|-marketing|clubmail|prdfjk|metasales|whynotu|TRWLies|weightloss44|loverslife434|euroschool|forsale|email4all|srhot|foryou|vip|mailman|postman|succeed|success|everyon|megaweb|emailers?|getrichclick|allinternetusers|market|(friend(s)?))@[a-z0-9.-_]*\.(jp|org|net|com|edu)) + (@(marketing)\.net) + we-deliver\.net + @griff\.net + Compucash + c-flash\.net + \$\$\$\$ + free.*software.*! + make.*money.*! + business@mail\.t-1net\.com + Your Turn To Win + [0-9]{3,5}.*search engines + greathomebiz\.com + qualhost\.com + (\$.* (per|a) .* (day|month|year) .*!.*!) + global-impact\.com + pericom-usa\.com + 206\.45\.233\.1 + \[207\.217\.28\.56\] + \[204\.246\.12\.107\] + \[206\.175\.223\.177\] + \[208\.144\.78\.230\] + \[206\.170\.68\.53\] + \[208\.128\.162\.46\] + 207\.92\.171\.120 + (123|Party79333|Hangman37|balo|Onsales|HockeyUBet)@aol\.com + Received: from \(\[ \. \. \. \]\) + kohui27@compuserve\.com + To: .*\.{12,} + To:.*[ <]you@ + Received: from xxxxxxxxxxxxxxxx + number18\.tierranet\.com + Your Listing on Yahoo + inetdatax\.com + greenharvest@t-1net\.com + random@random\.com + everyone@your\.net + \[12\.64\.37\.204\] + planetall\.com + Financial Freedom + Debt Management Club + 208\.211\.205\.88 + ^Received: .*http:// + (^Reply-to: .*noreply.*) + (\[000\.000\.000\.000\]) + (\[38\.12\.123\.80\]) + (\[205\.252\.149\.206\]) + group mail [0-9]\.[0-9] + you.*profit.*from + extractor pro + keepmailing + money.*!{3,8} + get@noticed\.now + money.*fast + glenfinnan + marathon4com + fresh.*addresses + mega-mailer + mass.*mailer + corporate.*marketing.*lists + marketing .*make.*you.*rich + mail .*for.*sale + million .*messages.*per.*hour + message.*millions.*hour + bulk e?-?mail + jerrysp@sunspot + d564390\.com + @.*(answer)[a-z0-9.-_]*\.(com|net|org|edu) + ((cyber|web)(suburb|market|shop|promo|gold)) + 4u2c?\.com + (mail|internet).*marketing + for name removal information + Last Chance to save + billy@bongo\.com + greatnewbooks + udeservelove + plrsssrprdtss + the.*internet.*! + adult.*!.*! + marketing secrets + first\.amendment\.protects\.us + ppp3128\.on\.sympatico\.ca + master-graphics + (^Subject: .*\$.*per.*month) + (^Subject: .*\$.*a.*minute) + E-X-P-0-S-E + major.*credit.*card + credit.*card.*!.*! + New Web Site.*free + --- CLOAKED! --- + Internet\.Mail\.Delivery + low.*cost.*service + (long.*distance.*(service|rates)) + you@.*ibm\.net + mykabot\.net + Adult Advertisement + Adults Only + US Ghetto AID + lolac@worldnet\.att\.net + international.*rates + international shop + VideoSex + Floodgate pro + save.*over.*[0-9]+% + (save the [a-z]+.*((!(!)+)|\*\*\*)) + 212@212\.net + online Sex + sex.*!.*!.*! + phone.*sex + make.*\$.*(in|every).*days + Internet.*Advertis + sexboy24 + distrib@usa\.net + --- unknown host --- + Smartdata\.Inc diff -rcN sendmail-8.8.8-orig/spamcan-exceptions.cf sendmail-8.8.8-spamcan-96/spamcan-exceptions.cf *** sendmail-8.8.8-orig/spamcan-exceptions.cf Wed Dec 31 16:00:00 1969 --- sendmail-8.8.8-spamcan-96/spamcan-exceptions.cf Wed Oct 29 23:12:04 1997 *************** *** 0 **** --- 1,20 ---- + midiworld\.com + dizzinews@samurai\.com + menieres_talk@smtp\.cochlea\.com + owner-dxpc@mcfeeley\.cc\.utexas\.edu + nationjob\.com + pagemart\.net + wheeltowheel + autofs@linux\.kernel\.org + bb@taex001\.tamu\.edu + SunSolve-EarlyNotifier + smtpgate\.norand\.com + bolero\.rahul\.net + plaidworks\.com + bywc@zytor + sun\.com + microsoft\.com + fool\.com + lists\.Stanford\.EDU + planetall\.com + usenix\.ORG diff -rcN sendmail-8.8.8-orig/src/Makefiles/Makefile.Linux sendmail-8.8.8-spamcan-96/src/Makefiles/Makefile.Linux *** sendmail-8.8.8-orig/src/Makefiles/Makefile.Linux Thu Aug 7 12:29:55 1997 --- sendmail-8.8.8-spamcan-96/src/Makefiles/Makefile.Linux Wed Oct 29 21:38:04 1997 *************** *** 24,30 **** # # use O=-O (usual) or O=-g (debugging) ! O= -O # define the database mechanisms available for map & alias lookups: # -DNDBM -- use new DBM --- 24,30 ---- # # use O=-O (usual) or O=-g (debugging) ! O= -g # define the database mechanisms available for map & alias lookups: # -DNDBM -- use new DBM *************** *** 61,67 **** HFDIR= ${DESTDIR}/usr/lib # additional .o files needed ! OBJADD= # additional pseudo-sources needed BEFORE= --- 61,67 ---- HFDIR= ${DESTDIR}/usr/lib # additional .o files needed ! OBJADD= spamcan.o # additional pseudo-sources needed BEFORE= diff -rcN sendmail-8.8.8-orig/src/Makefiles/Makefile.SunOS.5.1 sendmail-8.8.8-spamcan-96/src/Makefiles/Makefile.SunOS.5.1 *** sendmail-8.8.8-orig/src/Makefiles/Makefile.SunOS.5.1 Thu Aug 7 12:29:57 1997 --- sendmail-8.8.8-spamcan-96/src/Makefiles/Makefile.SunOS.5.1 Wed Oct 29 21:38:04 1997 *************** *** 32,45 **** # see also conf.h for additional compilation flags # include directories ! INCDIRS=-I/usr/sww/include # library directories ! LIBDIRS=-L/usr/sww/lib # libraries required on your system # delete -l44bsd if you are not running BIND 4.9.x ! LIBS= -lresolv -l44bsd -lsocket -lnsl -lelf # location of sendmail binary (usually /usr/sbin or /usr/lib) BINDIR= ${DESTDIR}/usr/lib --- 32,45 ---- # see also conf.h for additional compilation flags # include directories ! INCDIRS=-I/usr/sww/include -I/usr/local/include # library directories ! LIBDIRS=-L/usr/sww/lib -L/usr/local/lib # libraries required on your system # delete -l44bsd if you are not running BIND 4.9.x ! LIBS= -lresolv -l44bsd -lsocket -lnsl -lelf # location of sendmail binary (usually /usr/sbin or /usr/lib) BINDIR= ${DESTDIR}/usr/lib *************** *** 51,57 **** HFDIR= ${DESTDIR}/etc/mail # additional .o files needed ! OBJADD= # things to be made before compilation begins BEFORE= sysexits.h --- 51,57 ---- HFDIR= ${DESTDIR}/etc/mail # additional .o files needed ! OBJADD= spamcan.o # things to be made before compilation begins BEFORE= sysexits.h diff -rcN sendmail-8.8.8-orig/src/Makefiles/Makefile.SunOS.5.2 sendmail-8.8.8-spamcan-96/src/Makefiles/Makefile.SunOS.5.2 *** sendmail-8.8.8-orig/src/Makefiles/Makefile.SunOS.5.2 Thu Aug 7 12:29:57 1997 --- sendmail-8.8.8-spamcan-96/src/Makefiles/Makefile.SunOS.5.2 Wed Oct 29 21:38:04 1997 *************** *** 32,45 **** # see also conf.h for additional compilation flags # include directories ! INCDIRS=-I/usr/sww/include # library directories ! LIBDIRS=-L/usr/sww/lib # libraries required on your system # delete -l44bsd if you are not running BIND 4.9.x ! LIBS= -lresolv -l44bsd -lsocket -lnsl -lelf # location of sendmail binary (usually /usr/sbin or /usr/lib) BINDIR= ${DESTDIR}/usr/lib --- 32,46 ---- # see also conf.h for additional compilation flags # include directories ! INCDIRS=-I/usr/sww/include -I/usr/local/include # library directories ! LIBDIRS=-L/usr/sww/lib -L/usr/local/lib ! # libraries required on your system # delete -l44bsd if you are not running BIND 4.9.x ! LIBS= -lresolv -l44bsd -lsocket -lnsl -lelf # location of sendmail binary (usually /usr/sbin or /usr/lib) BINDIR= ${DESTDIR}/usr/lib *************** *** 51,57 **** HFDIR= ${DESTDIR}/etc/mail # additional .o files needed ! OBJADD= # things to be made before compilation begins BEFORE= sysexits.h --- 52,58 ---- HFDIR= ${DESTDIR}/etc/mail # additional .o files needed ! OBJADD= spamcan.o # things to be made before compilation begins BEFORE= sysexits.h diff -rcN sendmail-8.8.8-orig/src/Makefiles/Makefile.SunOS.5.3 sendmail-8.8.8-spamcan-96/src/Makefiles/Makefile.SunOS.5.3 *** sendmail-8.8.8-orig/src/Makefiles/Makefile.SunOS.5.3 Thu Aug 7 12:29:56 1997 --- sendmail-8.8.8-spamcan-96/src/Makefiles/Makefile.SunOS.5.3 Wed Oct 29 21:38:04 1997 *************** *** 31,40 **** # see also conf.h for additional compilation flags # include directories ! INCDIRS=-I/usr/sww/include # library directories ! LIBDIRS=-L/usr/sww/lib # libraries required on your system # delete -l44bsd if you are not running BIND 4.9.x --- 31,40 ---- # see also conf.h for additional compilation flags # include directories ! INCDIRS=-I/usr/sww/include -I/usr/local/include # library directories ! LIBDIRS=-L/usr/sww/lib -L/usr/local/lib # libraries required on your system # delete -l44bsd if you are not running BIND 4.9.x *************** *** 50,56 **** HFDIR= ${DESTDIR}/etc/mail # additional .o files needed ! OBJADD= # things to be made before compilation begins BEFORE= sysexits.h --- 50,56 ---- HFDIR= ${DESTDIR}/etc/mail # additional .o files needed ! OBJADD= spamcan.o # things to be made before compilation begins BEFORE= sysexits.h diff -rcN sendmail-8.8.8-orig/src/Makefiles/Makefile.SunOS.5.4 sendmail-8.8.8-spamcan-96/src/Makefiles/Makefile.SunOS.5.4 *** sendmail-8.8.8-orig/src/Makefiles/Makefile.SunOS.5.4 Thu Aug 7 12:29:56 1997 --- sendmail-8.8.8-spamcan-96/src/Makefiles/Makefile.SunOS.5.4 Wed Oct 29 21:38:04 1997 *************** *** 33,42 **** # see also conf.h for additional compilation flags # include directories ! INCDIRS=-I/usr/sww/include # library directories ! LIBDIRS=-L/usr/sww/lib # libraries required on your system # delete -l44bsd if you are not running BIND 4.9.x --- 33,42 ---- # see also conf.h for additional compilation flags # include directories ! INCDIRS=-I/usr/sww/include -I/usr/local/include # library directories ! LIBDIRS=-L/usr/sww/lib -L/usr/local/lib # libraries required on your system # delete -l44bsd if you are not running BIND 4.9.x *************** *** 53,59 **** HFDIR= ${DESTDIR}/etc/mail # additional .o files needed ! OBJADD= # things to be made before compilation begins BEFORE= sysexits.h --- 53,59 ---- HFDIR= ${DESTDIR}/etc/mail # additional .o files needed ! OBJADD= spamcan.o # things to be made before compilation begins BEFORE= sysexits.h diff -rcN sendmail-8.8.8-orig/src/Makefiles/Makefile.SunOS.5.5 sendmail-8.8.8-spamcan-96/src/Makefiles/Makefile.SunOS.5.5 *** sendmail-8.8.8-orig/src/Makefiles/Makefile.SunOS.5.5 Thu Aug 7 12:29:57 1997 --- sendmail-8.8.8-spamcan-96/src/Makefiles/Makefile.SunOS.5.5 Wed Oct 29 21:38:04 1997 *************** *** 12,18 **** # use O=-O (usual) or O=-g (debugging) # warning: do not use -O with versions of gcc prior to 2.6 ! O= -O CC= gcc --- 12,18 ---- # use O=-O (usual) or O=-g (debugging) # warning: do not use -O with versions of gcc prior to 2.6 ! O= -g CC= gcc *************** *** 23,29 **** # The really old (V7) DBM library is no longer supported. # See READ_ME for a description of how these flags interact. # ! DBMDEF= -DNDBM -DNIS -DNISPLUS # environment definitions (e.g., -D_AIX3) ENVDEF= -DSOLARIS=20500 --- 23,29 ---- # The really old (V7) DBM library is no longer supported. # See READ_ME for a description of how these flags interact. # ! DBMDEF= -DNDBM -DNIS # environment definitions (e.g., -D_AIX3) ENVDEF= -DSOLARIS=20500 *************** *** 31,45 **** # see also conf.h for additional compilation flags # include directories ! INCDIRS=-I/usr/sww/include # library directories ! LIBDIRS=-L/usr/sww/lib # libraries required on your system # delete -l44bsd if you are not running BIND 4.9.x # add -ldb if you add -DNEWDB above (in DBMDEF) ! LIBS= -lresolv -l44bsd -lsocket -lnsl -lkstat # location of sendmail binary (usually /usr/sbin or /usr/lib) BINDIR= ${DESTDIR}/usr/lib --- 31,45 ---- # see also conf.h for additional compilation flags # include directories ! INCDIRS=-I/usr/sww/include -I/usr/local/include # library directories ! LIBDIRS=-L/usr/sww/lib -L/usr/local/lib # libraries required on your system # delete -l44bsd if you are not running BIND 4.9.x # add -ldb if you add -DNEWDB above (in DBMDEF) ! LIBS= -lresolv -lsocket -lnsl -lkstat # location of sendmail binary (usually /usr/sbin or /usr/lib) BINDIR= ${DESTDIR}/usr/lib *************** *** 51,57 **** HFDIR= ${DESTDIR}/etc/mail # additional .o files needed ! OBJADD= # things to be made before compilation begins BEFORE= sysexits.h --- 51,57 ---- HFDIR= ${DESTDIR}/etc/mail # additional .o files needed ! OBJADD= spamcan.o # things to be made before compilation begins BEFORE= sysexits.h diff -rcN sendmail-8.8.8-orig/src/Makefiles/Makefile.SunOS.5.6 sendmail-8.8.8-spamcan-96/src/Makefiles/Makefile.SunOS.5.6 *** sendmail-8.8.8-orig/src/Makefiles/Makefile.SunOS.5.6 Thu Aug 7 12:29:57 1997 --- sendmail-8.8.8-spamcan-96/src/Makefiles/Makefile.SunOS.5.6 Wed Oct 29 21:38:04 1997 *************** *** 31,40 **** # see also conf.h for additional compilation flags # include directories ! INCDIRS=-I/usr/sww/include # library directories ! LIBDIRS=-L/usr/sww/lib # libraries required on your system # delete -l44bsd if you are not running BIND 4.9.x --- 31,40 ---- # see also conf.h for additional compilation flags # include directories ! INCDIRS=-I/usr/sww/include -I/usr/local/include # library directories ! LIBDIRS=-L/usr/sww/lib -L/usr/local/lib # libraries required on your system # delete -l44bsd if you are not running BIND 4.9.x *************** *** 50,56 **** HFDIR= ${DESTDIR}/etc/mail # additional .o files needed ! OBJADD= # things to be made before compilation begins BEFORE= sysexits.h --- 50,56 ---- HFDIR= ${DESTDIR}/etc/mail # additional .o files needed ! OBJADD= spamcan.o # things to be made before compilation begins BEFORE= sysexits.h diff -rcN sendmail-8.8.8-orig/src/conf.c sendmail-8.8.8-spamcan-96/src/conf.c *** sendmail-8.8.8-orig/src/conf.c Mon Oct 20 08:41:38 1997 --- sendmail-8.8.8-spamcan-96/src/conf.c Wed Oct 29 21:38:05 1997 *************** *** 1001,1010 **** */ int ! checkcompat(to, e) register ADDRESS *to; register ENVELOPE *e; { # ifdef lint if (to == NULL) to++; --- 1001,1020 ---- */ int ! checkcompat(to, e, is_spam) register ADDRESS *to; register ENVELOPE *e; + int *is_spam; { + int spamcan(ADDRESS *to, ENVELOPE *e, int *is_spam ); + int retval; + + retval = spamcan(to, e, is_spam); + + if (retval != EX_OK) + return( retval ); + + # ifdef lint if (to == NULL) to++; *************** *** 1014,1019 **** --- 1024,1030 ---- printf("checkcompat(to=%s, from=%s)\n", to->q_paddr, e->e_from.q_paddr); + # ifdef EXAMPLE_CODE /* this code is intended as an example only */ register STAB *s; *************** *** 1973,1979 **** /* Non Apollo stuff removed by Don Lewis 11/15/93 */ #ifndef lint ! static char rcsid[] = "@(#)$Id: getloadavg.c,v 1.16 1991/06/21 12:51:15 paul Exp $"; #endif /* !lint */ #ifdef apollo --- 1984,1990 ---- /* Non Apollo stuff removed by Don Lewis 11/15/93 */ #ifndef lint ! static char rcsid[] = "@(#)$Id: conf.c,v 1.2 1997/07/18 07:31:18 timb Exp timb $"; #endif /* !lint */ #ifdef apollo *************** *** 2939,2945 **** * causing nast effects. **************************************************************/ ! /*static char _id[] = "$Id: snprintf.c,v 1.2 1995/10/09 11:19:47 roberto Exp $";*/ static void sm_dopr(); static char *DoprEnd; static int SnprfOverflow; --- 2950,2956 ---- * causing nast effects. **************************************************************/ ! /*static char _id[] = "$Id: conf.c,v 1.2 1997/07/18 07:31:18 timb Exp timb $";*/ static void sm_dopr(); static char *DoprEnd; static int SnprfOverflow; diff -rcN sendmail-8.8.8-orig/src/deliver.c sendmail-8.8.8-spamcan-96/src/deliver.c *** sendmail-8.8.8-orig/src/deliver.c Wed Oct 22 13:12:02 1997 --- sendmail-8.8.8-spamcan-96/src/deliver.c Wed Oct 29 23:08:30 1997 *************** *** 846,851 **** --- 846,852 ---- char rpathbuf[MAXNAME + 1]; /* translated return path */ extern int checkcompat(); extern void markfailure __P((ENVELOPE *, ADDRESS *, MCI *, int)); + int is_spam; errno = 0; if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags)) *************** *** 1013,1018 **** --- 1014,1020 ---- user = to->q_user; e->e_to = to->q_paddr; + if (tTd(10, 5)) { printf("deliver: QDONTSEND "); *************** *** 1043,1057 **** e->e_from.q_paddr, to->q_paddr, e); if (rcode == EX_OK) { ! /* do in-code checking */ ! rcode = checkcompat(to, e); ! } ! if (rcode != EX_OK) ! { ! markfailure(e, to, NULL, rcode); ! giveresponse(rcode, m, NULL, ctladdr, xstart, e); ! continue; ! } /* ** Strip quote bits from names if the mailer is dumb --- 1045,1065 ---- e->e_from.q_paddr, to->q_paddr, e); if (rcode == EX_OK) { ! /* do in-code checking */ ! rcode = checkcompat(to, e, &is_spam); ! /* sm_syslog(LOG_DEBUG, e->e_id, "Ran checkcompat"); */ ! } ! if (rcode != EX_OK) ! { ! sm_syslog(LOG_DEBUG, e->e_id, "Bad code from checkcompat, rcode = %d", rcode); ! markfailure(e, to, NULL, rcode); ! giveresponse(rcode, m, NULL, ctladdr, xstart, e); ! continue; ! } ! ! /* reset because spamcan modifies these */ ! user = to->q_user; ! m = to->q_mailer; /* ** Strip quote bits from names if the mailer is dumb *************** *** 1065,1072 **** } /* hack attack -- delivermail compatibility */ ! if (m == ProgMailer && *user == '|') ! user++; /* ** If an error message has already been given, don't --- 1073,1081 ---- } /* hack attack -- delivermail compatibility */ ! if (m == ProgMailer && *user == '|') { ! user++; ! } /* ** If an error message has already been given, don't *************** *** 1078,1084 **** */ if (bitset(QBADADDR|QQUEUEUP, to->q_flags)) ! continue; /* ** See if this user name is "special". --- 1087,1093 ---- */ if (bitset(QBADADDR|QQUEUEUP, to->q_flags)) ! continue; /* ** See if this user name is "special". *************** *** 1090,1096 **** if (strcmp(m->m_mailer, "[FILE]") == 0) { ! rcode = mailfile(user, ctladdr, SFF_CREAT, e); giveresponse(rcode, m, NULL, ctladdr, xstart, e); e->e_nsent++; if (rcode == EX_OK) --- 1099,1106 ---- if (strcmp(m->m_mailer, "[FILE]") == 0) { ! ! rcode = mailfile(user, ctladdr, SFF_CREAT, e, is_spam); giveresponse(rcode, m, NULL, ctladdr, xstart, e); e->e_nsent++; if (rcode == EX_OK) *************** *** 1545,1550 **** --- 1555,1561 ---- (void) setsignal(SIGHUP, SIG_IGN); (void) setsignal(SIGTERM, SIG_DFL); + if (m != FileMailer || stat(tochain->q_user, &stb) < 0) stb.st_mode = 0; *************** *** 3092,3108 **** static void mailfiletimeout(); int ! mailfile(filename, ctladdr, sfflags, e) char *volatile filename; ADDRESS *ctladdr; volatile int sfflags; register ENVELOPE *e; { register FILE *f; register pid_t pid = -1; volatile int mode = ST_MODE_NOFILE; bool suidwarn = geteuid() == 0; EVENT *ev; if (tTd(11, 1)) { --- 3103,3121 ---- static void mailfiletimeout(); int ! mailfile(filename, ctladdr, sfflags, e, is_spam) char *volatile filename; ADDRESS *ctladdr; volatile int sfflags; register ENVELOPE *e; + int is_spam; { register FILE *f; register pid_t pid = -1; volatile int mode = ST_MODE_NOFILE; bool suidwarn = geteuid() == 0; EVENT *ev; + int spamcan_exists = 0; if (tTd(11, 1)) { *************** *** 3168,3176 **** mode = FileMode; oflags |= O_CREAT|O_EXCL; } ! else if (bitset(0111, stb.st_mode) || stb.st_nlink != 1 || (SafeFileEnv != NULL && !S_ISREG(stb.st_mode))) exit(EX_CANTCREAT); if (mode == ST_MODE_NOFILE) mode = stb.st_mode; --- 3181,3192 ---- mode = FileMode; oflags |= O_CREAT|O_EXCL; } ! else { ! if (bitset(0111, stb.st_mode) || stb.st_nlink != 1 || (SafeFileEnv != NULL && !S_ISREG(stb.st_mode))) exit(EX_CANTCREAT); + spamcan_exists = is_spam; + } if (mode == ST_MODE_NOFILE) mode = stb.st_mode; *************** *** 3197,3206 **** } } /* select a new user to run as */ if (!bitset(SFF_RUNASREALUID, sfflags)) { ! if (bitset(S_ISUID, mode)) { RealUserName = NULL; RealUid = stb.st_uid; --- 3213,3231 ---- } } + + /* set uid and gid for spam file */ + + if ( is_spam ) { + sfflags |= SFF_ROOTOK; + } + /* select a new user to run as */ + if (!bitset(SFF_RUNASREALUID, sfflags)) { ! ! if (bitset(S_ISUID, mode) || spamcan_exists) { RealUserName = NULL; RealUid = stb.st_uid; *************** *** 3212,3217 **** --- 3237,3243 ---- else RealUserName = ctladdr->q_user; RealUid = ctladdr->q_uid; + } else if (FileMailer != NULL && FileMailer->m_uid != 0) { *************** *** 3225,3238 **** } /* select a new group to run as */ ! if (bitset(S_ISGID, mode)) RealGid = stb.st_gid; ! else if (ctladdr != NULL && ctladdr->q_uid != 0) RealGid = ctladdr->q_gid; ! else if (FileMailer != NULL && FileMailer->m_gid != 0) RealGid = FileMailer->m_gid; ! else RealGid = DefGid; } /* last ditch */ --- 3251,3281 ---- } /* select a new group to run as */ ! if ( bitset(S_ISGID, mode) || spamcan_exists ) { RealGid = stb.st_gid; ! } ! else if (ctladdr != NULL && ctladdr->q_uid != 0) { RealGid = ctladdr->q_gid; ! if (is_spam && LogLevel > 15) ! sm_syslog(LOG_DEBUG, e->e_id, ! "using cltaddr gid %d", ctladdr->q_gid); ! } ! else if (FileMailer != NULL && FileMailer->m_gid != 0) { RealGid = FileMailer->m_gid; ! sm_syslog(LOG_DEBUG, e->e_id, ! "using filemailer gid %d", FileMailer->m_gid); ! } ! else { RealGid = DefGid; + sm_syslog(LOG_DEBUG, e->e_id, + "using default gid %d", DefGid); + } + + /* spamcan diag */ + if (is_spam && LogLevel > 12) + sm_syslog(LOG_DEBUG, e->e_id, "SPAMCAN: selected owner (%d, %d) for %s", + RealUid, RealGid, filename); + } /* last ditch */ diff -rcN sendmail-8.8.8-orig/src/savemail.c sendmail-8.8.8-spamcan-96/src/savemail.c *** sendmail-8.8.8-orig/src/savemail.c Wed Oct 22 19:30:27 1997 --- sendmail-8.8.8-spamcan-96/src/savemail.c Wed Oct 29 21:38:05 1997 *************** *** 368,374 **** expand("\201z/dead.letter", buf, sizeof buf, e); flags = SFF_NOLINK|SFF_CREAT|SFF_REGONLY|SFF_RUNASREALUID; e->e_to = buf; ! if (mailfile(buf, NULL, flags, e) == EX_OK) { int oldverb = Verbose; --- 368,374 ---- expand("\201z/dead.letter", buf, sizeof buf, e); flags = SFF_NOLINK|SFF_CREAT|SFF_REGONLY|SFF_RUNASREALUID; e->e_to = buf; ! if (mailfile(buf, NULL, flags, e, 0) == EX_OK) { int oldverb = Verbose; diff -rcN sendmail-8.8.8-orig/src/sendmail.h sendmail-8.8.8-spamcan-96/src/sendmail.h *** sendmail-8.8.8-orig/src/sendmail.h Wed Oct 22 13:12:02 1997 --- sendmail-8.8.8-spamcan-96/src/sendmail.h Wed Oct 29 21:38:05 1997 *************** *** 1412,1418 **** extern void markstats __P((ENVELOPE *, ADDRESS *)); extern void poststats __P((char *)); extern char *arpadate __P((char *)); ! extern int mailfile __P((char *, ADDRESS *, int, ENVELOPE *)); extern void loseqfile __P((ENVELOPE *, char *)); extern int prog_open __P((char **, int *, ENVELOPE *)); extern bool getcanonname __P((char *, int, bool)); --- 1412,1418 ---- extern void markstats __P((ENVELOPE *, ADDRESS *)); extern void poststats __P((char *)); extern char *arpadate __P((char *)); ! extern int mailfile __P((char *, ADDRESS *, int, ENVELOPE *, int)); extern void loseqfile __P((ENVELOPE *, char *)); extern int prog_open __P((char **, int *, ENVELOPE *)); extern bool getcanonname __P((char *, int, bool)); diff -rcN sendmail-8.8.8-orig/src/spamcan.c sendmail-8.8.8-spamcan-96/src/spamcan.c *** sendmail-8.8.8-orig/src/spamcan.c Wed Dec 31 16:00:00 1969 --- sendmail-8.8.8-spamcan-96/src/spamcan.c Wed Oct 29 23:17:27 1997 *************** *** 0 **** --- 1,612 ---- + /* + + Tim Berger + timb@consult.ml.org + + Capture mail messages having regular expression matches with any + header. + + Version 0.96 + + ** + + Copyright 1997 Timothy Berger - All Rights Reserved + + This program is free software 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. + + ** + + */ + + + # include "sendmail.h" + # include "pathnames.h" + # include + # include + # include + + # ifdef __linux__ + # include + # define SPOOL_DIR "/var/spool/mail/" + # else + # include + # define SPOOL_DIR "/var/mail/" + # endif + + /* concat the spool directory with the following filename */ + + #define SPAMCAN SPOOL_DIR "spamcan" + + /* enable personal spam mail files */ + + #define PERSONAL_SPAMCAN + + /* You probably shouldn't have too many regular expressions. + This default is probably way to big. */ + + #define SPAMCAN_MAX_REGEX_COUNT 4096 + + /* for concat of header name with value */ + + #define MAX_HEADER_LENGTH 4096 + + /* The max string lengh of any regular expression. I imagine regcomp + would barf on a 4k regular expression. */ + + #define SPAMCAN_MAX_REGEX_STRLEN 4096 + + /* Allow users to disable spam capture bound for them. */ + + #define USER_CONTROL + + /* Set FILTER_DISCRIMNATION to ONE OF THESE to decide what types of + messages you don't wish to filter. Breifly, + + NO_DISCRIMINATION will make spamcan scan every mail message + connecting to your sendmail daemon. + + RELAY_DISCRIMINATION will make spamcan only scan messages + originating from discrimination_mask. + + SUBNET_DISCRIMINATION will make spamcan only scan messages not + originating from the subnet your specify in discrimination_mask. + Standard stuff from the O'Rielly Sendmail book. + + LOCALHOST_DISCRIMINATION will make spamcan scan all messages not + originating from the local machine. + + */ + + #define NO_DISCRIMINATION 0 + #define RELAY_DISCRIMINATION 1 + #define SUBNET_DISCRIMINATION 2 + #define LOCALHOST_DISCRIMINATION 3 + + #define FILTER_DISCRIMNATION LOCALHOST_DISCRIMINATION + + #define SPRINTF_BUFFSIZE 512 + + + /* + + here is an example of how to convert your ip or netmask to hex: + echo 24.1.16.108 | awk -F. '{printf("0x%02x%02x%02x%02x\n", $1, $2, $3, $4)}' + + The following discrimination mask is only used if FILTER_DISCRIMNATION + is defined as SUBNET_DISCRIMINATION + + */ + + #define SUBNET_MASK 0xffffff00 + + /* set this to your relay, local ip, or subnet mask */ + + static long discrimination_mask = 0x1801106c; + + /* the regular expression buffer */ + static char *spamcan_cf = "/etc/spamcan.cf"; + regex_t spamcan_regex_list[SPAMCAN_MAX_REGEX_COUNT]; + static int spamcan_regex_count = 0; + static int spamcan_mtime = 0; + + /* regular expressions that let mail pass through */ + static char *spamcan_exceptions = "/etc/spamcan-exceptions.cf"; + regex_t spamcan_exceptions_list[SPAMCAN_MAX_REGEX_COUNT]; + static int spamcan_rx_exceptions_count = 0; + static int spamcan_exceptions_mtime = 0; + + void spamcan_load_regex(filename, explist, expcount, filename_mtime ) + char *filename; + regex_t *explist; + int *expcount, *filename_mtime; + { + + int loop; + FILE *fp; + struct stat st; + int error; + char regex_message[SPAMCAN_MAX_REGEX_STRLEN]; + char regexbuff[SPAMCAN_MAX_REGEX_STRLEN]; + + if (stat(filename, &st) == -1) { + sm_syslog(LOG_DEBUG, NOQID, "SPAMCAN: Can't stat %s", filename); + return; + } + + if ( st.st_mtime > *filename_mtime ) { + *filename_mtime = st.st_mtime; + } + else { + return; + } + + if ( ! (fp = fopen(filename, "r")) ) { + sm_syslog(LOG_DEBUG, NOQID, "SPAMCAN: Problem reading %s", filename); + return; + } + + if (LogLevel > 12) + sm_syslog(LOG_DEBUG, NOQID, "SPAMCAN: Loading spam file %s", filename); + + loop = 0; + while( (fgets(regexbuff, SPAMCAN_MAX_REGEX_STRLEN, fp) != NULL) && loop < SPAMCAN_MAX_REGEX_COUNT ) { + *(regexbuff + strlen(regexbuff) -1 ) = '\0'; + if (strlen(regexbuff) < 4) { + sm_syslog(LOG_DEBUG, NOQID, "SPAMCAN: expression [%s] from [%s] is too small, possible typo", + regexbuff, filename); + continue; + } + if (LogLevel > 19) + sm_syslog(LOG_DEBUG, NOQID, "SPAMCAN: read expression %s", regexbuff); + if ( (error=regcomp(& explist[loop], regexbuff, REG_EXTENDED|REG_ICASE)) ) { + regerror(error, & explist[loop], regex_message, (size_t)SPAMCAN_MAX_REGEX_STRLEN); + sm_syslog(LOG_DEBUG, NOQID, "SPAMCAN: unable to compile expression [%s] from [%s]. index = %d, %s", + regexbuff, filename, loop, regex_message); + } + else { + if (LogLevel > 12) + sm_syslog(LOG_DEBUG, NOQID, "SPAMCAN: compiled expression [%s] to index %d", + regexbuff, loop); + loop++; + } + } + + fclose (fp); + + *expcount = loop; + + if (LogLevel > 12) + sm_syslog(LOG_DEBUG, NOQID, "SPAMCAN: Compiled %d regular expressions", + *expcount); + + + } + + void spamcan_mark_to_save(to, e, reason, to_username, to_uid) + ADDRESS *to; + ENVELOPE *e; + char *reason; + char *to_username; + uid_t to_uid; + { + + char *spamcap; + HDR *header; + int found; + char *personal_spamcan; + struct stat st; + + personal_spamcan = NULL; + + #if defined(PERSONAL_SPAMCAN) + + if (to_username != NULL) { + personal_spamcan = (char*) + malloc( strlen(SPOOL_DIR) + strlen(to_username) + strlen(".spam") + 1 ); + + if (personal_spamcan == NULL) { + sm_syslog(LOG_DEBUG, e->e_id, "SPAMCAN: out of memory"); + return; + } + + strcpy(personal_spamcan, SPOOL_DIR); + strcat(personal_spamcan, to_username); + strcat(personal_spamcan, ".spam"); + if (stat(personal_spamcan, &st) == 0) { + if (to_uid == st.st_uid) { + to->q_user = personal_spamcan; + to->q_mailer = FileMailer; + } + else { + sm_syslog(LOG_DEBUG, e->e_id, "SPAMCAN: %s exists, but has wrong ownership %d", + personal_spamcan, st.st_uid); + } + } + } + else { + sm_syslog(LOG_DEBUG, e->e_id, "username is NULL"); + } + + #endif + + if (personal_spamcan != to->q_user) { + spamcap = (char *)malloc( strlen(SPAMCAN ) + 1 ); + + if (spamcap == NULL) { + sm_syslog(LOG_DEBUG, e->e_id, "out of memory"); + return; + } + + strcpy (spamcap, SPAMCAN); + to->q_user = spamcap; + to->q_mailer = FileMailer; + } + + if (LogLevel > 9) + sm_syslog(LOG_DEBUG, e->e_id, "SPAMCAN: selected spamcan %s", + to->q_user); + + for(header = e->e_header, found = 0; header && !found; header = header->h_link) { + if ( strcasecmp("X-Spamcan-Reason", header->h_field) == 0) { + header->h_value = reason; + found = 1; + } + } + + if ( !found ) { + addheader("X-Spamcan-Reason", reason, &e->e_header); + } + + } + + int spamcan_find_header(e, name, value) + ENVELOPE *e; + char *name, **value; + { + HDR *h_ptr; + int found = 0; + + for(h_ptr = e->e_header;h_ptr != NULL; h_ptr = h_ptr->h_link) { + if (strcasecmp(name, h_ptr->h_field) == 0) { + *value = h_ptr->h_value; + return (1); + } + } + return(0); + + } + + + /* This is completely incompatable with most mailing lists. + Forget this for now. May use some of this code in a future release */ + + int sanity_check(to, e, to_username, to_uid) + ADDRESS *to; + ENVELOPE *e; + char *to_username; + uid_t to_uid; + { + char *print_to; + HDR *h_ptr; + char *from_header, *to_header, *reply_header, *sender_header; + char *reason_alloc; + char reason[SPRINTF_BUFFSIZE]; + ADDRESS *ctladdr; + + reason_alloc = (char*)malloc(SPRINTF_BUFFSIZE); + + if ( reason_alloc == NULL) { + sm_syslog(LOG_DEBUG, e->e_id, "out of memory"); + return(0); + } + + + if (to_username != NULL) { + print_to = to_username; + } + else { + print_to = to->q_user; + ctladdr = getctladdr(to); + if ( ctladdr != NULL ) { + if (ctladdr->q_user != NULL) { + print_to = ctladdr->q_user; + } + } + } + + + /* don't accept outside mail without to header */ + + if( !spamcan_find_header(e, "To", &to_header) ) { + sprintf(reason, "No \"To\" header from [%s] to [%s]", + e->e_from.q_paddr, print_to ); + strcpy(reason_alloc, reason); + sm_syslog(LOG_DEBUG, e->e_id, "SPAMCAN: %s", reason_alloc); + spamcan_mark_to_save(to, e, reason_alloc, to_username, to_uid); + return (1); + } + + /* don't accept outside mail without from header */ + + if ( !spamcan_find_header(e, "From", &from_header) ) { + sprintf(reason, "No \"From\" header from [%s] to [%s]", + e->e_from.q_paddr, print_to ); + strcpy(reason_alloc, reason); + sm_syslog(LOG_DEBUG, e->e_id, "SPAMCAN: %s", reason_alloc); + spamcan_mark_to_save(to, e, reason_alloc, to_username, to_uid); + return (1); + } + + /* check if to matches from */ + + if ( strcasecmp(from_header, to_header) == 0) { + sprintf(reason, "Identical headers \"From\" and \"To\" from [%s] to [%s]", + e->e_from.q_paddr, print_to ); + strcpy(reason_alloc, reason); + sm_syslog(LOG_DEBUG, e->e_id, "SPAMCAN: %s", reason_alloc); + spamcan_mark_to_save(to, e, reason_alloc, to_username, to_uid); + return(1); + } + + /* check if to matches reply-to */ + + if ( spamcan_find_header(e, "Reply-To", &reply_header)) { + if ( strcasecmp(to_header, reply_header) == 0) { + sprintf(reason, "Identical headers \"Reply-To\" and \"To\" from [%s] to [%s]", + e->e_from.q_paddr, print_to ); + strcpy(reason_alloc, reason); + sm_syslog(LOG_DEBUG, e->e_id, "SPAMCAN: %s", reason_alloc); + spamcan_mark_to_save(to, e, reason_alloc, to_username, to_uid); + return(1); + } + } + + /* check if sender maches to */ + + if ( spamcan_find_header(e, "Sender", &sender_header)) { + if ( strcasecmp(to_header, sender_header) == 0) { + sprintf(reason, "Identical headers \"Sender\" and \"To\" from [%s] to [%s]", + e->e_from.q_paddr, print_to ); + strcpy(reason_alloc, reason); + sm_syslog(LOG_DEBUG, e->e_id, "SPAMCAN: %s", reason_alloc); + spamcan_mark_to_save(to, e, reason_alloc, to_username, to_uid); + return(1); + } + } + + + return (0); + + } + + + int spamcan_match ( name, substr, e, to, to_username, to_uid ) + char *name; + char *substr; + ENVELOPE *e; + ADDRESS *to; + char *to_username; + uid_t to_uid; + + { + + int loop, error; + regmatch_t pmatch[1]; + char reason_prime[SPRINTF_BUFFSIZE], reason[SPRINTF_BUFFSIZE], *reason_alloc; + char *print_to; + ADDRESS *ctladdr; + + reason_alloc = (char*)malloc(SPRINTF_BUFFSIZE); + + if ( reason_alloc == NULL) { + sm_syslog(LOG_DEBUG, e->e_id, "out of memory"); + return(0); + } + + if (to_username != NULL) { + print_to = to_username; + } + else { + print_to = to->q_user; + ctladdr = getctladdr(to); + if ( ctladdr != NULL ) { + if (ctladdr->q_user != NULL) { + print_to = ctladdr->q_user; + } + } + } + + + + for(loop = 0; loop < spamcan_regex_count; ++loop) { + + /* sm_syslog(LOG_DEBUG, e->e_id, "SPAMCAN: looking at string [%s]", substr); */ + + if ( (error=regexec(& spamcan_regex_list[loop], + substr, 1, &pmatch[0], 0)) == 0) { + /* sm_syslog(LOG_DEBUG, e->e_id, "there was a match"); */ + snprintf(reason_prime, SPRINTF_BUFFSIZE, + "substring [%%.%ds] matched [%%s] with expression [#%%d] from [%s] to [%s]", + pmatch[0].rm_eo - pmatch[0].rm_so, + e->e_from.q_paddr, + print_to ); + snprintf(reason, SPRINTF_BUFFSIZE, reason_prime, + substr + pmatch[0].rm_so, name, loop); + + sm_syslog(LOG_DEBUG, e->e_id, "SPAMCAN: %s", reason); + strcpy(reason_alloc, reason); + spamcan_mark_to_save(to, e, reason_alloc, to_username, to_uid); + return( 1 ); + } + else { + /* sm_syslog(LOG_DEBUG, e->e_id, "No match with regex #%d", loop); */ + } + } + + return( 0 ); + + } + + int spamcan(to, e, is_spam ) + register ADDRESS *to; + register ENVELOPE *e; + int *is_spam; + + { + HDR *h_ptr; + struct stat st; + char user_disable_spamcan_file[512]; + char *to_username; + struct passwd *pwent; + ADDRESS *alist; + int username_found; + uid_t to_uid; + char full_header[MAX_HEADER_LENGTH]; + struct in_addr natural_in; + int loop; + + *is_spam = 0; + + if ( RealHostAddr.sa.sa_family != AF_INET ) + return (EX_OK); + + if( RealHostAddr.sin.sin_addr.s_addr == 0x7f000001 ) + return( EX_OK ); + + /* Convert net byte order to host byte order - toivo@ucs.uwa.edu.au */ + natural_in.s_addr = ntohl(RealHostAddr.sin.sin_addr.s_addr); + + /* pass through locally generated mail - check specific ip address */ + + if ( FILTER_DISCRIMNATION == LOCALHOST_DISCRIMINATION && + natural_in.s_addr == discrimination_mask ) + return( EX_OK ); + + /* don't filter mail unless from relay */ + + if ( FILTER_DISCRIMNATION == RELAY_DISCRIMINATION && + natural_in.s_addr != discrimination_mask) + return ( EX_OK ); + + /* don't filter mail generated from specified subnet */ + if ( FILTER_DISCRIMNATION == SUBNET_DISCRIMINATION && + (natural_in.s_addr & SUBNET_MASK) == discrimination_mask + ) + return ( EX_OK ); + + /* pass through mail with In-Reply-To header */ + for(h_ptr = e->e_header;h_ptr != NULL; h_ptr = h_ptr->h_link) { + if ( (strcasecmp("In-reply-to", h_ptr->h_field) == 0) ) + return (EX_OK); + } + + username_found = 0; + to_username = NULL; + alist = to; + while ( alist && ! username_found) { + pwent = getpwnam(alist->q_user); + if (pwent != NULL) { + to_username = alist->q_user; + to_uid = pwent->pw_uid; + username_found = 1; + } + alist = alist->q_alias; + } + + #if defined(USER_CONTROL) + + /* Need to know username here. If I knew how to get this reliably any + other way this wouldn't be necessary. */ + + strcpy(user_disable_spamcan_file, SPOOL_DIR ".nospamcan."); + if ( username_found ) { + strcat(user_disable_spamcan_file, to_username); + if (LogLevel > 12) + sm_syslog(LOG_DEBUG, e->e_id, + "SPAMCAN: Checking for file %s", user_disable_spamcan_file); + } + + if( stat(user_disable_spamcan_file, &st) == 0 && to_username != NULL) { + if( to_uid == st.st_uid) { + sm_syslog(LOG_DEBUG, e->e_id, "SPAMCAN: %s exists, not capturing mail for %s", + user_disable_spamcan_file, to_username); + return (EX_OK); + } + else { + sm_syslog(LOG_DEBUG, e->e_id, "SPAMCAN: %s exists but has wrong ownership %d", + user_disable_spamcan_file, st.st_uid); + } + } + + #endif + + spamcan_load_regex(spamcan_cf, spamcan_regex_list, &spamcan_regex_count, + &spamcan_mtime); + + /* load exceptions */ + + spamcan_load_regex(spamcan_exceptions, spamcan_exceptions_list, + &spamcan_rx_exceptions_count, &spamcan_exceptions_mtime); + + for(h_ptr = e->e_header; h_ptr != NULL; h_ptr = h_ptr->h_link) { + for(loop=0; loop < spamcan_rx_exceptions_count; ++loop) { + if ( h_ptr->h_value != NULL && + regexec( &spamcan_exceptions_list[loop], h_ptr->h_value, + 0, NULL, 0) == 0) { + if (LogLevel > 12) + sm_syslog(LOG_DEBUG, e->e_id, "SPAMCAN: Passing message through"); + return(EX_OK); + } + } + } + + /* check each header for a match */ + + for(h_ptr = e->e_header; h_ptr != NULL; h_ptr = h_ptr->h_link) { + + /* skip the message id header, it contains nothing useful + and may cause filtering problems */ + + if ( (strcasecmp( "Message-Id", h_ptr->h_field) == 0) ) + continue; + + if ( (strcasecmp( "Resent-Message-Id", h_ptr->h_field) == 0) ) + continue; + + /* terminate last byte with null character in the event that we run out of space */ + + *( full_header + MAX_HEADER_LENGTH - 1 ) = '\0'; + + strncpy(full_header, h_ptr->h_field, MAX_HEADER_LENGTH - 1); + + strncpy(full_header + strlen(full_header), ": ", + MAX_HEADER_LENGTH - 1 - strlen(full_header) ); + + if ( h_ptr->h_value != NULL ) { + strncpy(full_header + strlen(full_header), h_ptr->h_value, + MAX_HEADER_LENGTH - 1 - strlen(full_header)); + } + + + if ( spamcan_match(h_ptr->h_field, full_header, e, to, to_username, to_uid) ) { + *is_spam = 1; + return( EX_OK); + } + + } + + /* skip possibly null ? value for envelope sender */ + + if (e->e_from.q_paddr == NULL) { + return(EX_OK); + } + + if ( spamcan_match("Sender from Envelope", e->e_from.q_paddr, e, to, to_username, to_uid) ) { + *is_spam = 1; + return ( EX_OK ); + } + + return(EX_OK); + }