Make your own free website on

Installing Sendmail 8.12.1 for Milter Support

Installing Filter

Testing a Filter

Security Concerns


4.1 Installing Sendmail 8.12.1 for Milter support

Starting with sendmail 8.12, sendmail is no longer set-user-ID root by default.  As a result of this, you need to install two .cf files. See steps 4 and 6 in this document.  We also strongly recommend reading sendmail/SECURITY for more installation information.

1.      Read all the README files noted in the INTRODUCTION section of the README file in this top-level directory.

2.      Create any necessary site configuration build files, as noted in devtools/Site/README.

3.      In the sendmail/ directory, run "sh Build" (see sendmail/README for details).

4.      Change to the cf/cf/ directory (that's not a typo): Copy whichever .mc file best matches your environment to, where config can be any name.  Next, tailor it as explained in cf/README.  Then run "sh Build".

5.      Back up your current /etc/mail/ and the sendmail binary (whose location varies from operating system to operating system, but is usually in /usr/sbin or /usr/lib).

6.      Install as /etc/mail/ and as /etc/mail/ This can be done in the cf/cf by using "sh Build install-cf". Read sendmail/SECURITY before continuing; you have to create a new user smmsp and a new group smmsp for the default installation. Then install the sendmail binary built in step 3 by cd-ing back to sendmail/ and running "sh Build install".

7.      For each of the associated sendmail utilities (makemap, mailstats, etc.), read the README in the utility's directory.  When you are ready to install it, back up your installed version and type "sh Build install".

8.      If you are upgrading from an older version of sendmail and are using any database maps, be sure to rebuild them with the new version of makemap, in case you are now using a different (and thereby incompatible) version of Berkeley DB.


4.2 Installing filter

4.2.1 Compiling and Installing Your Filter

To compile a filter, modify the Makefile provided with the sample program, or:

Your compile command line will look like

cc -I/path/to/include -I/path/to/sendmail -c myfile.c

and your linking command line will look something like

cc -o myfilter [object-files] -L[library-location] -lmilter -pthread

To run the filter, the Milter shared library must be available to the run-time linker.


4.3 Configuring Sendmail

First, you must compile sendmail versions before 8.12 with _FFR_MILTER defined. To do this, add the following lines to your build configuration file (devtools/Site/

APPENDDEF(`conf_sendmail_ENVDEF', `-D_FFR_MILTER=1')
APPENDDEF(`conf_libmilter_ENVDEF', `-D_FFR_MILTER=1') 

then type ./Build -c in your sendmail directory.

Next, you must add the desired filters to your sendmail configuration (.mc) file. With versions before 8.12, the file must then be processed with _FFR_MILTER defined. Mail filters have three equates: The required S= equate specifies the socket where sendmail should look for the filter; The optional F= and T= equates specify flags and timeouts, respectively. All equates names, equate field names, and flag values are case sensitive.

The current flags (F=) are:




Reject connection if filter unavailable


Temporary fail connection if filter unavailable

If a filter is unavailable or unresponsive and no flags have been specified, the MTA will continue normal handling of the current connection. The MTA will try to contact the filter again on each new connection.

There are three fields inside of the T= equate: S, R, and E. Note the separator between each is a ";" (semicolon), as "," (comma) already separates equates. The value of each field is a decimal number followed by a single letter designating the units ("s" for seconds, "m" for minutes). The fields have the following meanings:




Timeout for connecting to a filter. If set to 0, the system's connect() timeout will be used. Default: 5m


Timeout for sending information from the MTA to a filter. Default: 10s


Timeout for reading reply from the filter. Default: 10s


Overall timeout between sending end-of-message to filter and waiting for the final acknowledgment. Default: 5m

The following example specifies three filters. The first two rendezvous on Unix-domain sockets in the /var/run directory; the third uses an IP socket on port 999.

        INPUT_MAIL_FILTER(`filter1', `S=unix:/var/run/f1.sock, F=R')
        INPUT_MAIL_FILTER(`filter2', `S=unix:/var/run/f2.sock, F=T, T=S:1s;R:1s;E:5m')
        INPUT_MAIL_FILTER(`filter3', `S=inet:999@localhost, T=C:2m')
        define(`confINPUT_MAIL_FILTERS', `filter2,filter1,filter3')
        m4 -D_FFR_MILTER ../m4/cf.m4 >

By default, the filters would be run in the order declared, i.e. "filter1, filter2, filter3"; however, since confINPUT_MAIL_FILTERS is defined, the filters will be run "filter2, filter1, filter3". Also note that a filter can be defined without adding it to the input filter list by using MAIL_FILTER() instead of INPUT_MAIL_FILTER().

The above macros will result in the following lines being added to your .cf file:

        Xfilter1, S=unix:/var/run/f1.sock, F=R
        Xfilter2, S=unix:/var/run/f2.sock, F=T, T=S:1s;R:1s;E:5m
        Xfilter3, S=inet:999@localhost, T=C:2m
        O InputMailFilters=filter2,filter1,filter3

Finally, the sendmail macros accessible via smfi_getsymval can be configured by defining the following m4 variables (or cf options):

In .mc file

In .cf file

Default Value



j, _, {daemon_name}, {if_name}, {if_addr}



{tls_version}, {cipher}, {cipher_bits}, {cert_subject}, {cert_issuer}



i, {auth_type}, {auth_authen}, {auth_ssf}, {auth_author}, {mail_mailer}, {mail_host}, {mail_addr}



{rcpt_mailer}, {rcpt_host}, {rcpt_addr}


4.4 Testing a filter

Once you have compiled a filter, modified your .mc file and restarted the sendmail process, you will want to test that the filter performs as intended.

The sample filter takes one argument -p, which indicates the local port on which to create a listening socket for the filter.  Maintaining consistency with the suggested options for, this would be the UNIX domain socket located in /var/run/f1.sock.

% ./sample -p local:/var/run/f1.sock

If the sample filter returns immediately to a command line, there was either an error with your command or a problem creating the specified socket. Further logging can be captured through the syslogd daemon.  Using the 'netstat -a' command can ensure that your filter process is listening on the appropriate local socket.

Email messages must be injected via SMTP to be filtered.  There are two simple means of doing this; either using the 'sendmail -bs' command, or by telnetting to port 25 of the machine configured for milter. Once connected via one of these options, the session can be continued through the use of standard SMTP commands.

% sendmail -bs

220 ESMTP Sendmail 8.11.0/8.11.0; Tue, 10 Nov 1970 13:05:23 -0500 (EST)

HELO localhost

250 Hello testy@localhost, pleased to meet you

MAIL From:<testy>

250 2.1.0 <testy>... Sender ok

RCPT To:<root>

250 2.1.5 <root>... Recipient ok


354 Enter mail, end with "." on a line by itself



Subject: testing sample filter

Sample body


250 2.0.0 dB73Zxi25236 Message accepted for delivery


221 2.0.0 closing connection

In the above example, the lines beginning with numbers are output by the mail server, and those without are your input.  If everything is working properly, you will find a file in /tmp by the name of msg.XXXXXXXX (where the Xs represent any combination of letters and numbers).  This file should contain the message body and headers from the test email entered above.

If the sample filter did not log your test email, there are a number of methods to narrow down the source of the problem. Check your system logs written by syslogd and see if there are any pertinent lines. You may need to reconfigure syslogd to capture all relevant data.  Additionally, the logging level of sendmail can be raised with the LogLevel option. See the sendmail(8) manual page for more information.

4.5 Security Concerns

Even though sendmail goes through great lengths to assure that it can't be compromised even if the system it is running on is incorrectly or insecurely configured, it can't work around everything. This has been demonstrated by recent OS problems which have subsequently been used to compromise the root account using sendmail as a vector.  One way to minimize the possibility of such problems is to install sendmail without set-user-ID root, which avoids local exploits.  This configuration, which is the default starting with 8.12, is described in the first section of security guide.

** sendmail configuration without set-user-ID root **

sendmail needs to run as root for several purposes:

- bind to port 25

- call the local delivery agent (LDA) as root (or other user) if the LDA

  isn't set-user-ID root (unless some other method of storing e-mail in

  local mailboxes is used).

- read .forward files

- write e-mail submitted via the command line to the queue directory.

Only the last item requires a set-user-ID/set-group-ID program to avoid problems with a world-writable directory.  It is however sufficient to have a set-group-ID program and a group-writable queue directory.  The other requirements listed above can be fulfilled by a sendmail daemon that is started by root.  Hence this section explains how to use two sendmail configurations to accomplish the goal to have a sendmail binary that is not set-user-ID root, and hence is not open to system configuration/OS problems or at

least less problematic in presence of those.

The default configuration starting with sendmail 8.12 uses one sendmail binary which acts differently based on operation mode and supplied options.

sendmail must be a set-group-ID (default group: smmsp, recommended gid: 25) program to allow for queueing mail in a group-writable directory.  Two .cf files are required: for the daemon and for the submission program.  The following permissions should be used:

-r-xr-sr-x  root   smmsp      ... /PATH/TO/sendmail

drwxrwx---  smmsp  smmsp      ... /var/spool/clientmqueue

drwx------  root   wheel      ... /var/spool/mqueue

-r--r--r--  root   wheel      ... /etc/mail/

-r--r--r--  root   wheel      ... /etc/mail/

That is, the owner of sendmail is root, the group is smmsp, and the binary is set-group-ID.  The client mail queue is owned by smmsp with group smmsp and is group writable.  The client mail queue directory must be writable by smmsp, but it must not be

accessible for others. That is, do not use world read or execute permissions.  In the option UseMSP must be set, and QueueFileMode must be set to 0660. is available in cf/cf/, which has been built from cf/cf/  The file can be used as-is, if you want to add more options, use cf/cf/ as starting point and read cf/README:  MESSAGE SUBMISSION PROGRAM carefully.

The .cf file is chosen based on the operation mode.  For -bm (default), -bs, and -t it is (if it exists) for all others it is  This selection can be changed by -Ac or -Am (alternative .cf file: client or mta).

The daemon must be started by root as usual, e.g.,

/PATH/TO/sendmail -L sm-mta -bd -q1h

(replace /PATH/TO with the right path for your OS, e.g.,

/usr/sbin or /usr/lib).

Notice: if you run sendmail from inetd (which in general is not a good idea), you must specify -Am in addition to -bs.

Mail will end up in the client queue if the daemon doesn't accept connections or if an address is temporarily not resolvable.  The latter problem can be minimized by using

FEATURE(`nocanonify', `canonify_hosts')


which, however, may have undesired side effects.  See cf/README for a discussion.  In general it is necessary to clean the queue either via a cronjob or by running a daemon, e.g.,

/PATH/TO/sendmail -L sm-msp-queue -Ac -q30m

If the option UseMSP is not set, sendmail will complain during queue runs about bogus file permission.  If you want a queue runner for the client queue, you probably have to change OS specific scripts to accomplish this (check the man pages of your OS for more information.)  You can start this program as root, it will change its user id to RunAsUser (smmsp by default, recommended uid: 25).

This way smmsp does not need a valid shell.

4.6 Summary

This is a brief summary how the two configuration files are used:       For the MTA (mail transmission agent)

            The MTA is started by root as daemon:

            /PATH/TO/sendmail -L sm-mta -bd -q1h

            it accepts SMTP connections (on ports 25 and 587 by default);

            it runs the main queue (/var/spool/mqueue by default).           For the MSP (mail submission program)

            The MSP is used to submit e-mails, hence it is invoked

            by programs (and maybe users); it does not run as SMTP

            daemon; it uses /var/spool/clientmqueue by default; it

            can be started to run that queue periodically:

      /PATH/TO/sendmail -L sm-msp-queue -Ac -q30m