$Id: README,v 1.15 2008/03/05 18:11:38 msk Exp $

INTRODUCTION
============


This is the development area for Sendmail's DomainKeys filter, which is our
implementation of the Yahoo! DomainKeys service.

The filter implemented here, if plugged into the Sendmail MTA, provides
signing and verification service as per Yahoo!'s DomainKeys specification.


ADVISORY
========

THIS IS PRE-RELEASE SOFTWARE, and should not be used in any critical
production environments (yet).  However, we hope this pre-release period
will be as brief as possible so that it can be sanctioned for mainstream
use.


COMPILING
=========

Requires sendmail v8.13.0 or later, for required milter protocol
enhancements.

To build this package in the public domain:

(1) Download and unpack the source package.
(2) Change to the dk-milter-(version) directory.
(3) Edit libdk/Makefile.m4 and dk-filter/Makefile.m4 as indicated in those
    files to specify the locations of the OpenSSL include and library files.
(4) Type "sh Build".


INSTALLING
==========

(1) Configure sendmail:
  (a) Choose a socket at which the MTA and the filter will rendezvous
      (see the documentation in libmilter for details)
  (b) Add a line like this example to your sendmail.mc using your desired
      socket specification:
	INPUT_MAIL_FILTER(`dk-filter', `S=inet:8891@localhost')
  (c) Rebuild your sendmail.cf in the usual way

(2) Choose a selector name.  Current convention is to use the hostname
    (hostname only, not the fully-qualified domain name) of the host that
    will be providing the service, but you are free to choose any name you
    wish, especially if you have a selector assignment scheme in mind.

(3) Either:
  (a) Run the script gentxt.csh.  This will generate a public and private
      key in PEM format and output a TXT record appropriate for insertion
      into your DNS zone file.  Insert it in your zone file and reload your
      DNS system so the data is published.
	-OR-
  (b) Manually generate a public and private key:
    (i)   % openssl genrsa -out rsa.private 512
    (ii)  % openssl rsa -in rsa.private -out rsa.public -pubout -outform PEM
    (iii) Add a TXT DNS record containing the base64 encoding of your public
          key, which is everything between the BEGIN and END lines in the
          rsa.public file generated above, with spaces and newlines removed.
          It should be in this form:

	  "k=rsa; t=y; p=MFwwDQYJ...AwEAAQ=="

          ...using, of course, your own public key's base64 data.  The name of
          the TXT record should be SELECTOR._domainkey.example.com (where
          "SELECTOR" is the name you chose and "example.com" is your domain
          name).  You might want to set a short TTL on this record.  Reload
          your nameserver so that the record gets published.  For a translation
          of the parameter and value pairs shown here, see the draft spec;
          basically this just announces an RSA public key and also declares
          that your site is using this key in test mode so nobody should take
          any real action based on success or failure of the use of this key to
          verify a message.

(4) Store the private key in a safe place.  We generally use a path like
    /var/db/domainkeys/SELECTOR.key.pem (where "SELECTOR" is the name you
    chose).

(5) Start dk-filter.  You will need at least the "-p" option.  The current
    recommended set of command line options is:

	-l -p SOCKETSPEC -d DOMAIN -s KEYPATH -S SELECTOR

    ...where SOCKETSPEC is the socket you told sendmail to use above,
    DOMAIN is the domain or set of domains for which you want to sign
    mail, KEYPATH is the path to the private key file you generated, and
    SELECTOR is the selector name you picked.  You can tack "-f" on there
    if you want it to run in the foreground instead of in the background
    as a daemon.

(7) Restart sendmail.


DEBUG FEATURES
==============

The DKDEBUG environment variable, if set, specifies debugging options to
be applied by the filter.  Note that libdk uses the same variable name
(for now) so there may be some overlap in the debug flags used.
See libdk/README for details.

The contents of DKDEBUG should be a string containing characters representing
the required debug options as depicted in this list:

	t	thread progress; each callback is logged at LOG_INFO
		along with the thread ID

You can also compile the package with the -DDEBUG flag, which builds a version
of dk-filter that reads from standard input and dumps trace data to standard
output.  The input should be an RFC2822 message with the following lines
prepended:

	Fuser@example.com
	.

The first line, starting with "F", defines the envelope sender.  The value
of this is not actually used, but the mechanism is present and requires
the input.  The "." line separates the message headers and body from the
envelope and must also be included.

On standard output you will see each of the milter callbacks that are made
by the filter in response to the input, and ultimately the milter return
values, the headers that are added, modified or removed, and any changes to
the message body that result.  You can only feed one message per execution of
the debug mode of the program, and the program will terminate when a result
is produced.


COMMON PROBLEMS
===============

1) MASQUERADE, etc.

