               SNFMilter Installation and Configuration

              Copyright (C) 2009 ARM Research Labs, LLC.

           See www.armresearch.com for the copyright terms.
                                   
Installing SNFMilter to filter email involves the following steps:

  1) Check prerequisites.

  2) Create the snfmilter user and group.

  3) Build and install the SNFMilter package (using a tarball or a
  package).

  4) Configure the SNFMilter package.

  5) Interface with the MTA (postfix or sendmail).

  6) Configure the OS to start and stop SNFMilter on bootup and
  shutdown.

The following sections describes each of these steps for a default
installation.  Any OS-specific issues are described at the end of each
section.

Prerequisites
*************

Before installing SNFMilter, make sure that:

  1) The libmilter library is installed.

  2) The programs wget and gzip are installed.

Creating the snfuser user and group
*******************************

Before installing, the snfuser user and group must be created.  For
increased security, the snfuser user has no shell.

OS-specific issues--

The commands to create the snfuser user and group are OS dependent.  For
your convenience, the commands for creating the user and group for
varous OSes are listed here.  However, no guarantee is made that these
commands will work on your system; please refer to your system
documentation.

  1) FreeBSD:

     a) 'pw user add -c "Sniffer Account" -n snfuser -w no -s /bin/false'

  2) OpenBSD:

     a) 'useradd -g =uid -c "Sniffer Account" -s /bin/false snfuser'.

     You can safely ignore any warnings about the home directory not
     existing.

  3) RedHat (and variants such as Fedora):

     a) 'adduser --comment "Sniffer Account" -M --shell /bin/false snfuser'

  4) Suse:

     a) 'groupadd snfuser'

     b) 'useradd -c "Sniffer Account" -s /bin/false -g snfuser snfuser'

  5) Ubuntu:

     a) 'adduser --gecos "Sniffer Account" --no-create-home --disabled-password --shell /bin/false snfuser'.

Building and installing SNMilter
********************************

For some operating systems, configuration files are normally installed
in /etc, and the installation of the remaining files are in /usr
(i.e. /usr/sbin, /usr/share/snf-milter, etc).  In other operating
systems, the files are installed in /usr/local/etc or /usr/local.

The directories to install are specified by the '--prefix' and
'--sysconfdir' options to the configure script (see below).

To build and install from the tarball--

  1) Extract the distribution from the tarball: 'tar xvzf
  snf-milter-X.Y.Z.tar.gz', where X.Y.Z is the version of the
  distribution.

  2) 'cd' to the source directory.

  3) Run the configure script.  See the section on OS-specific issues
  for the options to specify.  This configures the package.

  4) Type 'make'.  This builds the distribution.

  5) Type 'make install'.  This installs the distribution in the default
  directories.

The following files are installed:

  Executables and scripts in sbin:
       SNFMilter
       SNFClient
       SNF2Check
       getRulebase.sample
       SNFDebugMilter (link to SNFMilter)

  Sample configuration files in etc/snf-milter:
       SNFMilter.xml.sample
       identity.xml.sample
       snf-milter.conf.sample

  In share/snf-milter
       GBUdbIgnoreList.txt.sample

During operation of SNFMilter, the following files are created:

  In share/snf-milter:
       *.snf
       Log files
       UpdateReady.txt

  Named pipe for the communication between SNFMilter and the MTA.

OS-specific issues for installation from a tarball--

  1) FreeBSD:

    ./configure --enable-os-type=FreeBSD

  2) OpenBSD:

    ./configure --enable-os-type=OpenBSD --sysconfdir=/etc

  3) RedHat (and variants such as Fedora and CentOS):

     Without SELinux:

      ./configure --enable-os-type=RedHat --sysconfdir=/etc --prefix=/usr

     With SELinux:

      ./configure --enable-os-type=RedHat --sysconfdir=/etc --prefix=/usr \
      --with-selinux

  4) Suse:

    ./configure --enable-os-type=Suse --sysconfdir=/etc --prefix=/usr

  5) Ubuntu:

    ./configure --enable-os-type=Ubuntu --sysconfdir=/etc --prefix=/usr

To install from a package--

The installation using a package is OS-dependent.  Here are the
commands for the various OSes (PKG_FILE is the package file):

  1) OpenBSD:

       pkg_add PKG_FILE

  2) Ubuntu:

       dpkg -i PKG_FILE

  3) RedHat (and other RPM-based distributions such as Fedora):

       rpm -i PKG_FILE

