diff -rcN sendmail-8.8.7-orig/COPYING.SPAMCAN sendmail-8.8.7-spamcan-95/COPYING.SPAMCAN *** sendmail-8.8.7-orig/COPYING.SPAMCAN Wed Dec 31 16:00:00 1969 --- sendmail-8.8.7-spamcan-95/COPYING.SPAMCAN Sat Sep 20 18:53:01 1997 *************** *** 0 **** --- 1,2 ---- + + This version is hereby in the public domain. There is no warranty. diff -rcN sendmail-8.8.7-orig/COPYRIGHT.SPAMCAN sendmail-8.8.7-spamcan-95/COPYRIGHT.SPAMCAN *** sendmail-8.8.7-orig/COPYRIGHT.SPAMCAN Wed Dec 31 16:00:00 1969 --- sendmail-8.8.7-spamcan-95/COPYRIGHT.SPAMCAN Sat Sep 20 18:54:18 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.7-orig/INSTALL.SPAMCAN sendmail-8.8.7-spamcan-95/INSTALL.SPAMCAN *** sendmail-8.8.7-orig/INSTALL.SPAMCAN Wed Dec 31 16:00:00 1969 --- sendmail-8.8.7-spamcan-95/INSTALL.SPAMCAN Tue Sep 30 00:14:00 1997 *************** *** 0 **** --- 1,32 ---- + + 1) Apply context diff to clean Sendmail 8.8.7 distribution. + You might need gnu patch. + + Eg: + tar xzvf sendmail.8.8.7.tar.gz + tar xzvf spamcan.tar.gz + cd sendmail-8.8.7 + patch -p1 < ../spamcan_for_v887_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) Create /etc/spamcan.cf and put some regular expressions there. + An example regular expression file has been included. + + 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.7-orig/NEWS.SPAMCAN sendmail-8.8.7-spamcan-95/NEWS.SPAMCAN *** sendmail-8.8.7-orig/NEWS.SPAMCAN Wed Dec 31 16:00:00 1969 --- sendmail-8.8.7-spamcan-95/NEWS.SPAMCAN Mon Sep 29 23:42:14 1997 *************** *** 0 **** --- 1,47 ---- + + 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.7-orig/TODO.SPAMCAN sendmail-8.8.7-spamcan-95/TODO.SPAMCAN *** sendmail-8.8.7-orig/TODO.SPAMCAN Wed Dec 31 16:00:00 1969 --- sendmail-8.8.7-spamcan-95/TODO.SPAMCAN Mon Sep 29 23:52:31 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.7-orig/sample-spamcan.cf sendmail-8.8.7-spamcan-95/sample-spamcan.cf *** sendmail-8.8.7-orig/sample-spamcan.cf Wed Dec 31 16:00:00 1969 --- sendmail-8.8.7-spamcan-95/sample-spamcan.cf Thu Aug 21 23:27:45 1997 *************** *** 0 **** --- 1,39 ---- + productlink@earthlink\.com + sales@claythay\.com + keepmailing + x-advertisement + sexyhot + marathon4com + (^Subject:.*(free|making).*money) + fresh.*addresses + mega-mailer + ExtractorPro + ((stealth|mass).*mailer) + corporate.*marketing.*lists + marketing.*make.*you.*rich + make.*money.*fast + health\.information\.news + mail.*for.*sale + million.*messages.*per.*hour + message.*millions.*hour + bulk.*mail + (^(From|To):.*[0-9]{8}@.*\.(org|net|com)) + (cyber(market|shop|promo|gold)) + e-mail.*marketing + ((From|To):.*(sales|srhot|foryou|allvip|mailman|succeed|success|everyon|megaweb|emailer|allinternetusers|market|4u|Friend)@.*\.(org|net|com)) + ((sallynet|scholarship|shoppingplanet|answerme|onlineprofit|yourdomain|ispam|devotion|quantcom|savetrees|nowhere|bank)\.(com|org)) + ^\$.*per.*month + ^\$.*a.*minute + E-X-P-0-S-E + major.*credit.*card + --- CLOAKED! --- + Internet\.Mail\.Delivery + low.*cost.*service + (long.*distance.*(service|rates)) + ^([a-z]*[0-9]+@juno.com) + Adults Only + (international.*(rates|service)) + VideoSex + (Floodgate.*(pro|bulk)) + save.*over.*[0-9]+% + save the [a-z]+.*(!|\*).*(!|\*) diff -rcN sendmail-8.8.7-orig/spamcan.html sendmail-8.8.7-spamcan-95/spamcan.html *** sendmail-8.8.7-orig/spamcan.html Wed Dec 31 16:00:00 1969 --- sendmail-8.8.7-spamcan-95/spamcan.html Thu Aug 21 23:27:45 1997 *************** *** 0 **** --- 1,137 ---- + + + + Spamcan: A Sendmail patch to capture spam by regular expression + + + + + +

