LDAP LOOKUPS
------------

This text contains general LDAP-related documentation. Please also
see README.lookups for additional lookup information.

LDAP lookups are enabled in amavisd.conf with:

$enable_ldap  = 1;

Definitions and default values of LDAP parameters.

  hostname      : The hostname or IP address or a socket path of the LDAP
                  server to connect to. A TCP port may be specified after
                  the host name followed by a colon (ex. localhost:389).
                  You can also specify a URI, such as:
                  'ldaps://127.0.0.1:636' or
                  'ldapi://%2Fvar%2Frun%2Fopenldap%2Fldapi/'.
                  May also be a reference to an array of hosts,
                  host:port pairs, or URI's, each will be tried in
                  order until a connection is made.
                  (Default = 'localhost')
  port          : The port where LDAP sends queries. May be overridden
                  by 'hostname'.
                  (Default supplied by Net::LDAP: 389, or 636 if using TLS/SSL)
  localaddr     : Will be passed to IO::Socket as the "LocalAddr" parameter,
                  which sets the client's IP address (as opposed to the
                  server's IP address.) (Default: undef (i.e. unspecified))
  scheme        : Connection scheme to use when not using an URI as "HOST",
                  possible values are: 'ldap', 'ldaps', or 'ldapi'.
                  (Default: 'ldap', unless a hostname starts with a string
                  'ldaps', in which case the default scheme is 'ldaps')
  inet6         : Try to connect to the server using IPv6 if "HOST" resolves
                  to an IPv6 target address. If it resolves to an IPv4 address,
                  the connection is tried using IPv4.
                  (Default: 1 if a module IO::Socket::INET6 is available,
                  0 otherwise)
  version       : The protocol version to use.
                  (Default = 3)
  timeout       : Timeout (in sec) passed when connecting the remote
                  server.
                  (Default = 120)
  base          : The DN that is the base object entry relative to
                  which the search is to be performed. The string may
                  also contain a '%d' token that will be replaced by
                  the e-mail address domain.
                  (Default = undef)
  scope         : Scope can be 'base', 'one' or 'sub'.
                  (Default = 'sub')
  query_filter  : The filter used to find the amavis account. The string
                  must contain a '%m' token that will be replaced by the
                  actual e-mail address.
                  (Default = '(&(objectClass=amavisAccount)(mail=%m))')
  deref         : By default aliases are dereferenced to locate the base
                  object for the search, but not when searching subordinates
                  of the base object. This may be changed by specifying a
                  "deref" parameter with one of the following values:
                  'never', 'search', 'find', 'always'. (Default = 'find')
  bind_dn       : If binding is needed, this specifies the DN to bind as.
                  (Default = undef)
  bind_password : Binding password.
                  (Default = undef)
  sasl          : Enable SASL if true.
                  (Default = 0)
  sasl_mech     : A space-separated list of SASL mechanisms.
                  (Default = '')
  sasl_auth_id  : SASL authentication id (e.g. a username)
                  (Default = undef)
  tls           : Enable TLS/SSL if true.
                  (Default = 0)
  sslversion    : SSL version: sslv2, sslv3, sslv2/3, tlsv1
                  (Default = 'tlsv1')
  clientcert    : A filename with a client certificate.
                  (Default = undef)
  clientkey     : A filename with a client certificate private key.
                  (Default = undef)
  cafile        : A filename containing the certificate of the CA
                  who signed the server's certificate.
                  (Default = undef)
  capath        : A pathname of a directory containing CA certificates.
                  (Default = undef)
  verify        : How to verify the server's certificate:
                  none, optional, require
                  (Default = 'none')

The desired parameters can be specified in amavisd.conf and defaults
will be supplied for any parameters not specified, ex:

$default_ldap = {
  hostname      => [ 'localhost', 'ldap2.example.com' ],
  timeout       => 5,
  tls           => 0,
  base          => 'ou=People,dc=example,dc=com',
  query_filter  => '(&(objectClass=amavisAccount)(mail=%m))',
};

