/****************************************************************************
* SCM Vn 2.0  April 2004
* Developed by Mike Eggleston (Fenland Software Ltd) from
*
*        spam mail counter-measure (SCM Vn 1.4)
*        By Jason Nunn <jsno@downunder.net.au>, May 2000
*        Darwin, NT, Australia
*
* Copyright (c) 2000  Jason Dunn
* Additional Code Copyright (c) 2004 Fenland Software Ltd 
*****************************************************************************/

Introduction
------------

When I was looking for a spam filter I chanced upon SCM Vn 1.4 by Jason 
Nunn.  It seemed to be just the type of thing I wanted but configuring it 
in a multi-user environment wasn't going the be simple - every user would 
need to maintain their own list of blocked and allowed addresses. I could 
see there was a lot of untapped potential to it though so I set about 
adding some enhancements.  This is the result.  The basic fucntionality 
remains the same and this version will continue to work with your existing 
.scmrc files with one small change - if you "notify_spammer" you will need 
to move the text of the 'reply_message' to a separate file.  You the need 
to specify the full path and name of that file in your .scmrc file by 
adding the line 

	reject_letter: path/filename

where /path/filename is the path and file name of your reply message.


'allow:', 'deny:' 'dump:' and 'me:' lists
-----------------------------------------

filtering rules are split into three groups- allow, deny and me. If you
have a look at the sample scmrc file provided, you will get the gist 
of their functions, but here is the brief description of each-

- The 'allow:' list tells SCM who you want to allow through.

- The 'deny:' list tells SCM who you want to filter.

- The 'dump:' list works like 'deny:' but doesn't send a 'reject-letter'.

- The 'me:' list tells SCM who you are, and what email addresses you have.

Entries in the lists can have wildcards. The supplied scmrc file 
gives examples.

An external allow/deny file can also be specfied and shared by several 
users.  This avoids have to duplicate the lists in each user's .scmrc 
file and also allows for automatic updating (see below).  The only 
directives allowed in this file are "allow: " and "deny: " - anything else 
is ignored.  Individual users can still "allow" an email address, even 
if it's given as "deny: " in this file, by specifying it in their own 
.scmrc file. 


How/What it Filters (in the order it does it)
---------------------------------------------

- First tests that the address in the "reply-to:" field resolves. If the
email header doesn't have a "reply-to:" field, then it tests for a
resolvable address in the "From:" field. If the selected field tested
doesn't resolve, then email is filtered.

- tests "to:", "from:", "reply-to:", "x-sender:", "return-path:", "CC:"
against any instances in the Deny list. If a match is found, then email is
filtered.

- tests the "From:" and "reply-to:" fields for any addresses that are
allowed. If any are found, email is accepted (even if it was previously
filtered by previous tests).

- tests the "From:" field. If our email address appears, then it's
filtered. This is very common practice for spammers to do this.  This 
directive overrides the "allow:" directive.

If the "filter" directive is defined, then SCM will filter messages. This 
is handy for testing purposes, because if you can disenable filtering by 
uncommenting this directive, and find out what SCM would have done to a 
given message by looking at the SCM status line at the bottom of the 
email.

If the "notify_spammer" directive is defined, then any email that is
filtered, the program will email them the message stored in the file 
specified by "reject_letter: " in your ~/.scmrc file.  It will first 
test the "Reply-To:" address.  If to resolves, they will be emailed using 
that address.  If it doesn't, then the "From:" address is tried. If no 
fields resolve, then SCM won't send them the message.

There is a potential danger in the above that the spammer has used a 
"From" address which bounces your email.  Your rejection message would be 
bounced back to your and SCM would immediately see it as a new spam mail 
and bounce it back again.  To prevent this, you can override your "From" 
address with the "reject_from:" parameter.  If you set this to an email 
address pointing to /dev/null the returned email will disappear into 
the bottomles pit.

If a spammer has sent us an email with our address in the "From:" or 
"Reply-to", then SCM won't attempt to reply - a circular condition will 
arise if it did.

If the "save_spam" directive is defined in .scmrc, then rejected emails 
are appended to ~/mail/spam.rejected.

If the "print_log" directive is defined, then SCM will save logs for a
given process in the directory ~/mail. It will create one log file for
each process executed.

In the event that a normal user is blocked, SCM will allow that user 
to get their email through to you by putting "==exemption==" in the 
subject field (this is configurable using the "exemption_tok:" directive 
in .scmrc). This will allow their email to get through, but their email 
body will be truncated to 'n' characters (configurable using "truncation:" 
directive).

