7.5 The access Database
The access
database was introduced in V8.9 sendmail, and
improved upon in V8.10. It provides a single, central database with
rules to accept, reject, and discard messages based on the sender
name, address, or IP number. It is enabled with the
access_db configuration feature.
For example, consider an access database with
the following contents:
From:postmaster@spam.com OK
From:spam.com REJECT
Here, mail from postmaster at the site
spam.com is accepted, while mail from any other
sender at that site is rejected.
Note that this example uses V8.10 syntax. Next we will describe the
access database using the old V8.9 syntax, then
describe the V8.10 and V8.12 updates.
7.5.1 Enabling the access Database Generally
To enable use of this
access
database, declare it in your mc configuration
file like this:
FEATURE(`access_db')
This enables use of the access database, and enables the default
database type and path as:
hash /etc/mail/access V8.11 and earlier
hash -T<TMPF> /etc/mail/access V8.12 and above
Note that with V8.12 and above a -T<TMPF>
has been added to specify that temporary errors should return a 4xy
SMTP code.
If you wish to use a different database type or pathname, you can do
so by providing an appropriate argument to the
access_db feature:
FEATURE(`access_db', `hash -o /etc/mail/access') V8.11 and earlier
FEATURE(`access_db', `hash -o -T<TMPF> /etc/mail/access') V8.12 and above
Here, we add the -o switch (-o) to the definition to make the existence of
the /etc/mail/access database file optional.
Beginning with V8.12, this feature takes two more arguments:
FEATURE(`access_db', `db specification', `skip', `lookupdotdomain')
The skip (the third argument), if present, enables
SKIP as a possible return value for the access
database (Section 7.5.2.5).
The lookupdotdomain (the fourth argument), if
present, enables the same behavior as if you independently declared
the lookupdotdomain feature (FEATURE(lookupdotdomain)).
7.5.2 Create the access Database
To create the access database, you first create
a text file that contains lines of hosts, addresses, and IP numbers
paired with keywords and values. After that you run
makemap to create the actual database from the
text file. If the text file is named
/etc/mail/access, you would build the database
like this:
# cd /etc/mail
# makemap hash access < access
The text file itself looks like this:
key value
whitespace: one or more tabs or spaces
The text file is composed of two columns of information. The lefthand
column is the key which is composed of a prefix and an address
expression. The prefix depends on the rule set doing the lookup. For
some it is Connect: or From:,
while for others it is TLS_Srv: or
TLS_Clt:. These are described in the sections of
this book dealing with the appropriate rule set.
The address expression can be any of the following depending on what
the rule set is trying to do:
host.your.domain a hostname
your.domain a domain name
user@ a username
user@host.another.domain a user address
123.45.67.89 an IPv4 host address
123.45 an IPv4 network (leftmost numbers)
IPv6:2002:c0a8:51d2::23f4 an IPv6 host address
IPv6:2002:c0a8:02c7 an IPv6 network (leftmost numbers)
Note that for usernames the @ is mandatory. More
address expressions can be used than we show here. These are the most
common. Others are described under the rule sets that use them.
The righthand column contains the value, which can be keywords or
values that determine what should be done with the item described on
the left. They are shown in Table 7-3, and
described in the sections indicated.
7.5.2.1 OK
The OK righthand value for the
access database tells
sendmail to accept the user, host, domain, or
address on the lefthand side. That is, even if other rules in the
rule set that did the lookup reject it (because the domain cannot be
looked up with DNS, for example), this return value will still cause
it to be accepted by that rule set. Note, however, that other rule
sets can subsequently reject it.
7.5.2.2 RELAY
The RELAY access
database righthand value tells sendmail to allow
the user (if the relay_mail_from feature is
defined), host, domain, or address listed on the lefthand side to
relay mail through this machine. It also allows mail to be relayed by
anyone when routing is to the host, domain, or IP numbers listed.
Note that RELAY also includes the behavior of OK.
7.5.2.3 REJECT
The REJECT access
database righthand value tells sendmail to
reject the user, host, domain, or address listed on the lefthand
side. The rejection will use the default message defined by the
confREJECT_MSG mc macro
(Section 7.5.4).
7.5.2.4 DISCARD
The DISCARD access
database righthand value tells sendmail to
accept any sender that is listed on the lefthand side (either as a
user, host, or IP number), but to silently discard the message using
the discard delivery agent (discard). The DISCARD keyword can also be used for
recipients if the blacklist_recipients feature
(Section 7.5.5) is declared. When a recipient is
discarded and when there are other recipients in the envelope, all
recipients are discarded. The one exception is if DISCARD is returned
to the check_compat rule set, established by the
compat_check mc feature
(Section 7.5.7), then only the one recipient is
discarded.
7.5.2.5 SKIP
This keyword provides a way to list hosts,
domains, or addresses that can give a default behavior. Such defaults
are defined by your selection of features to enable. Sometimes, for
example, you might desire to have the lookup of a host, domain, or
address return (if found) but have no further checks performed on it.
One way to do that is by using this special SKIP keyword as the
return value for the lookup:
From:bob.domain SKIP
If the lookup was done to see if relaying is OK for the domain
bob.domain, this SKIP instructs
sendmail to act as though the lookup did not
find bob.com. Thus, if the default is to deny
relaying, relaying for bob.com will be denied.
If the default is to allow relaying, relaying for
bob.com will be allowed.
The main use for SKIP is with the lookupdotdomain
feature (FEATURE(lookupdotdomain)). With that feature defined,
you could set up the access database like this:
From:server.bob.com SKIP
From:.bob.com RELAY
Here, mail from the machine server.bob.com will
be handled by the default rules. All other hosts in the
bob.com domain will be allowed to relay.
7.5.2.6 XYZ text
The SMTP protocol, as documented in
RFC2821, defines a set of three-digit codes that have special meaning
to the sending site. When sendmail rejects the
envelope sender, it does so by printing a 550 code in reply to the
MAIL FROM: command. This special form of keyword in your
access database allows you to cause
sendmail to print a code, followed by words of
your choice. Consider this entry in the access
database:
From:sales@spam.com ERROR:554 Spam delivery is unavailable.
Here we chose 554, which stands for "service
unavailable." When mail is received at your site,
this rule will cause the following interaction in the SMTP
conversation:
MAIL FROM:<sales@spam.com>
554 5.0.0 <sales@spam.com>... Spam delivery is unavailable.
The text you give following the SMTP might or might not appear in the
bounced mail that sales receives.
The XYZ code you specify does not have to be a 500 code (meaning
failure). You are also free to use 400 codes (to defer the mail) too.
Deferral might be appropriate as a means to handle a temporary
resource limitation:
newsupdates@your.domain 421 Our database is down for two days for repair
7.5.2.7 ERROR:XYZ text
This righthand value is the same as the
"XYX
text" expression discussed
earlier, but the ERROR: signals that the envelope-sender should be
rejected. The XYZ is optional, and sendmail will
supply a value if it is missing. This provides a handy way to reject
mail without having to remember the correct SMTP numbers:
sales@cybermarketing.com ERROR: Stop spamming us
When this address arrives from the outside, the SMTP will look like
this:
MAIL FROM:<sales@cybermarketing.com>
553 5.3.0 <sales@cybermarketing.com>... Stop spamming us
7.5.2.8 ERROR:D.S.N:XYZ text
This righthand value is the same as
ERROR:XYZ text, but it allows you finer control of the SMTP rejection
message. The D.S.N can be any of the DSN
codes defined in RFC1893. You should use this form if you change the
SMTP code from the default used by sendmail:
newsupdates@your.domain 450 Cache mailbox disk is full
Here, for example, you reject mail to
newsupdates at your site because the database is
down so you cannot drain the cache file. By changing the SMTP error
from its default, you will cause sendmail to
wrongly report the DNS error:
RCPT TO:<newsupdates@your.domain>
450 4.0.0 Cache mailbox disk is full
The 4.0.0 is not the correct DSN code for a full
mailbox. Instead, you should specify 4.2.2, like
this:
newsupdates@your.domain ERROR:4.2.2:450 Cache mailbox disk is full
This form uses three colon-delimited fields on the righthand side of
the access database. The first field is the
literal ERROR string. That is followed by your specification for the
correct DSN code. The third field is the SMTP error text as we
described earlier.
7.5.3 Finer Control with V8.10
Prior to V8.10, the lefthand side of the
access database could only contain a user,
host, domain, or address, and would only look them up based on the
client name or address, the MAIL FROM:. address, or the RCPT TO:
address.
Beginning with V8.10, sendmail offers much finer
control of addresses and rejections in the
access database. The lefthand side of the
access database can begin with one of three
possible prefixes:
- Connect:
-
The address is either the IP number or hostname of a connecting host.
- From:
-
The address is that of an envelope-sender.
- To:
-
The address is that of an envelope-recipient.
When an address is looked up in the access
database, it is first looked up with the prefix. If it is not found,
it is looked up again without a prefix, meaning that the old
access databases will still work with newer
versions of sendmail. To illustrate, consider
this update to the access database shown in the
previous section:
From:spamuser@hotmail.com REJECT
From:cybermarkets.com REJECT
Connect:example.org REJECT
Connect:192.168.212 REJECT
This access database will cause mail from
spamuser@hotmail.com to be rejected. Mail from
any user at cybermarkets.com will be rejected,
connections from the host example.org will be
rejected, and any mail from any host with an IP number ranging from
192.168.212.0 through 192.168.212.255 will have the initial
connection rejected. In that last example, any missing righthand part
of an IP address is assumed to be a wildcard for matching purposes.
This behavior is exactly the same as the example without prefixes,
with one exception. The example.org line,
without a prefix, will reject mail from all users at
example.org as well as connections from
example.org.
A more complex example will better illustrate the properties of the
three prefixes:
To:friend.domain RELAY
From:friend.domain RELAY
Connect:friend.domain OK
Connect:bad.domain REJECT
Here, we reject or allow based only on the envelope-recipient or the
connecting host.
The first line says that mail arriving at your site, regardless of
its origin, will be allowed to be relayed to any user at the site
friend.domain. This provides a way to allow
relaying on a host-by-host basis, even if you have all relaying
turned off with the various antirelay features (Section 7.4). This is useful if you are a secondary MX
site for friend.domain.
The second line says that we will also relay mail from the site
friend.domain. A line such as this requires that
you have declared the relay_mail_from feature
(Section 7.4.8) with a literal
domain second argument. Here, if the envelope
sender is any user at friend.domain, the
envelope recipient can be a local or remote address.
The third line says that we will specifically accept connections from
the host friend.domain. We do this because that
site might be rejected if it is listed on some DNSBL site (Section 7.2). An OK via a Connect
prefix overrides any rejection based on DNSBL lists.
The fourth line rejects connections from the host
bad.domain no matter what. This is one way to
reject connections on a site-by-site basis, if, for example, you want
to block messages from a site that is pushy but not eligible for
listing with a DNSBL server.
Even if you lack an immediate use for these prefixes you should
consider using them, just to experience their power.
7.5.4 Rejection Message for REJECT
When an address is rejected because of the
presence of REJECT in the access database, it is
rejected with the default message:
550 5.7.1 Access denied
Beginning with V8.9 sendmail, you can change
that message (to augment it or to clarify the reason for the
rejection) using the confREJECT_MSG
mc file macro. For example, to show why the
message was rejected, you could place the following in your
mc file:
define(`confREJECT_MSG', `550 Access denied. See http://www.your.domain/access_
denied')
Because the message you specify will be quoted in the configuration
file, you cannot place any m4 macros or
positional m4 macros in the message. They will
be silently stripped from the message.
7.5.5 Reject Per Recipient
The access_db feature
(Section 7.5) provides a way to selectively reject
envelope-sender addresses. By declaring this
blacklist_recipients feature, you enable the
access database to also selectively reject
envelope-recipient addresses:
FEATURE(`blacklist_recipients')
Consider the need to prevent outsiders from posting to strictly
inside mailing lists. In this example, the mailing lists are handled
on a machine different from that on which outside mail is received.
On the receiving machine, you would put lines such as these in your
access database:
board@our.domain 550 Outside access to private mailing list banned
accounting@our.domain 550 Outside access to private mailing list banned
401k-help@our.domain 550 Outside access to private mailing list banned
By declaring this blacklist_recipients feature,
these addresses will be prevented from receiving outside mail.
All forms of addresses in the access database
can be used for this recipient rejection. Consider:
To:badguy@ ERROR:550 Mailbox disabled for this user
To:host.our.domain ERROR:550 This machine bans email
To:123.45.67.89 ERROR:550 Printers cannot receive email
Be careful when rejecting recipients based on the username alone, as
in the first line in this example, because the username is rejected
for both the envelope-sender and the envelope-recipient. Thus, this
line will reject mail to both badguy locally, and
from badguy at all other sites in the world.
7.5.6 Accept and Reject Per Recipient
When a connection is made to your site by another, the
access database is checked to reject unwanted
connections. It is
checked again when the SMTP MAIL FROM: command is given to accept or
reject the envelope sender. It is checked a third time when the SMTP
RCPT TO: command is given to accept or reject the envelope recipient,
and prevent unwanted relaying.
This order is good for most sites, but might not be the best for your
particular needs. In case it isn't, the
delay_checks feature offers a way to check the
SMTP RCPT TO: address first, before the other two checks, and then
proceed with those other two checks, if appropriate. Delayed checks
are enabled with the delay_checks feature, which
you declare in your mc file like this:
FEATURE(access_db)
FEATURE(delay_checks)
Note that the access_db feature needs to be
enabled before you enable the delay_checks
feature.
Once enabled, the order of checks is changed. If the righthand side
in the access database is either REJECT or an
SMTP error for the envelope-recipient, the envelope-recipient is
rejected as usual. But if the envelope-recipient is allowed, the
envelope-sender is then checked, and if it is rejected, the
envelope-recipient is rejected with the
envelope-sender's error message. If the
envelope-sender is allowed, the connecting host is checked, and if it
is rejected, the envelope-recipient is rejected with the connecting
host's error message.
For example, consider the following abstract from an
access database:
To:postmaster@ OK
From:larry@ REJECT
Connect:spammer.domain REJECT
With the delay_checks feature enabled, the first
check will come as part of the SMTP RCPT TO: command, and that
address will be looked up in the access
database. In this example, if the user part of the recipient address
is postmaster, the message will be
accepted by the current calling
rule set. Subsequent rule sets can still reject it.
If the user part of the envelope-sender address is not
postmaster, the address given to the earlier
SMTP MAIL FROM: command will be looked up. If that envelope-sender
address has a user part that is larry (in our
example) the message will be rejected, but because it is too late to
reject the SMTP MAIL FROM:, the rejection will be given to the SMTP
RCPT TO: command.
If the envelope-sender is OK, the name of the connecting host will be
looked up. If the host is found in the access
database, and if the righthand side is REJECT, the message is
rejected and the error will be reported in reply to the SMTP RCPT TO:
command. If the host is found in the access
database, and if the righthand side is RELAY, the message is allowed
to be relayed. If the host is not found, and if no other relaying is
allowed, the message will not be allowed to be relayed and the denial
of relay error, if any, will be reported in reply to the SMTP RCPT
TO: command.
One reason to check the SMTP RCPT TO: address first might be to allow
mail from a spam site to be delivered to a specific local user, but
still block mail from that site for all other users. Another reason
might be to block mail from a spam site for a specific user, but
allow it to be delivered to all others. You can tune the
access database to do one (but only one) of
these two things by defining the delay_checks
feature with an extra argument that must be one, and only one, of two
possible lowercase words:
FEATURE(access_db)
FEATURE(`delay_checks', `friend') this one or
FEATURE(`delay_checks', `hater') this one, but not both
When the extra argument is friend, you can allow
mail from a spam site to a specific local user, while still blocking
mail from that site for all other users. When the extra argument is
hater, you can block mail from a spam site for a
specific user, while allowing it to be delivered to all other users.
If the extra argument is neither (or was uppercase), the following
error will be printed when you build your configuration file, and
that file will be incomplete:
*** ERROR: illegal argument bad word here for FEATURE(delay_checks)
The check_rcpt (Section 7.1.3) rule
set performs the lookup, and the relationship found
(friend or hater) determines
whether the check_mail (Section 7.1.2) and check_relay (Section 7.1.1) rule sets should be called to perform further
checks.
If the extra argument is friend and if the
database lookup returns FRIEND, those further rule set checks will be
skipped and the message will be accepted. But if the database lookup
fails to find the address, or returns something other than FRIEND,
further screening by the check_mail and
check_relay rule sets is performed.
If the extra argument is hater and the database
lookup returns HATER, further screening by the
check_mail and check_relay rule
sets is performed. But if the database lookup fails to find the
address, or returns something other than HATER, those additional rule
sets will be skipped.
As a first step, decide which of the two forms you prefer (remember,
you can only do one or the other), then add the new definition to
your mc file, generate a new configuration file,
and install it. Once the new configuration is ready, you can use one
of two new righthand side keywords in your
access database:
- SPAMFRIEND (V8.10-V8.11) or FRIEND (V8.12)
-
This address is allowed to receive messages that would otherwise be
rejected by the check_mail and
check_relay rule sets. You can use this keyword
only if you defined friend when you declared the
delay_checks feature.
- SPAMHATER (V8.10-V8.11) or HATER (V8.12)
-
This address will only receive messages that are also accepted by the
check_mail and check_relay rule
sets. An address not listed as SPAMHATER (V8.10 and V8.11) or HATER
(V8.12) will have processing by those additional rule sets skipped.
You can use this keyword only if you defined hater
when you declared the delay_checks feature.
To illustrate, consider the following abstract from such an
access database where we declared the
delay_checks feature as friend:
Connect:spam-mail.com REJECT
To:abuse@your.domain SPAMFRIEND V8.10 through V8.11
Spam:abuse@your.domain FRIEND V8.12
The site spam-mail.com is one of possibly many
sites that will be rejected by our site because they are known
spammers. Mail addressed to abuse@your.domain
will be accepted even if it is from any of the rejected spam sites.
In the following example we declared the
delay_checks feature as hater:
Connect:spam-mail.com REJECT
To:payroll@your.domain SPAMHATER V8.10 through V8.11
Spam:payroll@your.domain HATER V8.12
To:abuse@your.domain OK
Here, the site spam-mail.com is one of possibly
many sites that will be rejected by our site because they are known
spammers. Mail to payroll@your.domain will have
spam sites rejected. Mail to abuse@your.domain
will still be allowed to receive mail from otherwise rejected sites.
Whether you choose the spam haters or spam friends approach is
entirely dependent on your site's unique needs.
Think through the logic of your choice before setting up your
access database. If you make a mistake, you
might inadvertently allow spam to a user who doesn't
want it.
Note that you cannot mix friends and haters. If you do,
sendmail will ignore the mismatch. For example,
if you declare the delay_checks feature as
friend and place the following entry into your
access database, that entry will be ignored:
Spam:payroll@your.domain HATER ignored because delay_checks specified friend
Remember, you must choose one, and only one: either
friend or hater. You cannot
choose both, nor can you mix the two.
Note that the syntax of this delay_checks feature
has changed. It differs between V8.10 through V8.11 and V8.12. If you
have already used this feature with V8.10 or V8.11
sendmail, you will need to change it for V8.12.
You will need to add the Spam: prefix and new
righthand side values to your access database.
As an aid to conversion, the old syntax will be ignored. Once you
have finished converting from the earlier syntax to the new, you can
redeclare this V8.12 delay_checks by adding a
literal n as a third argument:
FEATURE(`delay_checks', `friend', `n') V8.12 and above
FEATURE(`delay_checks', `hater', `n') V8.12 and above
This n turns off backward compatibility (the
ability to ignore the old syntax) and causes the old syntax to
produce an error. The is a good way to check to be sure your
conversion was good.
Also note that, with V8.12, if an envelope-recipient is found to be
trusted, using one of the mechanisms listed with the
AuthMechanisms option (AuthMechanisms), that envelope-recipient is accepted and
further access database checks are
skipped.
7.5.7 FEATURE(check_compat)—V8.12 and Above
Beginning with V8.12
sendmail, you can create a rule set that makes
decisions about envelope-sender and envelope-recipient pairs with
entries in the access database. To enable these
checks, just add the check_compat feature to your
mc configuration file:
FEATURE(access_db) must be first
FEATURE(check_compat)
Once this is enabled, you can then add entries such as the following
to your access database (note that the
<@ > is literal):
Compat:sender<@>recipient keyword
Here, the Compat: prefix is literal and must be
present. It is immediately followed (with no intervening spaces) by
the envelope-sender address, a literal <@>,
and the envelope-recipient address (where the envelope-recipient
address has already undergone aliasing and processing by a
user's ~/.forward file).
Neither address should be surrounded with angle braces. The address
pair is followed by whitespace (spaces and tabs) and then a keyword.
There are three possible keywords:
- DISCARD
-
Mail from this sender to this recipient is accepted, then discarded
and logged. DISCARD can be followed by a colon. It can also be
followed by optional text that will be logged as the reason for the
discard.
- TEMP:
-
Mail from this sender to this recipient is rejected with a temporary
error (causing the message to be deferred for a later delivery
attempt). This keyword must be followed by a valid 4xy SMTP code and
text that describes the reason for the temporary failure.
- ERROR:
-
Mail from this sender to this recipient is rejected with a permanent
error (causing the message to bounce). This keyword must be followed
by a valid 5xy SMTP code and text that describes the reason for the
rejection.
To illustrate, consider the following example of such entries in an
access database:
Compat:bin@your.site<@>admin@your.site DISCARD
Compat:ads@spam.site<@>taka@your.site DISCARD
Compat:db@your.site<@>lp@your.site TEMP:421 printer is down for repair
Compat:bob@your.site<@>betty@your.site ERROR:553 Interoffice banter banned
Compat:betty@your.site<@>bob@your.site ERROR:553 Interoffice banter banned
The first line might be used at a site where the pseudo-user
bin generates a great deal of automated email
and that email is sent to admin, among others.
This line causes that automated mail to be accepted and discarded.
The second line might be used to prevent mail from a known spam list
from being sent to the user taka at your site.
This line causes that spam mail to be accepted and discarded.
The third line might be used to defer mail to a printer from the
database. The TEMP will cause the message to be deferred for a later
try. You could then remove this line after the printer is repaired
and back in service.
The last two lines show a way to prevent two users at your site from
sending email to each other. The idea is that it is OK for them to
send email to each other at other sites, but not this one. Each such
prohibited message is rejected and bounced. For this scheme to work,
however, you will need to place an empty
root-owned ~/.forward file
in each of the two users' home directories to
prevent them from bypassing this restriction by setting up their own
~/.forward files.
This last example underscores a weakness in this
compat_check feature. Because each
envelope-recipient undergoes aliases
translation, and ~/.forward translation before
the lookup, the entry in the access database
must correctly represent the translated address. For example,
consider a pseudo-user named nill who has an
aliases file entry such as this:
# deep six mail to nill
nill: /dev/null
Here, the intention is to have all mail to nill
delivered to the /dev/null file. If you wanted
selected mail to nill to be rejected, do not do
this:
Compat:user@other.domain<@>nill@your.site ERROR:553 Don't mail to nill
note
The nill@your.site will never be found because
by the time this lookup happens nill has been
transformed into /dev/null. The correct way to
set up your access database to handle this
situation would look like this:
Compat:user@other.domain<@>/dev/null ERROR:553 Don't mail to nill
note
Also note that when the recipient is an actual user (as, for example,
bob):
Compat:user@other.domain<@>bob@your.site ERROR:553 Don't mail to nill
bob can alter his
~/.forward file at any time, thus rendering his
recipient entry useless.
7.5.8 Screen by domain and .domain Too
Normally, lookups of hosts in the
access database are literal. That is,
host.domain is looked up first as
host.domain and then as
domain. If you declare the
lookupdotdomain feature (FEATURE(lookupdotdomain)), or add a literal
lookupdotdomain fourth argument (Section 7.5.1) to the access_db
feature's declaration, you cause the sequence to
become host.domain, then
.domain, and lastly domain.
This feature allows you to structure an access
database to handle the domain differently than it handles hosts in
the domain:
From:.domain REJECT
From:domain OK
Here, envelope-senders with a host part of
@anything.domain will be rejected, but those
with a host part of @domain will be accepted. To
illustrate, consider the following attempt to accept mail only from
cs.Berkeley.EDU and to reject mail from hosts in
that subdomain:
From:.cs.Berkeley.EDU REJECT
From:cs.Berkeley.EDU OK
7.5.9 Choose Queue Groups Via the access Database
Beginning with V8.12, it is possible to select
queue groups using the
access database by declaring the
queuegroup feature. Queue groups and the
queuegroup feature are discussed in detail in
Section 11.4.
7.5.10 Screen Based on STARTTLS and AUTH=
Beginning with V8.12, it is possible to accept, reject, and allow
relaying based on the STARTTLS and AUTH= SMTP extensions. These
abilities, and the features that support them, are detailed in Section 10.10.8.
|