The amavisd-new LDAP schema is available in file LDAP.schema of the
distribution, and at http://www.ijs.si/software/amavisd/LDAP.schema

LDAP 'search' requests all available fields from the specified directory and
the result is cached (just for the duration of this mail message processing).
Individual attributes can be extracted one at a time from this cache
very quickly, so there is no penalty in using several calls to lookup
for different attributes (for the same key) in different parts of the
program.

lookup_ldap() performs a lookup for an e-mail address in an LDAP
directory. If a match is found it returns whatever the map returns
(a reference to a hash containing values of requested attributes),
otherwise returns undef. Given an e-mail address the following lookups
are done by default:

with $ldap_lookups_no_at_means_domain = 0   (default):

 - lookup for user+foo@example.com
 - lookup for user@example.com (only if $recipient_delimiter is '+')
 - lookup for user+foo (only if domain part is local)
 - lookup for user     (only local; only if $recipient_delimiter is '+')
 - lookup for @example.com
 - lookup for @.example.com
 - lookup for @.com
 - lookup for @.       (catchall)

With $ldap_lookups_no_at_means_domain = 1 :

 - lookup for user+foo@example.com
 - lookup for user@example.com (only if $recipient_delimiter is '+')
 - lookup for user+foo@ (only if domain part is local)
 - lookup for user@     (only local; only if $recipient_delimiter is '+')
 - lookup for example.com
 - lookup for .example.com
 - lookup for .com
 - lookup for .         (catchall)

NOTE: a null reverse path e-mail address used by MTA for delivery status
notifications (DSN) has empty local part and empty domain. As far as the
lookup is concerned (which uses raw, i.e. non-quoted and non-bracketed
address form), this address is @, i.e. a single character "@".
The LDAP lookup for null address goes through the following sequence
of keys: "", "@", "@." (double quotes added for clarity, they are not
part of the query key).

lookup_ldap_attr() also performs a lookup for an e-mail address against
an LDAP directory. It first calls lookup_ldap() if it hasn't been called
yet for this key, but instead of returning all available attributes,
it returns just a value of one particular attribute. This is the
subroutine that gets called from lookup() for arguments (objects) of
type Amavis::Lookup::LDAPattr.

LDAP white/black listing
------------------------

amavisWhitelistSender/amavisBlacklistSender are multivalued attributes
containing either full email addresses or domain specifications. The
envelope sender address is compared against each attribute value until
a match is made.

amavisBlacklistSender: user@example.com
amavisBlacklistSender: @example.com
amavisBlacklistSender: @.example.com

A domain specification with a leading '@.' matches a domain as well
as its subdomains.

LDAP banned rule names
----------------------

amavisBannedRuleNames may contain a comma-separated list of names mapped
through %banned_rules to actual banned_filename tables.

amavisBannedRuleNames: ALLOW_EXE, DEFAULT

<amavisd.conf>

%banned_rules = (
  'NO-MS-EXEC'=> new_RE( qr'^\.(exe-ms)$' ),
  'PASSALL'   => new_RE( [qr'^' => 0] ),
  'ALLOW_EXE' => new_RE( qr'.\.(vbs|pif|scr|bat)$'i, [qr'^\.exe$' => 0] ),
  'ALLOW_VBS' => new_RE( [qr'.\.vbs$' => 0] ),
  'DEFAULT'   => $banned_filename_re,
);

Special handling of optional LDAP attribute 'amavisLocal'
---------------------------------------------------------

A special shorthand is provided when LDAP lookups are used: when a match
for a recipient address (or domain) is found in LDAP tables (regardless of
attribute values), the recipient is considered local, regardless of static
@local_domains_acl or %local_domains lookup tables. This simplifies
life when a large number of dynamically changing domains is hosted.

To overrule this behaviour, have an explicit boolean attribute 'amavisLocal'
with a value of True returned for each local domain, and False for other
domains which might be present in LDAP for some reason, but are nonlocal.

In general LDAP lookups are similar to SQL lookups except for the low level
LDAP/SQL specific code. The overall functionality, lookup rules, etc. are
identical.
