Database-maps can be used to look up information in databases, to perform transformations (such as dequoting), to perform computations, and to store values into macros.
V8.13 sendmail has expanded the roles of database-maps in the following ways:
Two new ldap
database-map switches have
been
added: -w
(Section 23.1.1.1
[V8.13]) allows you
to specify the LDAP API/protocol version to use;
-H
(Section 23.1.1.2
[V8.13]) allows you
to specify an LDAP URI instead of specifying the LDAP server with
both the -h
host
(23.7.11.4[3ed]) and -p
port (23.7.11.9[3ed]).[30]
LDAP Recursion has been added (Section 23.1.2[V8.13])
with
support for the
AliasFile
option
(24.9.1[3ed]) and class macros.
The ldap_routing
feature’s third
argument
may now be a literal sendertoo
to reject
nonexistent envelope sender addresses. (Section 23.1.3
[V8.13])
The ldap_routing
feature has had its arguments
expanded from four to six. Support has been added to suppress an
extra lookup of part of an unmatched address and to specify how to
handle connection errors to and temporary failures from the LDAP
server (Section 23.1.4
[V8.13]).
The dnsbl
feature
(7.2.1[3ed]) no longer uses the
host
database-map type to look up addresses.
Instead, it now uses the dns
database-map type
(Section 9.1.1
[V8.13]). The
DNSBL_MAP_OPT
mc
macro (Section 9.1.1
[V8.13]) has been
added to help tune the use of the dns
database-map
type with the dnsbl
feature. (These new items are
described in Chapter 9.)
The new socket
database-map type (Section 23.1.5
[V8.13]) allows
queries to be made over Unix-domain and TCP/IP sockets.
The ph
database-map type
(23.7.18[3ed]) -v
switch (formerly deprecated) has been removed. Use the
-k
switch, instead, which is (and has been) the
official replacement switch.
V8.13 sendmail has added two new switches to the
ldap
database-map type: -w
and
-H
.
When you build sendmail
, you can
include support for the
ldap
database-map type by adding
-DLDAPMAP
to confMAPDEF
in your
Build
m4
file:
APPENDDEF(`confMAPDEF´, `-DLDAPMAP´)
If your LDAP library returns one API version, but your LDAP server
uses a different one, you can insist that
sendmail use the version on the server by
supplying this new -w
switch with your
ldap
database-type declaration. For example, to
look up a login name in an LDAP database and have the official email
address for that user returned, you might use a declaration like
this:
Kgetname ldap -k"uid=%s" -v"mail" -hhost
-b"o=Organization, c=US" -w3
Note that the trailing argument to this K
configuration line is the new -w
switch, which
specifies your wish to use LDAP API Version 3 with the server running
on host
.
If your system’s <ldap.h>
include file defines a maximum API version, and you exceed that
maximum with -w
, the following error will print:
LDAP versionspecified
exceeds max ofmax
in mapname
If your system’s <ldap.h>
include file defines a minimum API version, and you specify too low a
minimum with -w
, the following error will print:
LDAP versionspecified
is lower thanmin
in mapname
Either error will cause the API version specified with
-w
to be ignored. For example, on Solaris 9, with
Sun supplied LDAP, the minimum and maximum are both set to
3
.
Modern versions of LDAP allow you
to specify Universal Resource
Identifiers (URI) in place of host and port combinations when
specifying an LDAP server. Beginning with V8.13
sendmail, you may specify an LDAP URI by
utilizing the new -H
database-map switch. For
example, prior to V8.13 sendmail
, you might have
used an mc
configuration statement like this:
define(`confLDAP_DEFAULT_SPEC´, `-h ldap.example.gov -p 8389´)
Here, -h
specifies the LDAP server host and
-p
specifies the nonstandard port 8389. Beginning
with V8.13, you can simplify this declaration by using the new
-H
database-map switch:
define(`confLDAP_DEFAULT_SPEC´, `-H ldap://ldap.example.gov:8389´)
One advantage to using -H
is that it allows you to
fetch the URI from a secure server by using
ldaps://
instead of
ldap://
—for example:
define(`confLDAP_DEFAULT_SPEC´, `-H ldaps://ldap.example.gov -b dc=example,dc=gov´)
Here, the -b
LDAP database-map switch
(23.7.11.2[3ed]) specifies the base from
which to begin the search. If, rather than reading from a TCP/IP
socket, your LDAP server uses a Unix-domain socket, you may use
ldapi://
instead of ldap://
, to
access that Unix-domain socket:[31]
define(`confLDAP_DEFAULT_SPEC´, `-H ldapi:// -b dc=example,dc=gov´)
Note that, when you build sendmail
with LDAP
support, the sendmail
source determines whether
you have a working ldap_init
( ) function in your
LDAP library. If you do (and all modern versions of LDAP do), you
will be allowed to use the new -H
database-map
switch. If not, you will see the following warning when you attempt
to use it:
Must compile with -DUSE_LDAP_INIT to use LDAP URIs (-H) in map name
If you believe sendmail
interpreted your LDAP
setup wrongly, you may define USE_LDAP_INIT
when
building to correct the error.
Prior to V8.13, LDAP lookups could only return the actual data sought, rather than information that would automatically result in another lookup. Beginning with V8.13, lookups are allowed to be recursive. LDAP recursion allows a query to return either: a new query; a Distinguished Name (DN); or an LDAP URL. When any of these are returned, they result in another lookup.
LDAP recursion is requested with the -v
ldap
database-map switch
(23.7.11.14[3ed]), which specifies the
list of attributes to return. Recursion is caused by specifying
attributes like this:
-vattribute
:type
:objectclass
|objectclass
|...
Here, the type
can be one of four literal
values: NORMAL
, DN
,
FILTER
, or URL
.
The NORMAL
type says that the
attribute
will be added to the result of
the lookup if the record found is a member of the
objectclass
specified. This is the default
type if type
is omitted.
The DN
type expects that any matches of the
attribute
have a fully qualified
distinguished name. The sendmail
program will
perform a second lookup of the attribute
using the returned DN
record.
The FILTER
type requires that any matches of the
attribute
have the value of an LDAP search
filter. The sendmail
program will perform the
same lookup again but will replace the original search filter with
the new filter returned.
The URL
type expects that the lookup will return a
URL
. The sendmail
program
will perform a lookup using the returned URL
and
will then use the resulting attributes returned.
The objectclass
list is optional and, if
present, contains the object-class values for which the
attribute
applies. If there is more than
one object-class value, each must be separated from the next by a
vertical bar character (|
). If object-class values
are listed, the attribute
will only be
used if the LDAP record returned by a lookup is a member of any of
the object-class values listed.
Note that recursion is liberal. It is not an error if recursion ultimately fails to lead to an LDAP record. The lookup will simply fail in the same manner as it would if a record does not exist.
To illustrate, consider the following mc configuration file lines.
define(`confLDAP_DEFAULT_SPEC´, `-H ldaps://ldap.example.gov -b dc=example,dc=gov´) LOCAL_CONFIG Kgetname ldap -k (&(objectClass=sendmailMTAAliasObject)(sendmailMTAKey=%0)) -v sendmailMTAAliasValue, mail:NORMAL:inetOrgPerson, uniqueMember:DN:groupOfUniqueNames, sendmailMTAAliasSearch:FILTER:sendmailMTAAliasObject, sendmailMTAAliasURL:URL:sendmailMTAAliasObject
First, we use -H
when defining
confLDAP_DEFAULT_SPEC
. The use of
ldaps://
, instead of ldap://
,
allows us to connect to the secure server,
ldap.example.gov.
Second, under the LOCAL_CONFIG
part of our
mc
configuration file, we define a database map
using the K
configuration command. We give the
database-map the name getname
and the type
ldap
. The -k
LDAP database-map
switch specifies the LDAP search query to use.
The -v
ldap database-map
switch illustrates LDAP recursion. There are five statements
following -v
, each on its own line for clarity and
each separated from the next by a comma. The first statement is a
lone attribute named sendmailMTAAliasValue
.
Because it lacks a colon-keyword type, it is presumed to be type
NORMAL
. Here, any value in the
sendmailMTAAliasValue
attribute will be added to
any result-string regardless of any object-classes (because the
attribute has no object-classes).
The second statement shows an attribute named
mail
, defined to be the type
NORMAL
, with a single object-class called
inetOrgPerson
. The value in the attribute
mail
will be added to the result string only if
the LDAP record that is looked up is a member of the
inetOrgPerson
object-class. The type
NORMAL
is not recursive. Only a single lookup is
performed and only a single result is added to the string.
The third statement shows an attribute named
uniqueMember
, defined to be the type
DN
, with a single object-class called
groupOfUniqueNames
. The type DN
makes the action associated with the attribute
uniqueMember
recursive. When
uniqueMember
is looked up, the return value may
contain zero or more DN
records that belong to the
object-class groupOfUniqueNames
. Each of those
returned DN
records will again be searched to find
any of the attributes listed in the -v
line.
The forth statement shows an attribute named
sendmailMTAAliasSearch
, defined to be the type
FILTER
, with an object-class
sendmailMTAAliasObject
. The type
FILTER
makes the attribute
sendmailMTAAliasSearch
recursive. A lookup is made
using the initial search (the -k
line) to find any
new filters that are in the object-class
sendmailMTAAliasObject
. For any that are found, a
second lookup is performed using each new filter, to return any
records that contain any of the attributes listed in the
-v
line.
The fifth statement shows an attribute named
sendmailMTAAliasURL
, defined to be the
type
URL, with an object-class called
sendmailMTAAliasObject
. The type
URL
makes the attribute
sendmailMTAAliasURL
recursive. A lookup is made
using the default URL to find any new URLs that are in the
object-class sendmailMTAAliasObject
. For any that
are found, a second lookup is performed using each new
URL
to return records that contain the attributes
requested in the original search.
As of V8.13, the default schema for alias lookups using LDAP has been changed to include LDAP recursion support. Recall that you declare alias lookups with LDAP like this:
define('ALIAS_FILE´, `ldap:´)
This causes aliases to be looked up using LDAP and the following default schema:
ldap -k (&(objectClass=sendmailMTAAliasObject) (sendmailMTAAliasGrouping=aliases) (|(sendmailMTACluster=${sendmailMTACluster}) (sendmailMTAHost=$j)) (sendmailMTAKey=%0)) -v sendmailMTAAliasValue, sendmailMTAAliasSearch:FILTER:sendmailMTAAliasObject, sendmailMTAAliasURL:URL:sendmailMTAAliasObject
See Section 23.1.2 [V8.13] for a description of this schema.
Note that sendmail
macros (such as
$j
just shown) are not expanded when the default
schema is first defined. Rather, they are expanded each time an LDAP
lookup is performed.
In the event you wish to use your own schema rather than the default,
you may do so by appending it to the ldap
: when
defining ALIAS_FILE
:
define(`ALIAS_FILE´, `ldap:-k (&objectClass=mg)(mail=%0) -v mmember´)
Here, we replaced the long, recursive default schema above with a much shorter and nonrecursive schema of our own design.
See cf/README
in the
sendmail
source distribution for an additional
discussion of the default schema and how to use it.
As of V8.13, the default schema for class macro assignments using LDAP has been changed to include LDAP recursion support. Recall (22.1.3.2[3ed]) that you declare classes with LDAP, for example, like this:
RELAY_DOMAIN_FILE(`@LDAP´)
This causes the class $=R
(see
7.4.1.2[3ed]) to be filled with values
that match a sendmailMTAClassName
with the value
R
. More generally, for any class
X
, the following default schema will be used:
F{X}@ldap:-k (&(objectClass=sendmailMTAClass) (sendmailMTAClassName=X) (|(sendmailMTACluster=${sendmailMTACluster}) (sendmailMTAHost=$j))) -v sendmailMTAClassValue, sendmailMTAClassSearch:FILTER:sendmailMTAclass, sendmailMTAClassURL:URL:sendmailMTAClass
Note that sendmail
macros (such as
$j
shown earlier) are not expanded when the
default schema is first defined. Rather, they are expanded each time
an LDAP lookup is performed.
See 7.4.1.2[3ed] for a discussion of how
to define you own default schema when declaring a class. Also, see
cf/README
in the sendmail
source distribution for additional discussion of this default schema
and how to use it.
Recall that the ldap_routing
feature
(23.7.11.17[3ed]) is
used like this:
FEATURE(`ldap_routing´, `newldapmh
´, `
newldapmra
´,
` bounce´
, ` detail ´)
Prior to V8.13, the third argument
(bounce
) could only be one of two literal
words: bounce
or passthru
. If
the third argument was present and was neither an empty string nor
the literal string passthru
, failed lookups would
bounce.
Beginning with V8.13, a new literal word,
sendertoo
, may be used in place of either
bounce
or passthru
. When you
specify sendertoo
, you cause the envelope sender
to also be rejected if that address is not found in LDAP. Thus,
sendertoo
acts as if bounce
was
also specified (that is, both not-found recipients and senders will
be rejected).
Recall that the ldap_routing
feature
(23.7.11.17[3ed]) is
used like this:
FEATURE(`ldap_routing´, `newldapmh
´, `
newldapmra
´,
` bounce´
, `detail
´
)
Beginning with V8.13, two more arguments are now available for your use:
FEATURE(`ldap_routing´, `newldapmh
´,`
newldapmra
´,` bounce ´, `
detail
´,`
nodomain ´, ` tempfail ´)
The new fifth argument, nodomain
, is an
argument with no special word required (nodomain
,
no
, and UncleBob
, for example,
will all work). Without this new argument, a failed lookup of an
address ([email protected]) will cause the
@host.doman part of the address to also be looked up
in LDAP. Now, the presence of a nodomain
argument prevents that secondary lookup.
The new sixth argument, tempfail
, can be
one of two possible literal expressions: tempfail
or queue
. These tell sendmail
what do if sendmail
cannot connect to the LDAP
server, and what to do if the LDAP lookup fails because of a
temporary LDAP failure. If the sixth argument is missing or if it is
the queue
literal, the message will be queued for
a later attempt. If the sixth argument is the
tempfail
literal, the message will be temporarily
rejected with a 4yz reply code. We recommend you use
queue
rather than omitting the sixth argument
(relying on the default) to make your intent clear.
Beginning with V8.13 sendmail, a new
database-map type called
socket
is available for your use.[32] Declare an socket
database-map type
like this:
Kname
sockettype:port@host
Here, name
is the identifier that you will
later use in rule sets. The type:port@host
is declared in the same fashion as a Milter is declared, by using the
X
configuration command
(7.6.2[3ed]). For example:
Ktrustedip socket inet:[email protected]
Here, lookups can be made in rule sets using the database-map
trustedip
. The sendmail
program will make an IPv4 connection (the inet
) to
port 8020
on the host
db5.example.gov. Once the connection has been made,
lookups are performed using a simple dialogue that looks like this:
sendmail sends: database_map_name key sendmail receives: status datum
Note that neither what is sent nor received may end in a carriage-return/linefeed pair, or in a carriage-return only, or in a linefeed only. Also note that the two parts of each dialogue are separated by a single space character.
Both the sent request and the received reply begin and end with characters that denote their length and termination.[33] The length is an ASCII representation of the number of characters sent or received, stated as a prefix and a colon. The entire sent or received message is terminated by a comma. The length prefix does not include the comma. For example:
sendmail sends: 17:trustedip 1.2.3.4, sendmail receives: 14:OK VERYTRUSTED,
The sendmail program sends the database-map name
declared earlier using a K
configuration command.
In our example, this is the database-map named
trustedip
. That name is followed by a single space
and then the key to look up in the database. Again, the entire
request is prefixed with the length and a colon and terminated with a
comma (and excludes any terminating newline or carriage-return
characters).
The connected-to host replies with one of the keywords shown in Table 23-1. Each must be completely uppercase. The
keyword is followed by a single space, then information appropriate
to the keyword (for OK
, this is the sought datum).
The entire reply is prefixed with a length and
a colon and terminated with a
comma.
Table 23-1. The socket database-map reply keywords
Keyword |
Description |
---|---|
|
The key was found in the database, and the datum is the value sought. |
|
The key was not found in the database, and the datum is empty. |
|
A temporary failure occurred while performing the lookup. The datum may contain an explanatory message. |
|
The lookup timed out. The datum may contain an explanatory message. |
|
A permanent failure occurred while performing the lookup. The datum may contain an explanatory message. |
To illustrate, consider the need to look up the name of the central
mail server for your department. If such a database-map were called
mailservers
, you could use the following
configuration file line to look up your domain in that database-map:
Kmailservers socket -o inet:[email protected] ... R $* <@ $+ > $* $: $1<@$2>$3 <$(mailservers $2 $)> R $* <@ $+ > $* <$+> $#smtp $@ $4 $: $1 < @ $2 > $3 ...
Here, we look up the host part of an address ($2
)
in the mailservers
database on the host
db4.example.gov. The -o
makes the
existence of the database-map optional. If the host part is found, it
is rewritten to be the name of the mail server for that host. In the
last rule, we forward the original address to that server.
Only a few database switches are available with this socket database-map type. They are shown in Table 23-2.
Table 23-2. The socket database-map type K command switches
Switch |
sendmail text reference |
Description |
---|---|---|
|
23.3.2[3ed] |
Append tag on successful match |
|
23.3.3[3ed] |
Don’t use this database map if
|
|
23.3.4[3ed] |
Don’t fold keys to lowercase |
|
23.3.7[3ed] |
Suppress replacement on match |
|
23.3.8[3ed] |
Append a null byte to all keys |
|
23.3.9[3ed] |
Never add a null byte |
|
23.3.10[3ed] |
This database map is optional |
|
23.3.11[3ed] |
Don’t strip quotes from key |
|
23.3.12[3ed] |
Space replacement character |
|
23.3.13[3ed] |
Suffix to return on temporary failure |
|
23.3.14[3ed] |
Ignore temporary errors |
Note that the socket
database-map type is
available only if sendmail
is compiled with the
SOCKETMAP
compile-time macro (Section 3.1.1
[V8.13]) defined
when you build sendmail
(which is normally
not done by default).
For examples of how to use this new socket database-map type, see the
files contrib/socketmapServer.pl
and
contrib/socketmapClient.pl.
[30] These new ldap switches allow the use of ldapi and ldaps (if supported by the underlying LDAP libraries).
[31] Note, however, in order to use Unix domain sockets, your underlying LDAP library must support Unix-domain sockets.
[32] The sendmail program needs to be built with SOCKETMAP defined (Section 3.1.1 [V8.13]) in order to use this new database-map type. NETUNIX is required to use Unix-domain sockets but is generally defined by default.
[33] The protocol for socketmap
uses the
“netstring” format invented by D.J.
Bernstein. This format is described at http://cr.yp.to/proto/netstrings.txt.
3.135.216.11