Configuration
*************

Configuration consists of creating the configuration files used by
SNFMilter from the sample configuration files of the distribution.
There are three configuration files.  The location of the files
described in this section are for the installation in /usr and /etc.

  1) SNFMilter.xml (sample configuration file is
  SNFMilter.xml.sample).

  2) identity.xml (sample configuration file is identity.xml.sample).

  3) Optional: snf-milter.conf (sample file is
  snf-milter.conf.sample).  This is used to set the parameters for
  starting SNFMilter in debug mode.  If this file is not present, then
  SNFMilter starts in the non-debug mode.

and one in /usr/share/snf-milter:

  1) GBUdbIngoreList.txt (sample configuration file is
  GBUdbIgnoreList.txt.sample).

To configure SNFMilter, do the following:

  1) Copy SNFMilter.xml.sample to SNFMilter.xml, and edit as follows:

     a) Specify the directories.  The default directories are:

          <node identity='/etc/snf-milter/identity.xml'>
          <log path='/var/log/snf-milter/'/>
          <rulebase path='/usr/share/snf-milter/'/>
          <workspace path='/usr/share/snf-milter/'/>
          <update-script on-off='on' call='/usr/sbin/getRulebase'
	  		 guard-time='180'/>

     The paths need to be changed only if the default directories are
     not used.

     b) Specify the communication between SNFMilter and the MTA.  The default

          <socket type='unix' path='/var/snf-milter/socket'
          group='snfuser'/>

     is not appropriate for all OSes; please see OS-specific issues at
     the end of this section.

     SNFMilter attempts to create the specified path, and, if 'group'
     is specified, to change the group of the path to the specified
     group.  The snfuser user must therefore have adequate permission to
     create the specified path, and to change the group of the
     specified path to the specified group.  Please see the
     OS-specific issues at the end of this section for example
     procedures for doing this.

     If desired for security purposes, restrict the permissions of
     SNFMilter.xml.  For example, to make SNFMilter.xml readonly by
     only the snfuser user and snfuser group, enter the following:

       chmod 440 SNFMilter.xml

  2) Create the directory in which SNFMilter creates the socket, and
  set the correct ownership and permissions.  Please see the
  OS-specific issues at the end of this section for example procedures
  for each OS.

  3) Copy identity.xml.sample to identity.xml, and edit to include the
  license ID and authentication attributes of the <identity> element.
  If desired for security purposes, restrict the permissions of
  identity.xml.  For example, to make identity.xml readonly by only
  snfuser, enter the following:

    chmod 400 identity.xml

  4) Copy GBUdbIngoreList.txt.sample to GBUdbIgnoreList.txt, and edit
  as appropriate (the file format is described in the comments in the
  file).  There must be at least one entry in the file.

  5) In the directory for the update script specified in the
  configuration file (default: /usr/sbin):

     a) Copy getRulebase.sample to getRulebase, and edit as follows:

       i) In the line

            AUTHENTICATION=authenticationxx

          replace authenticationxx with the authentication for the
          SNFMilter license.
          
       ii) In the line

            LICENSE_ID=licenseid

          replace licenseid with the license ID of the SNFMilter
          license.

       iii) Any other changes as necessary if the default directories
       are not used.

     b) Ensure that getRulebase is executable by the snfuser user.  This
     can be done with the command:

       chmod +x getRulebase

     c) SELinux only:  Set the security context of getRulebase:

     	restorecon -F -R -v getRulebase

  6) Ensure that the snfuser user has read/write access to the files in
  workspace (default: /usr/share/snf-milter) and configuration
  directory (default: /etc/snf-milter).  To grant this access, enter
  the following command, as the root user:

    chown -R snfuser:snfuser /usr/share/snf-milter

    chown -R snfuser:snfuser /etc/snf-milter

   As you modify files in these directories, please ensure that the
  read/write permissions for snfuser is maintained.

  7) Create the logfile directory if it doesn't exist, and ensure the
  snfuser user has read/write access to it:

    mkdir /var/log/snf-milter

    chown snfuser:snfuser /var/log/snf-milter

    chmod 755 /var/log/snf-milter

  6) Download the rulebase file:

     a) 'cd /usr/share/snf-milter'.  If the workspace specified in the
     configuration file is not the default, this command should be
     changed accordingly.

     b) 'touch UpdateReady.txt'.

     c) 'chown snfuser UpdateReady.txt'.

     d) 'su -m snfuser -c "/usr/sbin/getRulebase"'.  If getRulebase is in
     a different directory, this command should be changed
     accordingly.

