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.
+
+
+
+
+
+ - It's not a good idea to mess with your relay host since it
+ resides outside the firewall. Since you're beind the firewall, it's
+ probably inconvenient to mess with anything on the other side.
+
+ - Users at your site may choose not to have Spamcan scan
+ their mail by touching /var/spool/mail/.nospamcan.username.
+ Spamcan needs to look for this.
+
+
- Users at your site may choose to have spam directed a personal
+ spam mailbox owned by them by touching /var/spool/mail/username.spam.
+
+
+
+ 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);
+ }
.