Spamcan: A Sendmail patch to capture spam by regular expression + +

+

+
Get the current release
+ +

+
+
+ +

+ + Spamcan is a simple yet extremely powerful junkmail + capturing/nuking sofware patch to Sendmail v8. It is designed to + capture site-wide junkmail to a global capture file, a user owned spam + mailbox if it exists, or to /dev/null. + +

+ + While user-level filtering programs such as procmail may be used to + filter out spam by regular expression, Spamcan is the first of it's + kind designed to capture spam site-wide by regular expression. In my + experience, bouncing spam is futile and wasts bandwidth. Most spam + has forged addresses and invalid return addresses. + +

+ + Spamcan was written with the philosophy that unsolicited email is an + evil and disruptive presence. In my opinion it is unreasonable to + ask or require each and every user at a site with hundreds of users to + put up with unsolicited email or to manage their own anti-spam rules. + I beleve it is up to the system administration group to provide + excellent service to the user community and I belive Spamcan is a + powerful tool that aids in providing excellent service. + +

+ + Spamcan works by comparing every header line of a mail message, + including subject line, with a list of regular expressions you've + prepared. By default matching is not case sensitive. The expression + list typically contains lines such as the following: + +

+ x-advertisement
+ sexyhot
+ (Subject: ((free|making).*money))
+ fresh.*addresses
+ mega-mailer
+ ExtractorPro
+ ((stealth|mass).*mailer)
+ make.*money.*fast
+ ((From|To): ([0-9]{8}@.*\.(org|net|com)))
+ (cyber(market|shop|promo|gold))
+ ((sales|srhot|foryou|allvip|mailman|succeed|success|everyon|megaweb|emailer|allinternetusers|market|4u|Friend)@.*\.(org|net|com))
+ ((sallynet|scholarship|shoppingplanet|answerme|onlineprofit|yourdomain|ispam|devotion|quantcom|savetrees|nowhere|bank)\.(com|org))
+ --- CLOAKED! ---
+ 
+ + The envelope "from" is also examined. Using regular expressions + is a very powerful and dangerous capability. Extreme caution must be + taken in formulating your expressions. Fortunately, Spamcan does not + discard or bounce email. Rather, Spamcan cans it to a + spamcan. In the unfortunate event that you've managed to + capture non-spam, it may be forwarded to the appropriate user. + Spamcan adds the header X-Spamcan-Reason to every message it + identifies as spam before sending it to the spamcan. It contains the + reason for identifying the mail as spam and the intended recipient. + +

+ + All spamcan diagnostics are logged via syslog with the mail facility + at the debug level. Look for any problems relating to spamcan there. + +

+ + Spamcan was designed to be installed on the internal mailhost for + several reasons. /var/spool/mail is used for username.spam and + .nospamcan.username because in many installations it is + globablly writable. It's generally not a good idea to access user + home directories because large mail distributions may cause your + automounter to mount everyone's home. I recommend you don't do this + with .forward either. + +

+ +

+ + Spamcan was designed stay out of the way of valid mail message + traffic. It examines all non-message-id headers. Internal mail and + outgoing mail is not examined. Incoming mail messages containing the + in-reply-to header are also passed through un-examined. If spammers + use this as a back-door this feature may have to be removed. + +

+ + Spamcan is known to work on Linux, Solaris and Irix but I'm sure it + would not take much to make it work on other platforms. + +

+ + Please let me know if you find Spamcan useful. Send bug reports, + enhancements, or comments to + spamcan-proj@consult.ml.org + +

+ + I'm always interested in hearing from sites that have feedback, + good or bad.
+

+