OS-specific issues--

  1) FreeBSD: Please follow the directions for RedHat, but use the
  following command to allow the postfix MTA programs to access the
  named pipe:

      pw mod group -n snfuser -m postfix

  In the SNFUSERMilter.xml configuration, you should also ensure that the
  <socket> element specifies the 'snfuser' group:

      <socket> type='unix' path='/var/snf-milter/socket' group='snfuser'/>

  2) OpenBSD: For the default postfix installation, postfix runs
  chrooted in /var/spool/postfix.  Verify this by checking the
  master.cf postfix configuration file.  In this case, specify the
  communication as follows:

      <socket type='unix' path='/var/spool/postfix/snf-milter/socket'/>

  and create the directory '/var/spool/postfix/snf-milter', owned by
  user '_postfix', with group 'snfuser', and with read permissions for
  _postfix and read/write permissions for snfuser:

      mkdir /var/spool/postfix/snf-milter

      chown _postfix:snfuser /var/spool/postfix/snf-milter

      chmod 770 /var/spool/postfix/snf-milter

  To allow the postfix MTA programs access to the named pipe, make the
  postfix user a member of the snfuser group:

      usermod -G snfuser _postfix

  If you're planning to use SNFMilter with sendmail, please follow the
  directions for Redhat.

  3) RedHat (and variants such as Fedora and CentOS): For
  the default postfix installation, postfix does not run chrooted.
  Verify this by checking the master.cf postfix configuration file.
  In this case, specify the communication as follows:

      <socket type='unix' path='/var/snf-milter/socket'/>

  and create the directory '/var/snf-milter' if it doesn't exist, with
  the following ownership and permissions:

      mkdir /var/snf-milter

      chown snfuser:snfuser /var/snf-milter

      chmod 750 /var/snf-milter

  To allow the postfix MTA programs access to the named pipe, make the
  postfix user a member of the snfuser group:

      usermod -G snfuser postfix

  For the default sendmail configuration, sendmail does not run
  chrooted.  You can determine whether sendmail runs chrooted by the
  presence of confSAFE_FILE_ENV in /etc/mail/sendmail.mc configuration
  file.  The configuration is the same as for postfix for RedHat,
  except that you do not need to have the postfix user be a member of
  the snfuser group.

  4) Suse:  Follow the directions for RedHat.

  5) Ubuntu: If you're planning to use SNFMilter with postfix, please
  follow the directions for OpenBSD, but use 'postfix' for the user
  and group name instead of '_postfix', and make the postfix user a
  member of the snfuser group with the usermod command:

      usermod -G snfuser postfix

  If you're planning to use SNFMilter with sendmail, please follow the
  directions for Redhat.

Configuring the OS
******************

The OS can be configured to automatically start and stop SNFMilter on
system startup and shutdown.  The following gives the procedure for
each OS:

OpenBSD:

  1) Add the following line to /etc/rc.local:

       /usr/local/sbin/snf-milter start

  2) Add the following line to /etc/rc.shutdown:

       /usr/local/sbin/snf-milter stop

  3) Run '/usr/local/sbin/snf-milter start' to start the server.

FreeBSD:

  1) Create the directory /etc/rc.conf.d (if it doesn't exist).

  2) Create create a /etc/rc.conf.d/snfmilter with the contents:

       snfmilter_enable="YES"

  3) Run '/usr/local/etc/rc.d/snf-milter start' to start the server.

Ubuntu:

  1) Set the VERBOSE variable in /etc/default/rcS to control the
  script output.

  2) Configure the system to run the script.  With sysv-rc-conf:

       sysv-rc-conf -level 2345 snf-milter on

     will start the server for runlevels 2, 3, 4, and 5.

     And

       sysv-rc-conf --list snf-milter

     will list the runlevels for which the server is started.

  3) Run '/etc/init.d/snf-milter start' to start the server.

RedHat (and variants such as Fedora and CentOS):

  1) Run 'chkconfig --add snf-milter'.  This configures the system to
  run the script on startup and shutdown.

  2) Run 'chkconfig --list snf-milter' to display the runlevels

  3) Run 'service snf-milter start' to start the SNFMilter.

Integration with MTAs
*********************

The section assumes you will be using SNFMilter with an MTA to inject
headers that will be used later to remove, quarantine, or otherwise
redirect messages detected as spam. There are several ways to use
SNFMilter; so the following is just a good starting point.

