Ideas about check_* in sendmail 8.9

Last Update 2000-06-24

sendmail 8.10 is available so some of the proposals below have actually been implemented.

Introduction

sendmail 8.9 introduced standard FEATUREs for the new rulesets to check who can use your machine to send/relay e-mail and to avoid UBE from well known sites.

However, some of you are not satisfied with the available "grain" of control. sendmail 8.9 use a single access map to control nearly all anti-UBE features. This causes several problems, which are explained below.

Relaying

There are at least two ways to deal with relaying in 8.9: class R and the access map. An member of class R or an entry in access with RHS "RELAY" allows relaying in both directions (in and out). Moreover, the access map is used for many purposes: overriding rejections by other rules in the same check_* ruleset (RBL, unresolvable domains, etc), rejection and discarding of mail. Those who followed the development of 8.9.0 Beta noticed a change of the possible RHSs: RELAY has been introduced in addition to OK to allow for finer control (OK: accept, RELAY: accept and relay).

So what do you need/want? Frank Cusack already wrote a patch which introduced RELAYTO and RELAYFROM (with the obvious meaning) for finer control. With this patch, a hierarchy of values is introduced:

RELAY                 implies
RELAYTO  RELAYFROM    imply
OK

Rejections

Rejections have as RHS:
REJECT
DISCARD
XYZ some error text

Note: the feature blacklist_recipients will not only prevent local recipients from receiving mail:

badlocaluser		550 Mailbox disabled for this username
host.mydomain.com	550 That host does not accept mail
user@otherhost.mydomain.com	550 Mailbox disabled for this recipient
but it will also keep you from sending mails to all addresses/domains that have an error message or REJECT as RHS. For example, if you blocked mail from these addresses:
spammer@aol.com		REJECT
cyberspammer.com	REJECT
then mail can't be sent to spammer@aol.com or anyone at cyberspammer.com.

Even worse, if you block mail to a local user with the (unusual?) name com, then you can't communicate via e-mail with any domain that ends in .com. This problem occurs since usernames for feature blacklist_recipients are not tagged with a @ is it is done for check_mail.

Overriding

The access map can have domain names, e-mail addresses, local parts of e-mail addresses, and IP addresses (complete or subnets), as LHS. The lookup of data in the check_* rulesets is usually done against the most specific entry first. So it is possible to override rejections of full domains with acceptance of e-mail addresses. For example, it seems to be possible to reject all mail from SOME.DOMAIN but accept mail from FRIEND@SOME.DOMAIN by using:

FRIEND@SOME.DOMAIN	OK
SOME.DOMAIN		REJECT
However, the access map is also used in check_relay ruleset. So if e-mail with an address like user@SOME.DOMAIN comes from a site with the hostname SOME.DOMAIN (or HOST.SOME.DOMAIN), it will be rejected by check_relay .

Questions

What do you think? Is a hierarchy of "permissions" sufficient? Or should there be different values for different purposes? (my HACKs used different maps for different purposes, but this has "historical" reasons :-).

