/*
 * -----------------------------------------------------------
 *
 *   Dr.Web Mail Filter for Sendmail [*]
 *
 * -----------------------------------------------------------
 */

1. Requirements
2. How to provide the joint work of Sendmail and drweb-smf
  2.1 How it works 
  2.2 Changing sendmail.mc and sendmail.cf
  2.3 Setting up drweb-smf
3. How to build Sendmail with the support of Mail Filter API
  3.1 Setting up the patches for Sendmail
  3.2 Building from separate source texts
  3.3 Building Sendmail from FreeBSD distribution
  3.4 Building Sendmail from FreeBSD ports
4. The known problems
5. Contacts


        1. Requirements

- Dr.Web Daemon v.4.23 or higher
- drweb-smf filter
- Source Sendmail texts not lower than 8.11. The filter does not work with
  versions 8.12.0 Beta1-Beta9 because of the error in Sendmail, corrected
  in the following beta-versions. They are required only if Sendmail has no
  Milter API support, some distributors (e.g. RedHat) now deliver Sendmail
  with MilterAPI support pre-included.


        2. How to provide the joint work of sendmail and drweb-smf

    We suppose that your Sendmail supports MilterAPI already, if it is not
true turn to the paragraph 3, where it is described how to re-build
Sendmail with the necessary API support.

   2.1 How it works

So what Sendmail Mail Filter API can provide:

+----------+      +------------------------+      +--------+
| sendmail |<---->| milter-api | drweb-smf |<---->| drwebd |
+----------+    ^ +------------------------+    ^ +--------+
                1                               2

    1. Through a transport connection, that drweb-smf identifies by its
transport address __ADDRESS__ (specified in the previous topic), the inner
Milter API commands and the message are transferred. As for the message, it
is transferred not as a whole, but in parts, depending on the mailing
session phase: helo, mail from:, rcpt to: etc. That is why the filter saves
the message in temporary files (see the -f option). Through Milter API
drweb-smf reports what is to be done with the message. Milter API is a
multi-stream library and thus a few mailing sessions can be processed in
one and the same time. So, considering this interaction, Sendmail is a
client, and the mail filter performs the server function, that is why it is
the filter address that gets specified (in sendmail.cf and in the filter
command line), as for Sendmail it chooses for this connection a suitable
client address.

    2. Through another transport connection drweb-smf by means of Dr.Web