If the "upd_allow_deny" directive is defined, an "==exemption==" will add 
the sender's email address to the "allow: " list.  The "accept_letter" (if 
defined) will be sent to inform them that they can send emails normally.
The "From" address can also be overridden like the "reject_letter".




SCM Status Line entries and what they mean
----------------------------------------------

After screening an email, SCM will append a status line on the end of the 
email to tell you what tests passed/failed, and what it done with it.

ie-

<Email header>

<Email body>

--
SCM Vn 2.0  [FM:DENY] [!F]


'From:' field:

[RPTO:!VRFY]
[FM:!VRFY] ........... You get this messages when SCM can't resolve the 
                       "reply-to" and "from:" fields respectively.

[RPTO:!EMAIL]
[FM:!EMAIL] .......... The respective fields in the email header don't
                       have valid email addresses. Usually means that 
                       SCM found them to be incomplete - ie "Mike 
                       Eggleston <mike>".

[FM:DEFUNC] .......... SCM found the the "From:" field is nonsense.

[FM:ME] .............. Address matched in the 'Me:' list. Email filtered.

[TO:DUMP]
[TO:DENY] ............ 'To:' address matched in the 'deny:'/'dump:' list 
                       -  filter flag set

[FM:DUMP]
[FM:DENY] ............ Address matched in the 'deny:'/'dump:' list -
                       filter flag set

[RPTO:DUMP]
[RPTO:DENY] .......... 'Reply-To:' address was matched in 'deny:'/'dump:' 
                       list - filter flag set

[XS:DUMP]
[XS:DENY] ............ 'X-Sender:' address was matched in 'deny:'/'dump:' 
                       list - filter flag set

[RETP:DUMP]
[RETP:DENY] .......... 'Return-Path:' address was matched in 
                       'deny:'/'dump:' list - filter flag set

[CC:DUMP]
[CC:DENY] ............ 'CC:' address was matched in 'deny:'/'dump:' list -
                       filter flag set

{FM:AL} .............. address found in the 'Allow:' list -
                       email isn't filtered

{RPT:AL} ............. 'Reply-To:' address matched in the 'Allow:' list -
                       email isn't filtered

[TRUCT:%d] ........... Spammer replied using '==exemption==' directive.
                       This tells you that SCM truncated email to %d 
                       bytes.

{SNT} ................ SCM sent a "reject_letter" email.

{EX-SNT} ............. SCM sent an "accept_letter" email.

[!F] ................. Filtering off (no filter directive defined in 
                       ~/.scmrc file)


Installation and setup
----------------------

a) compile distribution

  make
  make install

  this will install SCM in /usr/local/bin/scm
  and the 'info' page in /usr/info

b) connect it up. The following assumes you're using sendmail.

The mechanics behind SCM is that sendmail will read a incoming email from 
port 25. It will then pipe the email to SCM which will do the filtering.  
If email is accepted, then SCM will pass the message to procmail, and 
procmail will then deliver it to the /var/spool/mail directory.

Normally what happens is that sendmail just passes the email to 
procmail... here we have to put SCM "inbetween" this process to make it 
work.

there are two ways of doing it. You can create a "~/.forward" file with 
a piped entry in it that runs SCM -

"| IFS=' ' && exec /usr/local/bin/scm -f- || exit 75"

copy the 'forward' file to ~/.forward

Having failed that (assuming it's not a configuration problem with
sendmail), and if you have root access to the machine you're using, edit
/etc/sendmail.cf file. Change any instances of "/usr/bin/procmail" to
"/usr/local/scm".

c) copy scmrc to ~/.scmrc

d) edit .scmrc as needed.  pay particular attention to the file paths
   sendmail and procmail.

e) If this is a new installation, copy the files in etc/scm to 
   the (new) directory /etc/scm 

f) Set the ownership and permissions of the allow_deny file.  The 'reject' 
   and 'accept' letters can be owned by root:root with permissions 644.  
   As it's possible for the allow_deny file to be updated by an incoming 
   email the ownership and permissions need to be set accordingly.  
   Set the ownership to root:group (where 'group' is the group of the 
   user who receives ==exemption== emails) and the permissions to 664.
   If automatic updates are not going to be allowed, the set the ownership 
   to root:root and the permissions to 644 instead.


Contact
-------

	Email:	   technical@fensoft.co.uk

	Web Site:  www.fensoft.co.uk