It is presumed that SNFMilter is configured with x-header injection
turned on and that the x-headers have been customized to suit your
needs. Check the <xheaders/> section of your
/etc/snf-milter/SNFMilter.xml file to verify that SNFMilter is
configured to do what you want.

Integration with postfix
------------------------

**********************************************************************

NOTE--postfix version 2.6.2 and earlier has a bug that causes problems
under the following circumstances:

  1) More than one message is received by postfix in one SMTP
  connection.

  2) One or more of the messages is quarantined.

When this happens, postfix erroneously reports an "unexpected filter
response SMFIR_ADDHEADER after event SMFIC_MAIL" in the mail log, and
then sends a "Service unavailable - try again later" response to the
next MAIL command.

This bug can be fixed by patching the sources for posfix version 2.5
or later.  The procedure is:

  1) Unpack the postfix sources.

  2) Change to src directory in the postfix distribution.

  3) Apply the patch:

       patch -p0 < patchFile

     where patchFile is the file postfix-multi-message.patch in this
     directory.

  4) Build and install postfix as usual.

**********************************************************************

To integrate SNFMilter with postfix:

  1) Edit the postfix configuration file 'main.cf':

     a) Specify the communication between SNFMilter and postfix:

          smtpd_milters = unix:/path/to/socket

        or

          non_smtpd_milters = unix:/path/to/socket

        See below (OS-specific issues) for default paths for each OS.

        There is one connection per instance of SNFMilter.

        This must be consistent with the SNFMilter.xml configuration file.

  2) See the postfix documentation for other options
  (http://www.postfix.org/MILTER_README.html).

  3) Start postfix if it isn't running, or reload the configuration
  (with 'postfix reload') if postfix is already running.

OS-specific issues--

  1) FreeBSD: The postfix configuration file is
  /usr/local/etc/postfix/main.cf.  For the default postfix configuration
  (for which postfix not run chrooted), specify

          smtpd_milters = unix:/var/snf-milter/socket

  in main.cf.

  2) OpenBSD: The postfix configuration file is
  /etc/postfix/main.cf.  For the default postfix configuration (for
  which postfix runs chrooted), specify

          smtpd_milters = unix:/snf-milter/socket

  in main.cf.

  3) RedHat (and variants such as Fedora): The postfix
  configuration file is /etc/postfix/main.cf.  For the default postfix
  configuration (for which postfix does not run chrooted), specify

          smtpd_milters = unix:/var/snf-milter/socket

  in main.cf.

  4) Suse:  Follow the directions for RedHat.

  5) Ubuntu:  Follow the directions for OpenBSD.

Integration with sendmail
-------------------------

The following is for sendmail 8.13 or later.  If your sendmail version
is older than 8.13, please consult the sendmail documentation for
integrating a milter.

  1) Edit the sendmail configuration file 'sendmail.mc' (in the
  sendmail configuration file directory):

     a) Specify the communication between SNFMilter and sendmail:

          INPUT_MAIL_FILTER(`SNFMilter', `S=unix:/path/to/socket')

        See below (OS-specific issues) for default paths for each OS.

        The /path/to/socket must be consistent with the SNFMilter.xml
        configuration file.

  2) Specify any other options.  Please see
  https://www.milter.org/developers/installation#config for further
  information.

  3) Run 'make' in the sendmail configuration file directory.

  4) Start or restart sendmail.

OS-specific issues--

  1) FreeBSD: The sendmail configuration file is
  /etc/mail/<hostname>.mc, where <hostname> is the name of
  the host.  This file is created after running 'make' in /etc/mail.
  For the default sendmail configuration (for which sendmail is not
  run chrooted):

    a) Specify

          INPUT_MAIL_FILTER(`SNFMilter', `S=unix:/var/snf-milter/socket')

    in the configuration file.

    b) Run 'make' to create the cf files.

    c) Copy <hostname>.cf to sendmail.cf.

    d) Copy <hostname>.submit.cf to submit.cf.

  2) OpenBSD: The sendmail configuration file are in
  /usr/share/sendmail/cf.  Edit the appropriate file, and add

          INPUT_MAIL_FILTER(`SNFMilter', `S=unix:/var/snf-milter/socket')

  at the end.  If your configuration specifies that sendmail is run
  chrooted, modify the path to the socket accordingly.  Then run
  'make', and copy the resulting cf file to /etc/sendmail.cf.  You'll
  need to restart sendmail for the changes to take effect.

  3) RedHat (and variants such as Fedora): The sendmail
  configuration file directory is /etc/mail.  For the default sendmail
  configuration (for which sendmail does not run chrooted), specify

          INPUT_MAIL_FILTER(`SNFMilter', `S=unix:/var/snf-milter/socket')

  in sendmail.mc (along with any other options).  You can determine
  whether sendmail runs chrooted by the presence of confSAFE_FILE_ENV
  in sendmail.mc

  4) Suse: Follow the directions for RedHat.  The sendmail
  configuration file is /etc/mail/linux.mc.  To create the cf file for
  sendmail, do the following in the /etc directory:

    rm sendmail.cf

    m4 /etc/mail/linux.mc > sendmail.cf

  5) Ubuntu.  Follow the directions for RedHat.