Since dk-filter plugs into the sendmail MTA at the SMTP level (i.e. before
most MTA processing), the headers it sees are the raw headers as provided
but the SMTP client.  Therefore, if the MTA changes any of the headers
which are used in the signature, the message which gets signed outbound and
the message which gets verified at the receiver will not be the same and
signatures will fail.

The solutions available to solve this are:

a) Don't use MASQUERADE, genericstable, or any other feature which alters
the headers before they are sent to the next hop.

b) Run a second MTA which receives messages after they have been altered
as described above.

c) Anticipate the rewrites the MTA will do and send your mail with those
modifications already made.  For example, if user@hostname.example.com will be
rewritten by your MTA as user@example.com, arrange that your MUAs will send
mail that way so that the MTA doesn't actually rewrite anything.


2) Spacing rewrites

The MTA will helpfully remove extraneous spaces at the beginning and end
of headers.  Thus, a message injected with a header that reads:

	From:  <foo@example.com>

...will be reduced and sent by the MTA as:

	From: <foo@example.com>

However, dk-filter sees the earlier form and signs based on that.  Therefore,
again, the signed message and the verified message differ and verification
will not succeed.  Thunderbird and Mozilla are known to have this problem
when configured a certain way.

The solutions available:

a) Don't inject messages with spaces the MTA will strip.

b) Compile with the ANTICIPATE_SENDMAIL_MUNGE enabled.


3) Missing Message-Id: header

The DomainKeys specification stipulates that normally all headers below
the signature header are included in the signed version of the message.
Thus, the positions of headers added by the MTA are significant when
applying this specification.

If you inject a message with SMTP but don't include a Message-Id: header,
the MTA will generate one for you.  The problem here is that dk-filter never
sees the header that gets added so it's not included in the signed message;
however, that header will be added in such a position that the verifier will
assume that it is part of the signed message, and thus the signed and
verified messages won't match and the verification will fail.

The solutions available:

a) Restart dk-filter with the "-H" flag, which adds an additional tag
to DomainKeys signatures that indicate specifically which headers should
when reconstructing the message during verification.  Thus, even if the
Message-Id: header is not present during signing and the MTA adds it later
below the signature, the verifier will be informed that it should be
omitted during signature verification.

b) Always send mail with a proper Message-Id: header included in the message.


4) Added Headers

Similarly, if you are running filters which add headers that appear in the
flow of mail after dk-filter signs the message, those headers will be
included when verifying although they were not included when signing.

The solutions available:

a) Have those filters insert their headers above the DomainKey-Signature:
header rather than adding them below.

b) Restart dk-filter with the "-H" flag as described above.


SUPPORT
=======

To get support or report bugs, you can access the Sourceforge "tracker"
facilities at http://sourceforge.net/projects/dk-milter.

There are two public mailing lists available for news and questions about
dk-milter.  To keep up to date on the latest developments, please
subscribe to one or both of the following:

	dk-milter-announce@lists.sourceforge.net (release announcements)
	dk-milter-discuss@lists.sourceforge.net (general discussion)

You can subscribe to these lists via the project URL above.  There is also
a private mailing list which should be used to report security bugs or
other potentially sensitive issues:

	dk-milter-security@lists.sourceforge.net (security issues)
