$Id: README,v 1.7.2.3 2010/07/13 23:51:21 grooverdan Exp $

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

This is the development area for The OpenDKIM Project's DKIM filter, which is
our implementation of the DKIM service.

The filter implemented here, if plugged into the a Milter-aware MTA, provides
signing and verification service as per the DKIM specification.

COMPILING
=========

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

To build and install this package:

(1) Download and unpack the source package.
(2) Change to the opendkim-(version) directory.
(3) Type "./configure".
(4) Type "make".
(5) Type "make install"


INSTALLING
==========

(1) Configure your MTA:

    For 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(`opendkim', `S=inet:8891@localhost')
    (c) Rebuild your sendmail.cf in the usual way

    For Postfix:
    (a) Choose a socket at which the MTA and the filter will rendezvous
        (see the documentation in libmilter for details).  Be careful with
        UNIX domain sockets as on some distrubutions and setups the smtpd
        process is running in a chroot environment.  A UNIX socket will
        need to be visible to the chrooted smtpd process.
    (b) Add a line like this example to your postfix main.cf using your
        desired socket specification:

	    smtpd_milters = inet:8891@localhost
	    non_smtpd_milters = inet:8891@localhost
	
    (c) If you have a content filter in master.cf that feeds it back into a
        different smtpd process, you should alter the second smtpd process in
	master.cf to contain '-o receive_override_options=no_milters' to
	prevent messages being signed or verified twice.  For tips on avoiding
	DKIM signature breakage, see:
	http://www.postfix.org/MILTER_README.html#workarounds

(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 "opendkim-genkey.sh -s SELECTOR". The opendkim-genkey man
      page has full details of options.  This will generate a private key
      in PEM format and output a TXT record containing the matching public
      key 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 1024
    (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:

	  "v=DKIM1; t=y; p=MFwwDQYJ...AwEAAQ=="

          ...using, of course, your own public key with is the base64 data 
	  from the generated rsa.public file.

	  NOTE:  Keysizes above 2700 bits are unlikely to fit into a 512 byte
	  DNS record.

(4) Publish your public DNS key.
    The public key DNS record should appear as a TXT resource record at:

        SELECTOR._domainkey.DOMAIN

    SELECTOR is the name you chose with the Selector config option or the
    result of the KeyTable lookup.

    DOMAIN is the domain name specified in the "-d" command line, the Domain 
    option in the configuration file, or the domain that would be returned
    from a KeyTable lookup.
  
    For a translation of the parameters and value pairs, see RFC4871.  Using 
    "t=y" is indicates you are in "test mode", advising verifiers that they
    should not take any real action based on success or failure of the use
    of this key after verifing a message.  Remove the "t=y" once you have
    tested the DKIM signing of your messages to your satisfaction.

    You might want to set a short TTL on this record during testing so
    changes are propagated to other nameservers more quickly.

    Reload your nameserver to publish the changes.

    Check that the DNS server is returning your published DNS record.  Be
    aware that synchronization to secondary DNS servers and negative caching
    of DNS resolver servers may effect the results observed.  For reliable
    results, query your DNS server directly:

        dig -t txt SELECTOR._domainkey.DOMAIN NAMESERVER
 
    NAMESERVER is a nameserver for your domain.  You can get a list of these
    using:

        dig -t ns DOMAIN

    If the key can be retreived correctly then opendkim-testkey can be used to
    verify that the key matches the private key.

        opendkim-testkey -d DOMAIN -s SELECTOR -k rsa.private

    BIND servers have a 256 byte limit on serving TXT records, so a 1024 bit 
    RSA key is recommended if using BIND as your primary DNS server.

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

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

	-l -p SOCKETSPEC -d DOMAIN -k 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.

(6) Restart/reload your MTA.


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

Two configuration file entries are provided to enable detailed debugging
and forensics when tracking down failed verifications.  These are
"KeepTemporaryFiles" and "TemporaryDirectory".

When a message is to be signed or verified, its headers and body are passed
through a selected canonicalization algorithm.  The output of this algorithm
is stored in a pair of temporary files if "KeepTemporaryFiles" is enabled.
If a verifier and a signer both produce these files, they can be compared
after a failed verification to determine how the signed data and verified
data differ.

"TemporaryDirectory" simply selects the directory to be used to create
these files, if other than the default (/var/tmp) is desired.

These debug features are useful when using a remote verifier that is equipped
to send back replies which contain the canonicalization output at the remote
end.  Such a verifier, when a signature verification fails, will ask the
sending domain for its sender policy.  If that policy exists and contains
an "r=" tag, then the verifier will send a message to the address
contained in that tag which contains the canonicalized forms of the failing
message as generated at the verifier.  Comparing these forms to the local
copies of the same (generated as described above) using a utility such as
"diff" will show how a message was modified between the signing and verifying
operations.  This will usually reveal the cause of the failed verification.


REUSING DOMAINKEYS RECORDS
==========================

Published DomainKeys key records are almost totally compatible with DKIM.
The one area in which they differ is the use of the granularity ("g=") tag.

Under DomainKeys, the default granularity is the empty string.  DomainKeys
interprets this as "match anyone".  However, DKIM interprets this as
"match none".  Thus, a key record containing "g=" means one thing to
DomainKeys but the opposite to DKIM, making it incompatible.

Under DKIM, the default granularity is "*", which means "match anyone".

Since both systems have defaults that mean "match anyone", a DomainKeys
key record which doesn't have a "g=" string in it at all will work as
expected with DKIM.  Thus, if you want to use one key record with both
systems, remove the "g=" portion of the record and reload your nameserver.


UPGRADING FROM 1.x to 2.x
=========================

Configuration files from v1.x.x installations of OpenDKIM are compatible
with v2.x.x except for the "KeyList" feature, which has been dropped in
favour of a more flexible configuration.

The "KeyList" in older versions was a file of this form:

	pattern:domain:selector:keypath

...where:

	"pattern" was a pattern to be matched against the From: header field
	of a message being considered for signing, with the asterisk ("*")
	character being used as the conventional wildcard

	"domain" was the domain to be used when generating the signature

	"selector" was the selector to be used when generating the signature

	"keypath" was the path to the private key to be used to generate
	the signature

In the newer configuration files, this function has been split into two
different files.  The first, known as the "KeyTable", maps names of keys
to domains, selectors and keys, and the second, known as the "SigningTable",
maps sender patterns to entries in the first.

So if for example an older installation had the following KeyList:

	*@example.com:example.com:foo:/var/db/dkim/foo.private
	*@example.net:example.net:bar:/var/db/dkim/bar.private

This would now be split into the two new data sets.  In recent versions of
OpenDKIM, a data set can be in any of a number of actual forms (SQL databases,
flat files, LDAP directories, regular expression files, etc.) so these will
be expressed in terms of their data set keys (the item looked up) and values
(the item or items returned).  So in the new setup, a KeyTable matching
the above setup will contain:

	KEYS		VALUES
	----		------
	K1		example.com
			foo
			/var/db/dkim/foo.private

	K2		example.net
			bar
			/var/db/dkim/bar.private

This defines the keys that will be used to sign.  Then it is necessary to
tell the filter which addresses get signed by which keys, so the SigningTable
will contain:

	KEYS		VALUES
	----		------
	example.com	K1
	example.net	K2

Consult SigningTable in opendkim.conf(5) man page for a description of the
expected keys and values in the SigningTable data set.


DATA SETS
=========

Several OpenDKIM configuration values describe lists or sets of data, sometimes
with associated values.  OpenDKIM refers to these as "data sets".  They
can be stored in a variety of ways such as comma-separated lists, flat files,
files involving pattern matching (called "refiles"), Oracle/Sleepycat Berkeley
databases (hash or btree), SQL databases, Lua scripts or LDAP directories.

For some data sets, merely a test for membership in the set is done.  Such
entries only have "keys" (items in the set), with no associated "values".

`file' and `refile' data sets are nearly identical.  Each is a flat file
containing two columns separated by whitespace.  The left column is the key
and the right the value (as described above).  If more than one value appears
in the right column, then those values should be separated by colons, e.g.:

	key	value1:value2:value3

For example, the difference is that the key column of a `file' SigningTable
is matched exactly in the order described in opendkim.conf(5), while the key
column of a `refile' SigningTable is a glob-style expression using where "*"
is treated as zero or more characters.  The `refile' matching syntax is
the same as that of an OpenDKIM 1.x KeyList.

The `csl' data set works exactly he same way as a `file' data set, but instead
of specifying a file to read, it specifies a list of data separated by commas,
e.g.:

	csl:key1 value1,key2 value2

The `bdb' data set simply reads those key/value pairs from a Berkeley-style DB
file (also known as a Sleepycat DB) rather than a flat file or list.

For LDAP data sets, the search filter and the attributes to be returned
should be provided in the LDAP URI.  Any instances of `$d' in the LDAP
filter will be replaced with the domain or email address being queried for
(with the search terms as described above).

For instance, a simple SigningTable data set that searches for the "mail"
attribute and returns a "keyName" attribute might be:

	ldap://localhost/dc=example,dc=com?keyName?sub?(mail=$d)

The general format for using an LDAP directory in a data set is:

	ldap://host[:port]/basedn[?attrs[?scope[?filter[?exts]]]]

The scheme ldaps:// may be used to connect via SSL, and ldapi:// may be
used to connect via UNIX socket.

LDAP credentials are stored in the opendkim.conf file.

For ODBX (SQL database) data sets, a similar mechanism is used, but the URI
must also be tagged with the prefix "dsn:".  For the example above,
returning columns in a PostgreSQL database instead of LDAP attributes, you
might use:

	dsn:pgsql://username:password@localhost/dkim/table=dkimkeys?keycol=keyName?datacol=mail

The general format for using a database in a data set is:

	dsn:<backend>://[user[:pwd]@][port+]host/dbase[/key=val[?...]]

The special DSN keys "table", "keycol" and "datacol" are required to name the
database from which to select records, the column in which keys will be found,
and the column(s) from which their corresponding values should be extracted.

A Lua script can be specified as below:

        lua:/usr/local/keyretrive.lua

The Lua script will receive a global variable called "query" which is a string
containing the query to be performed.


SUPPORT
=======

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

	opendkim-announce@lists.opendkim.org (release announcements)
	opendkim-users@lists.opendkim.org (general discussion)

Send an email to opendkim-announce-request@lists.opendkim.org with subscribe
as the subject to receive release announcements.  You can find more
information about our mailing lists at http://www.opendkim.org.

To report bugs and feature requests, you can access the SourceForge "tracker"
facilities at http://sourceforge.net/projects/opendkim.