Where is the access map used?

  1. check_relay
    1. rejection: REJECT, DISCARD, XYZ some error text,
    2. or override the RBL (there's a bug in 8.9.{0,1} (patch for cf/m4/proto.m4)): OK, RELAY.

    check_relay may reject mail from a host while check_mail would allow it: OK for user, REJECT for host so we need something like:

    REJECTRELAY
    REJECTMAIL
    
    (and we have a problem with Custom-Error-Messages...)
  2. check_mail
    1. rejection: REJECT, XYZ some error text
    2. override the various checks (unqual. address, unresolvable domain): OK, RELAY,
  3. check_rcpt
    1. blacklist_recipients reject mail to an address (REJECT, error message)
    2. relay to an e-mail address: RELAY
    3. relay from a host address (FQHN, IP number): RELAY
RELAY_LOCAL_FROM currently only works for local domains (class w), no check in the access map is done. This can be added by Local_check_rcpt for POP authentification.

Possible Solutions?

Different RHS

We could use different RHS for these cases, e.g.,
RBL_OK		override RBL
MAIL_OK
UNQUAL_OK
UNRESOLV_OK
MAIL_REJECT
MAIL_DISCARD
RCPT_OK
RCPT_REJECT
RCPT_DISCARD
RELAY_FROM
RELAY_TO

Do you think this is necessary/useful?

The idea is to have "multiple" RHSs, and check for the occurence of the required keyword, e.g.,

R<$* OKUNQUAL $*>	$@ OK
However, I haven't started yet to write rules, so I'm not sure whether it will really work. BTW: there is a small gotcha: the keywords must be "unique", i.e., they should not appear in a user written error message. This could be achieved by using delimiters, e.g.,
134.245		:OKRBL:RelayFrom:
dialup.some.domain	:RejectRelay::;550 no direct access for dialups.
which at least minimizes the problem of getting a wrong match.

However, there is still a problem with this: if we do a lookup of an entry, we may get something in return we aren't interested in. So the rules become more complicated since they have to filter relevant results, and for those values that are not relevant in the particular context, lookups of other data must continue. Example:

user@domain		:ToReject:
@domain			:FromOK:
If check_mail looks up the sender address user@domain it will get a match on the first entry which, however, isn't relevant here, because it is intended for check_rcpt (blacklist_recipients). So the rules have to recognize this and continue lookups to find the second entry.

Another problem is the identification of error messages. Since we can have a list of possible values as RHS and only some of them are relevant in the particular rulesets, we need to make sure that the others are not interpreted as user-defined error messages as it is currently the default.

Tag the LHS

Another idea is to tag the LHS (which would be optional, the default is the current behavior to be compatible):
Connect:1.2.3			REJECT
Connect:1.2.3.4			OK
Connect:relay.domain	RELAY
To:another.domain		RELAY
From:1.2.4				OK
From:some.domain		REJECT
From:friend@some.domain	OK
To:olduser@				REJECT
This will give high flexibility. Even though the table might be hard to read, it should be easy to generate it from simpler descriptions (different files). This should only be optional, the default behavior (and map content) should be the one which is currently supported (except for maybe some slight enhancements). Since we tag the LHS, we can have `multiple' entries, because they are distinguished by the tags. A drawback might be that it is possible to create `inconsistent' maps, that is, allow relaying by one entry, but reject mail by another. However, just as Unix isn't supposed to stop you from doing stupid things (because it would stop you doing clever things), why should sendmail? Another drawback might be a larger map, as can be seen from the example.

The tags used are

Connect:
for connection information, i.e., ${client_name} and ${client_addr}.
From: for envelope sender
To: for envelope recipient
The entries above will allow connections from the IP number 1.2.3.4 and reject everything else in the net 1.2.3. It allows relaying from relay.domain and to another.domain.

Order of calls

As explained the new rulesets for SMTP connections are called in the order: check_relay (host name and host address when a client connects), check_mail for the MAIL command, and check_rcpt for the RCPT command. Hence it is per default not possible to override rejections in check_relay by the sender address, or rejections in check_mail for individual recipients. There are some HACKs available which provide the opportunity to change the order by modifying some rulesets. This allows you to:
  1. accept mail from specific (envelope) senders, even though the server rejects connections from some clients,
  2. accept mail for specific recipients, e.g., postmaster, even though the mail would be rejected by other means.
The HACKs for 8.8 have also appropriate options: _CHECK_MAIL_IN_RCPT_ and _CHECK_RELAY_IN_RCPT_. This enables the exemption from senders or recipients from rejecting mail from/for them.

Should such a feature also be included in a future sendmail release?


[(links)] [Hints] [Avoiding UBE] [cf/README] [New]
Copyright © Claus Aßmann Please send comments to: <ca at sendmail.org>
Disclaimer: the information provided may be inaccurate or outdated or incomplete. Please contact me if you find an error.