Daemon API interface transfers the commands (and the message, if the local
mode is not enabled by the -l option) to the daemon and waits for an
answer. A positive answer received (the message is "clean"), the temporary
file is deleted and Sendmail gets the permission to receive this letter. A
virus found, the message is transferred to the infected messages archive
(see the -a option), the message itself gets changed by the notification
sent to the addressees and (optional) to the sender (the -x option) and to
the administrator (the -g option). In case of errors during the message
processing the -b option is activated. Regarding the given interaction the
filter is a client, whereas the daemon operates as a server, the daemons
address is specified (in daemon's ini file and in the filter command line).

    Thus drweb-smf is a mere agent (or converter) between Sendmail
interface and drwebd. Each of the three programs can be run on different
computers, but the optimal variant will be to run the filter and the daemon
on one and the same computer, that will allow to (with the -l option
enabled) transfer the message only once, because the daemon will scan it as
local disc file.

   2.2 Changing sendmail.mc and sendmail.cf

    If you would like not to re-build sendmail.cf, you can just insert or add 
(if the corresponding definitions already exist) into sendmail.cf:

-------------------- cut ------------------
############################
# Input mail filters
############################
O InputMailFilters=drweb-filter

# If you have Sendmail 8.12.x or higher,
# you should uncomment the following line 
# O Milter.LogLevel=6

############################
#      Xfilters
############################

Xdrweb-filter,  S=__ADDRESS__, F=T, T=S:5m;R:5m;E:1h
------------------- cut ---------------------

Now we can set the following flags (F=) for the case when the filter is
inaccessible:

        R               Delivery failed 
        T               Delivery temporary blocked
(if neither F=R, nor F=T are not specified, the message will be delivered
without checking)

or add into sendmail.mc (additional options described in README in the
directory with the libmilter library source texts):

only for Sendmail versions under 8.12.x:
------------------- cut ---------------------
define(`_FFR_MILTER',1)
------------------- cut ---------------------

and for all Sendmail versions:
------------------- cut ---------------------
MAIL_FILTER(`drweb-filter', `S=__ADDRESS__, F=T, T=S:5m;R:5m;E:1h')
define(`confINPUT_MAIL_FILTERS', `drweb-filter')
define(`confMILTER_LOG_LEVEL',`6')
------------------- cut ---------------------

Note: timeout value should correspond to Sendmail timeout values
"O Timeout.datablock=XX" (it is 1hr by default, XX=>1h)

    And then you should recompile sendmail.cf.

Note:
__ADDRESS__ - is a line setting filter connecting transport. Its format is
identical to that used in the filter configuration file. It may be for
TCP/IP socket family:

inet:__PORT__@__HOST__
(__PORT__ & __HOST__ must have concrete values, e.g., inet:3001@localhost)

or for UNIX-DOMAIN sockets:

local:__SOCKPATH__
(similarly __SOCKPATH__ must specify the path which must be accessible with
the rights you will start the filter with, e.g. local:/var/run/drweb-smf.sock)

    For details on setting up the filter see Sendmail documentation
(starting with {sendmaildir}/libmilter/README).

    drweb-smf can be started with the necessary keys (for the description
of the keys see the next paragraph). After that restart Sendmail.

    !!! The optimal way is to run daemon and filter (but not necessarily
Sendmail) on one and the same computer because it will allow to perform
local files scanning without transferring the message through the sockets.
To perform this it is necessary that daemon and filter rights were
sufficient for accessing the general directory and enough for reading
temporary files created by the filter.

    To enable your filter to display sendmails message ID (message
identification number for Sendmail) in the log file when outputting the
message, make sure that there is the following line in sendmail.cf:

------------------- cut ---------------------
O Milter.macros.envfrom=i, ... 
------------------- cut ---------------------

(dots stand for other parameters - their value is not important).

    To suppress the output in the syslog of the alike messages:

------------------- cut ---------------------
X-Authentication-Warning: some.domain.com: drweb set sender to DrWeb-DAEMON@some.domain.com using -f
------------------- cut ---------------------

include drweb user (or the one who is running drweb-smf) in the
trusted-users list in submit.cf file

------------------- cut ---------------------
#####################
#   Trusted users   #
#####################

Tdrweb
------------------- cut ---------------------

   2.3 Setting up drweb-smf 

    Filter parameters are set up in the configuration file. If started with
no parameters the filter is trying to find the configuration file in
standard (for the filter) directories which you can easily find out by
simply starting the filter from the console:

$ drweb-smf --help

    If the given location of the configuration file does not suit you, you
can explicitly set up configuration file name by specifying in Content
Filtering not only the path to the filter, but also setting up the
parameter:

{path/to}/drweb-smf --conf={path/to/conf/file}

    After that you should edit the configuration file and set up
notification templates. When started, the filter is trying to check its
operability in the given configuration by creating and checking a test file
in the spool.

    For the description of the filter configuration file, notification
templates and the trusted users list see conf_file.txt, notify.txt and
 
users_list.txt correspondingly.

    
        3. How to build Sendmail with the support of Mail Filter API
    
    You need to build Sendmail with the support of Mail Filter API. If it
is already done do not doubt to pass to the paragraph 4, but do not forget
to copy libmilter.a and libsmutil.a for version 8.11.x (Linux) or libsm.a
for version 8.12.x (libsmutil or libsm needed for Linux, not needed for
FreeBSD) into /usr/local/lib, and mfapi.h into /usr/local/include.


   3.1 Setting up the patches for Sendmail

    All errors nonfatal - so patches
 can be skipped. We provide three patches:

listener-8.11.1 - fix bug with filter core dumping on exit. Fixed in next 
versions of Sendmail    
listener-8.12.0 - fix bug then filter use unix-socket and socket-file has not
deleted at exit. Fixed in version 8.12.2

$ cp listener-8.1X.Y.patch /place/where/source/texts/are/libmilter
$ cd /place/where/source/texts/are/libmilter
$ patch < listener-8.1X.Y.patch

sendmail-8.12.2 - fix bug then message size is growed up to double, if filter 
used with evaluation key. Will be fixed in version 8.12.3

$ cp sendmail-8.12.2.patch /place/where/sendmail/source/tree/are/located
$ cd /place/where/sendmail/source/tree/are/located
$ patch < sendmail-8.12.2.patch

   3.2 Building from separate source texts

    From now on {sendmaildir} stands for a directory where Sendmail has been 
unpacked (e.g. /usr/local/src/sendmail-8.xx.x):

$ cd {sendmaildir}

Step A)
We should indicate that we'd like to build with the support of libmilter, for 
this:

$ cd {sendmaildir}/devtools/Site/

    If the site.config.m4 file does not exist, create it, and if it does,
add into it the following lines:

for Sendmail versions under 8.12.x:
--- cut ---
dnl Milter
APPENDDEF(`conf_sendmail_ENVDEF', `-D_FFR_MILTER')
APPENDDEF(`conf_libmilter_ENVDEF', `-D_FFR_MILTER')
--- cut ---

for Sendmail versions from 8.12.x:
--- cut ---
dnl Milter
APPENDDEF(`conf_sendmail_ENVDEF', `-DMILTER')
--- cut ---

If there occur any errors when building Sendmail then you should probably
add the following lines:
--- cut ---
APPENDDEF(`confLIBSEARCH', `db db2 bind resolv 44bsd')
APPENDDEF(`confINCDIRS', `-I/usr/include/db2/ -I/usr/include/db1/')
APPENDDEF(`confMAPDEF', `-DNEWDB ')
--- cut ---

Step B)
Now building libmilter library:

$ cd {sendmaildir}/libmilter
$ ./Build -c

It is only left to build and install Sendmail itself:

$ cd {sendmaildir}/sendmail
$ ./Build

Now let's install Sendmail the way it is described in {sendmaildir}/INSTALL
file. 

   3.3 Building Sendmail from FreeBSD distribution (/usr/src/contrib)

    If you have FreeBSD, the first thing to do is to add into make.conf
(located by default in /etc/defaults/) the following line:

for Sendmail versions under 8.12.x:
SENDMAIL_CFLAGS=-D_FFR_MILTER

for Sendmail versions from 8.12.x:
SENDMAIL_CFLAGS=-DMILTER

    It is assumed that your directory arrangement is standard for FreeBSD
4.x. If it is not so, you will need to perform a few minimal and quite
clear changes (from now on $ stands for shell prompt):

$ cd /usr/src/lib/libsmutil
$ make clean
$ make
$ cd /usr/src/lib
$ mkdir libmilter
$ cd libmilter

    Creating in this directory Makefile containing the following:

-------------------- cut --------------------------
SENDMAIL_DIR=${.CURDIR}/../../contrib/sendmail
.PATH:  ${SENDMAIL_DIR}/libmilter

CFLAGS+=-I${SENDMAIL_DIR}/src -I${SENDMAIL_DIR}/include
CFLAGS+=-DNEWDB -DNIS -DMAP_REGEX -DNOT_SENDMAIL

# User customizations to the sendmail build environment
CFLAGS+=${SENDMAIL_CFLAGS}

LIB=    milter

SRCS+=  comm.c engine.c handler.c listener.c main.c signal.c sm_gethost.c smfi.c

INTERNALLIB=        true
NOPIC=              true
INTERNALSTATICLIB=  true

.include <bsd.lib.mk>
--------------------- cut --------------------------

Then:

$ make clean
$ make

Rebuilding Sendmail itself:

$ cd /usr/src/usr.sbin/sendmail
$ make clean
$ make
$ make install

   3.4 Building Sendmail from FreeBSD ports

    If you are building Sendmail (version 8.11.5 or higher, but might be
lower) from FreeBSD ports collection you can just edit Makefile and set the
following option:

SENDMAIL_WITH_MILTER=Yes 

and go on with the usual Sendmail building process.


        4. The known problems

    When using Unix socket to provide communication between the filter and
Sendmail (option -m) Milter API supporting library (delivered together with
Sendmail) did not remove (up to the version 8.12.2) the file used to carry
the socket functions. For the version 8.12.x you can find the
listener-8.12.0-1.patch. The installation process duplicates (but for the
file name) the one described in the paragraph 3.1. For versions 8.11 you
will have to remove the file or from the script managing the filter.


        5. Contacts

    There exists user support forum on the site at www.drweb.ru where you
can put a question to the developers, ask for advice or just share your
experience. The address of the forum is:
http://www.drweb.ru/linux-bsd/forum

    You can also send your comments on how the filter works and error
reports (providing all the information mentioned below) to Sergey Akhapkin,
asv@drweb.ru. We are very interested to know what new possibilities you
would like to see introduced in the new filter versions.

    Please, collect some information before writing to the developers:

    1) If the drweb-smf.core file (FreeBSD) or the core file (Linux) still
remain in the root directory after having processed the filter and your
Sendmail version is 8.11.1 (or, perhaps, higher - we do not know whether
the bug will be recovered in them), check if you have put listener.patch
from DrWeb distribution. If the patch is not put, you may build the filter
with the debugging information. For this, launch configure, after prompt
"Enter compiler optimizations flag(s) only" input -O0 -g3 and rebuild the
filter. In case core appears once more send it to us with the sources of
the filter, to which all this is happening.

    2) If it seems to you that the filter does not always work the way you
expect, try to enable debugging output into syslog. To do it edit
syslog.conf adding the line (if there is nothing alike):

--- cut ---
mail.debug      /var/log/mail.debug
--- cut ---

If your Sendmail version is 8.12.x or higher you may also try increasing
Milter-API log level by changing the following line

O Milter.LogLevel=6

into (or by adding)

O Milter.LogLevel=14

    After that in suspicious cases you may analyse this log or send it to
us with an explanation of the situation.

Besides, messages should contain the following information:

- distribution name and version
- kernal and the standard libc library version
- Sendmail version
- DrWeb daemon version
- configuration files: daemon's (drweb32.ini), drweb_sendmail.conf
- fragment of sendmail.cf with data on the filter
  (all the lines containing "drweb-filter")

-----
* - Sendmail is a trademark of Sendmail, Inc.