Configuration Directives
------------------------

	filter
		This activates the filter.  If it's not present, the email 
		will be allowed through.  The status line (added to the 
		bottom of the email) will show which tests the email 
		failed.  Comment it out when testing your configuration.

	notify_spammer
		This causes a "reject_letter" (see below) to be sent to 
		the email sender informing them their email has been 
		rejected.

	save_spam
		If this is present, rejected email are appended to the 
		file ~/mail/spam.rejected.  This file can get very big, 
		very quickly so use this directive with caution.

	print_log
		Write a log file for each email processed.

	upd_allow_deny
		Update the "allow_deny_file" with the from: address of an 
		"==exemption==" email (see below).  This allows genuine 
		emailers to add themselves to the "whilelist".

	procmail_path: /usr/bin/procmail
		Location of the procmail program (/usr/bin/procmail).

	sendmail_path: /usr/bin/sendmail
		Location of the sendmail program (/usr/bin/sendmail).

	exemption_tok: ==exemption==
		If the specified string is found in the Subject: field the 
		email is allowed through (but see "truncation" below).

	reject_letter: /etc/scm/reject-letter
		Full path of the file containing the message to 
		"notify_spammer".

	accept_letter: /etc/scm/accept-letter
		Full path of the file containing the message sent in 
		reponse to an "==exemption==" which updates the 
		"allow_deny_file".

	allow_deny_file: /etc/scm/allow_deny
		Full path of the file containing the "whitelist" and 
		"blacklist".

	reject_from: spam@mycompany.com
		Address to be used as the From: address for the 
		"reject_letter".  By making this an alias for /dev/null 
		(in sendmail's aliases file) the "reject_letter" won't be 
		bounced back and forth between two spam protected hosts.

	accept_from: spambuster@mycompany.com
		Address to be used as the From: address for the 
		"accept_letter".


	truncation:    40
		Length to which the body of an "==exemption==" email will 
		be truncated (minimum 8 chars).

  "Blacklist" and "Whitelist" for this user.  The common "blacklist" and 
  "whitelist" are in the "allow_deny_file".
    
  Nb/ for allow,deny and me lists, wildcards are allowed... ie:

	allow: *.fensoft.co.uk
	deny: *@spammers.com
	me: m*@*fensoft.*

  "Whitelist"
  Compares both "from:" field and "reply-to:" fields only. If anyone of
  them matches, then message will be accepted.

	allow: fred@yahoo.com
	allow: harry@hotmail.com

  "Blacklist" (insert addresses you want to kill here)
  It will compare everything in the smtp header except for the subject 
  field.  If a match is found, the message is dropped.

	deny: *@spam*
	deny: spam*@spammers.co.uk


  The "dump:" directive works the same as the "deny:" directive but it 
  doesn't send a "reject-letter" even if the "notify spammer" flag is set.  

	dump: knownspammer@spammers.com

  If a common "allow_deny" s used, a "dump:" record is written to it when 
  a "reject-letter" is sent.  This prevents multiple replies to innocent 
  parties who have had their email addresses hijacked by spammers.

  Deny everything, only emails from addreses specified on the "whitelist" 
  will be allowed through.

	deny: *@*

  Your own email address(es).  Any email received from any of these 
  addresses goes straight to the bin even if the specific address is on 
  the "whitelist" - no "reject_letter" is sent and no ==exemption== is 
  permitted.  Be careful about using wildcards here especially if you 
  have other users in the same domain.
 
	me: me@mycompany.com
	me: myself@mydomain.com




Configuration Suggestion.
-------------------------

Add a record to the "allow_deny_file" to block everything -
	deny: *@*

Next add records to allow specific email addresses or groups of email 
addresses (using wildcards) through.  These "allow:" records can be added 
to the "allow_deny_file" or to your own .scmrc file.

Set up an email name in Sendmail's aliases file to point to /dev/null
Specify that name as the "reject_from:" in your .scmrc file

Set up a new user (or nominate an existing one) to recieve "==exemption==" 
requests.  In this user's .scmrc file, specify the "upd_allow_deny" 
directive and the "allow_deny_file".  You can also override the "from:" 
address for the "accept_letter" if you wish.

Remember, the "accept_letter" and "reject_letter" can be common to all 
users.  The "reject_letter" should tell the receipient to send an email 
with ==exemption== (or whatever sequence of characters are specified in  
the "exemption_tok" directive) in the subject field, to the user set up to 
receive these requests.

THEORY.  For simplicity, presume the "allow_deny_file" only has one record 
"deny: *@*" and there are no "allow:" records in the .scmrc files.  
When an email is received, a "reject_letter" is emailed to the sender.  
This email has a "From:" address linked to /dev/null so, if it's bounced 
back, it disappears without trace.  If the sender of the original email 
reads it, they will know to send an email with ==exemption== as the 
subject to the specified user.  When that email is received, the 
"allow_deny_file" is updated with the sender's "From" address and an 
"accept_letter" is returned to them.  They can then send emails normally.



                                 ooo0ooo