Debugging
---------

To obtain additional information for debugging, SNFMilter can be run
in debug mode.  In debug mode, additional messages are output to a
file, and core dumps are enabled.  Debug mode is enabled and disabled
using the snf-milter startup script.  Please see the section
"Configuring the OS" the the location of the startup script for each
OS.

To enable debug mode, run:

  snf-milter debug_mode

Note: Running this command creates a file
/usr/share/snf-milter/debug_mode that indicates to the snf-milter
startup script to start SNFMilter in debug mode.  This file contains
brief documentation about running in debug mode.

To enable production mode (non-debug mode), run:

  snf-milter production_mode

Note: Running this command creates a file
/usr/share/snf-milter/production_mode that indicates to the snf-milter
startup script to start SNFMilter in production mode.  This file has
the same content as /usr/share/snf-milter/debug_mode.

After the desired mode is enabled, you can start or restart SNFMilter
using the standard procedure.

In debug mode for all OSes except OpenBSD, SNFDebugMilter is run with
strace (with the '-r -tt -v' options), and all the output is written
to /var/log/snf-milter/debug.log.  Also, any core dumps are written to
/usr/share/snf-milter.

In debug mode for OpenBSD, SNFDebugMilter is run with ktrace.  The
output of SNFDebugMilter is written to /var/log/snf-milter/debug.log,
and the output of strace is written to /var/log/snf-milter/ktrace.out.

OS-specific issues--

  1) FreeBSD: You'll need to ensure that core dumps are enabled.  On
  FreeBSD 7.0, the command to do this is:

    sysctl kern.coredump=1

  You'll also need to ensure that /proc is mounted.  You can mount
  /proc with the following command:

    mount -t procfs proc /proc

  When running in debug mode, 'snf-milter start' displays the PID of
  the strace process instead of the SNFDebugMilter process.
  'snf-milter status' displays the PID values correctly.

  2) OpenBSD:  Use kdump to view the kernal trace file:

       kdump /var/log/snf-milter/ktrace.out

Default SELinux Policy
**********************

Source files for a SELinux policy to confine SNFMilter and getRulebase
are included in the SELinux directory.  That directories contains
files for each of the supported operating systems (e.g. the SELinux
policy source files for RedHat compatible systems (e.g. Fedora,
CentOS) are in SELinux/RedHat.

During the build process, the appropriate source files are copied to
the SELinux directory and used to build the SNFMilter.pp policy file.
The installation installs the SNFMilter.pp policy.

Verify that the policy was installed by:

  semodule --list | grep SNFMilter

To remove the policy:

  semodule -r SNFMilter

To reinstall the policy and relabel the SNFMilter-related files:

  cd SELinux

  ./InstallPolicy

Description of the policy--

In order to run under SELinux, the MTA needs access to the socket used
for communication between the MTA and SNFMilter.

The SELinux policy does the following:

  1) Confines the SNFMilter daemon and getRulebase script to its own
     domain.

  2) Defines a type for readonly files (for configuration) and
     read-write files (for logging).

  3) Gives the SNFMilter deamon needed permissions to:

     a) Run getRulebase.

     b) Write to the SNFMilter logging directory.

     c) Use the syslog facility.

     d) Listen on ports 9001, 9030, and 9050 (only 9001 is needed, but
        the existing SELinux policy requires that access be given to
        all or none of these three ports).

     e) Connect to port 25 and 80.

  4) Gives the postfix domains the required permissions for
     communicating with the socket.

Please see SELinuz.SNFMilter.te for further info.

Installing the policy relabels the installed files so that SNFMilter
has the needed access.