+ Tim Berger + + + diff -rcN sendmail-8.8.7-orig/spamreport.pl sendmail-8.8.7-spamcan-95/spamreport.pl *** sendmail-8.8.7-orig/spamreport.pl Wed Dec 31 16:00:00 1969 --- sendmail-8.8.7-spamcan-95/spamreport.pl Thu Aug 21 23:27:45 1997 *************** *** 0 **** --- 1,25 ---- + #!/usr/local/bin/perl + + # Tim Berger + # 7.7.97 + + $spamcan = "/var/mail/spamcan"; + + print "Content-Type: text/plain\n\n"; + + print "Captured Spam\n\n"; + + open(SPAMCAN, $spamcan) || print "Unavailable"; + + $date = 0; + while () { + if (/^Date: ([a-z]{3}), ([0-9]{1,2}) ([a-z]{3})/i && $date == 0) { + print "$3 $2: "; + $date = 1; + } + if (/^X-Spamcan-Reason: (.*)/ && $date == 1) { + print "$1\n"; + $date = 0; + } + } + diff -rcN sendmail-8.8.7-orig/src/Makefiles/Makefile.Linux sendmail-8.8.7-spamcan-95/src/Makefiles/Makefile.Linux *** sendmail-8.8.7-orig/src/Makefiles/Makefile.Linux Sun Jul 6 11:22:57 1997 --- sendmail-8.8.7-spamcan-95/src/Makefiles/Makefile.Linux Thu Aug 21 23:27:45 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.7-orig/src/Makefiles/Makefile.SunOS.5.1 sendmail-8.8.7-spamcan-95/src/Makefiles/Makefile.SunOS.5.1 *** sendmail-8.8.7-orig/src/Makefiles/Makefile.SunOS.5.1 Tue Jun 24 14:56:27 1997 --- sendmail-8.8.7-spamcan-95/src/Makefiles/Makefile.SunOS.5.1 Thu Aug 21 23:27:45 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.7-orig/src/Makefiles/Makefile.SunOS.5.2 sendmail-8.8.7-spamcan-95/src/Makefiles/Makefile.SunOS.5.2 *** sendmail-8.8.7-orig/src/Makefiles/Makefile.SunOS.5.2 Tue Jun 24 14:56:27 1997 --- sendmail-8.8.7-spamcan-95/src/Makefiles/Makefile.SunOS.5.2 Thu Aug 21 23:27:45 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.7-orig/src/Makefiles/Makefile.SunOS.5.3 sendmail-8.8.7-spamcan-95/src/Makefiles/Makefile.SunOS.5.3 *** sendmail-8.8.7-orig/src/Makefiles/Makefile.SunOS.5.3 Tue Jun 24 14:56:27 1997 --- sendmail-8.8.7-spamcan-95/src/Makefiles/Makefile.SunOS.5.3 Thu Aug 21 23:27:45 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.7-orig/src/Makefiles/Makefile.SunOS.5.4 sendmail-8.8.7-spamcan-95/src/Makefiles/Makefile.SunOS.5.4 *** sendmail-8.8.7-orig/src/Makefiles/Makefile.SunOS.5.4 Tue Jun 24 14:56:27 1997 --- sendmail-8.8.7-spamcan-95/src/Makefiles/Makefile.SunOS.5.4 Thu Aug 21 23:27:45 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.7-orig/src/Makefiles/Makefile.SunOS.5.5 sendmail-8.8.7-spamcan-95/src/Makefiles/Makefile.SunOS.5.5 *** sendmail-8.8.7-orig/src/Makefiles/Makefile.SunOS.5.5 Tue Jun 24 14:56:27 1997 --- sendmail-8.8.7-spamcan-95/src/Makefiles/Makefile.SunOS.5.5 Thu Aug 21 23:27:45 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.7-orig/src/Makefiles/Makefile.SunOS.5.6 sendmail-8.8.7-spamcan-95/src/Makefiles/Makefile.SunOS.5.6 *** sendmail-8.8.7-orig/src/Makefiles/Makefile.SunOS.5.6 Tue Jun 24 14:56:27 1997 --- sendmail-8.8.7-spamcan-95/src/Makefiles/Makefile.SunOS.5.6 Thu Aug 21 23:27:45 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.7-orig/src/SPAMCAN.CREDITS sendmail-8.8.7-spamcan-95/src/SPAMCAN.CREDITS *** sendmail-8.8.7-orig/src/SPAMCAN.CREDITS Wed Dec 31 16:00:00 1969 --- sendmail-8.8.7-spamcan-95/src/SPAMCAN.CREDITS Fri Aug 22 00:07:36 1997 *************** *** 0 **** --- 1,3 ---- + + Credits/Notes + diff -rcN sendmail-8.8.7-orig/src/conf.c sendmail-8.8.7-spamcan-95/src/conf.c *** sendmail-8.8.7-orig/src/conf.c Sat Aug 2 11:06:54 1997 --- sendmail-8.8.7-spamcan-95/src/conf.c Thu Aug 21 23:27:45 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 *************** *** 2929,2935 **** * 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; --- 2940,2946 ---- * 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.7-orig/src/deliver.c sendmail-8.8.7-spamcan-95/src/deliver.c *** sendmail-8.8.7-orig/src/deliver.c Sat Aug 2 08:05:09 1997 --- sendmail-8.8.7-spamcan-95/src/deliver.c Mon Sep 29 23:35:46 1997 *************** *** 860,865 **** --- 860,866 ---- 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)) *************** *** 1027,1032 **** --- 1028,1034 ---- user = to->q_user; e->e_to = to->q_paddr; + if (tTd(10, 5)) { printf("deliver: QDONTSEND "); *************** *** 1057,1071 **** 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 --- 1059,1079 ---- 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 *************** *** 1079,1086 **** } /* hack attack -- delivermail compatibility */ ! if (m == ProgMailer && *user == '|') ! user++; /* ** If an error message has already been given, don't --- 1087,1095 ---- } /* hack attack -- delivermail compatibility */ ! if (m == ProgMailer && *user == '|') { ! user++; ! } /* ** If an error message has already been given, don't *************** *** 1092,1098 **** */ if (bitset(QBADADDR|QQUEUEUP, to->q_flags)) ! continue; /* ** See if this user name is "special". --- 1101,1107 ---- */ if (bitset(QBADADDR|QQUEUEUP, to->q_flags)) ! continue; /* ** See if this user name is "special". *************** *** 1104,1110 **** 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) --- 1113,1120 ---- 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) *************** *** 1559,1564 **** --- 1569,1575 ---- (void) setsignal(SIGHUP, SIG_IGN); (void) setsignal(SIGTERM, SIG_DFL); + if (m != FileMailer || stat(tochain->q_user, &stb) < 0) stb.st_mode = 0; *************** *** 3097,3112 **** */ int ! mailfile(filename, ctladdr, sfflags, e) char *filename; ADDRESS *ctladdr; int sfflags; register ENVELOPE *e; { register FILE *f; register pid_t pid = -1; int mode = ST_MODE_NOFILE; bool suidwarn = geteuid() == 0; if (tTd(11, 1)) { --- 3108,3126 ---- */ int ! mailfile(filename, ctladdr, sfflags, e, is_spam) char *filename; ADDRESS *ctladdr; int sfflags; register ENVELOPE *e; + int is_spam; { register FILE *f; register pid_t pid = -1; int mode = ST_MODE_NOFILE; bool suidwarn = geteuid() == 0; + int spamcan_exists = 0; + if (tTd(11, 1)) { *************** *** 3162,3170 **** 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; --- 3176,3187 ---- 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; *************** *** 3191,3200 **** } } /* select a new user to run as */ if (!bitset(SFF_RUNASREALUID, sfflags)) { ! if (bitset(S_ISUID, mode)) { RealUserName = NULL; RealUid = stb.st_uid; --- 3208,3226 ---- } } + + /* 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; *************** *** 3206,3211 **** --- 3232,3238 ---- else RealUserName = ctladdr->q_user; RealUid = ctladdr->q_uid; + } else if (FileMailer != NULL && FileMailer->m_uid != 0) { *************** *** 3219,3232 **** } /* 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 */ --- 3246,3276 ---- } /* 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.7-orig/src/savemail.c sendmail-8.8.7-spamcan-95/src/savemail.c *** sendmail-8.8.7-orig/src/savemail.c Sat Aug 2 11:06:53 1997 --- sendmail-8.8.7-spamcan-95/src/savemail.c Thu Aug 21 23:27:45 1997 *************** *** 348,354 **** 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; --- 348,354 ---- 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.7-orig/src/sendmail.h sendmail-8.8.7-spamcan-95/src/sendmail.h *** sendmail-8.8.7-orig/src/sendmail.h Sat Aug 2 11:06:53 1997 --- sendmail-8.8.7-spamcan-95/src/sendmail.h Thu Aug 21 23:27:45 1997 *************** *** 1411,1417 **** 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)); --- 1411,1417 ---- 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.7-orig/src/spamcan.c sendmail-8.8.7-spamcan-95/src/spamcan.c *** sendmail-8.8.7-orig/src/spamcan.c Wed Dec 31 16:00:00 1969 --- sendmail-8.8.7-spamcan-95/src/spamcan.c Mon Sep 29 23:39:35 1997 *************** *** 0 **** --- 1,612 ---- + /* + + Tim Berger + timb@consult.ml.org + + Capture mail messages having regular expression matches with any + header. + + Version 0.95 + + ** + + 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); + } .