40. Access control lists

Access Control Lists (ACLs) are defined in a separate section of the run time configuration file, headed by “begin acl”. Each ACL definition starts with a name, terminated by a colon. Here is a complete ACL section that contains just one very small ACL:

begin acl
small_acl:
  accept   hosts = one.host.only

You can have as many lists as you like in the ACL section, and the order in which they appear does not matter. The lists are self-terminating.

The majority of ACLs are used to control Exim’s behaviour when it receives certain SMTP commands. This applies both to incoming TCP/IP connections, and when a local process submits a message using SMTP by specifying the -bs option. The most common use is for controlling which recipients are accepted in incoming messages. In addition, you can define an ACL that is used to check local non-SMTP messages. The default configuration file contains an example of a realistic ACL for checking RCPT commands. This is discussed in chapter 7.

The -bh command line option provides a way of testing your ACL configuration locally by running a fake SMTP session with which you interact. The host relay-test.mail-abuse.org provides a service for checking your relaying configuration (see section 40.49 for more details).

In order to cause an ACL to be used, you have to name it in one of the relevant options in the main part of the configuration. These options are:

    acl_not_smtpACL for non-SMTP messages
    acl_not_smtp_mimeACL for non-SMTP MIME parts
    acl_not_smtp_startACL at start of non-SMTP message
    acl_smtp_authACL for AUTH
    acl_smtp_connectACL for start of SMTP connection
    acl_smtp_dataACL after DATA is complete
    acl_smtp_etrnACL for ETRN
    acl_smtp_expnACL for EXPN
    acl_smtp_heloACL for HELO or EHLO
    acl_smtp_mailACL for MAIL
    acl_smtp_mailauthACL for the AUTH parameter of MAIL
    acl_smtp_mimeACL for content-scanning MIME parts
    acl_smtp_notquitACL for non-QUIT terminations
    acl_smtp_predataACL at start of DATA command
    acl_smtp_quitACL for QUIT
    acl_smtp_rcptACL for RCPT
    acl_smtp_starttlsACL for STARTTLS
    acl_smtp_vrfyACL for VRFY

For example, if you set

acl_smtp_rcpt = small_acl

the little ACL defined above is used whenever Exim receives a RCPT command in an SMTP dialogue. The majority of policy tests on incoming messages can be done when RCPT commands arrive. A rejection of RCPT should cause the sending MTA to give up on the recipient address contained in the RCPT command, whereas rejection at other times may cause the client MTA to keep on trying to deliver the message. It is therefore recommended that you do as much testing as possible at RCPT time.

The non-SMTP ACLs apply to all non-interactive incoming messages, that is, they apply to batched SMTP as well as to non-SMTP messages. (Batched SMTP is not really SMTP.) Many of the ACL conditions (for example, host tests, and tests on the state of the SMTP connection such as encryption and authentication) are not relevant and are forbidden in these ACLs. However, the sender and recipients are known, so the senders and sender_domains conditions and the $sender_address and $recipients variables can be used. Variables such as $authenticated_sender are also available. You can specify added header lines in any of these ACLs.

The acl_not_smtp_start ACL is run right at the start of receiving a non-SMTP message, before any of the message has been read. (This is the analogue of the acl_smtp_predata ACL for SMTP input.) In the case of batched SMTP input, it runs after the DATA command has been reached. The result of this ACL is ignored; it cannot be used to reject a message. If you really need to, you could set a value in an ACL variable here and reject based on that in the acl_not_smtp ACL. However, this ACL can be used to set controls, and in particular, it can be used to set

control = suppress_local_fixups

This cannot be used in the other non-SMTP ACLs because by the time they are run, it is too late.

The acl_not_smtp_mime ACL is available only when Exim is compiled with the content-scanning extension. For details, see chapter 41.

The acl_not_smtp ACL is run just before the local_scan() function. Any kind of rejection is treated as permanent, because there is no way of sending a temporary error for these kinds of message.

The ACL test specified by acl_smtp_connect happens at the start of an SMTP session, after the test specified by host_reject_connection (which is now an anomaly) and any TCP Wrappers testing (if configured). If the connection is accepted by an accept verb that has a message modifier, the contents of the message override the banner message that is otherwise specified by the smtp_banner option.

The ACL test specified by acl_smtp_helo happens when the client issues an EHLO or HELO command, after the tests specified by helo_accept_junk_hosts, helo_allow_chars, helo_verify_hosts, and helo_try_verify_hosts. Note that a client may issue more than one EHLO or HELO command in an SMTP session, and indeed is required to issue a new EHLO or HELO after successfully setting up encryption following a STARTTLS command.

If the command is accepted by an accept verb that has a message modifier, the message may not contain more than one line (it will be truncated at the first newline and a panic logged if it does). Such a message cannot affect the EHLO options that are listed on the second and subsequent lines of an EHLO response.

Two ACLs are associated with the DATA command, because it is two-stage command, with two responses being sent to the client. When the DATA command is received, the ACL defined by acl_smtp_predata is obeyed. This gives you control after all the RCPT commands, but before the message itself is received. It offers the opportunity to give a negative response to the DATA command before the data is transmitted. Header lines added by MAIL or RCPT ACLs are not visible at this time, but any that are defined here are visible when the acl_smtp_data ACL is run.

You cannot test the contents of the message, for example, to verify addresses in the headers, at RCPT time or when the DATA command is received. Such tests have to appear in the ACL that is run after the message itself has been received, before the final response to the DATA command is sent. This is the ACL specified by acl_smtp_data, which is the second ACL that is associated with the DATA command.

For both of these ACLs, it is not possible to reject individual recipients. An error response rejects the entire message. Unfortunately, it is known that some MTAs do not treat hard (5xx) responses to the DATA command (either before or after the data) correctly – they keep the message on their queues and try again later, but that is their problem, though it does waste some of your resources.

The acl_smtp_mime option is available only when Exim is compiled with the content-scanning extension. For details, see chapter 41.

The ACL for the SMTP QUIT command is anomalous, in that the outcome of the ACL does not affect the response code to QUIT, which is always 221. Thus, the ACL does not in fact control any access. For this reason, the only verbs that are permitted are accept and warn.

This ACL can be used for tasks such as custom logging at the end of an SMTP session. For example, you can use ACL variables in other ACLs to count messages, recipients, etc., and log the totals at QUIT time using one or more logwrite modifiers on a warn verb.

Warning: Only the $acl_cx variables can be used for this, because the $acl_mx variables are reset at the end of each incoming message.

You do not need to have a final accept, but if you do, you can use a message modifier to specify custom text that is sent as part of the 221 response to QUIT.

This ACL is run only for a “normal” QUIT. For certain kinds of disastrous failure (for example, failure to open a log file, or when Exim is bombing out because it has detected an unrecoverable error), all SMTP commands from the client are given temporary error responses until QUIT is received or the connection is closed. In these special cases, the QUIT ACL does not run.

The not-QUIT ACL, specified by smtp_notquit_acl, is run in most cases when an SMTP session ends without sending QUIT. However, when Exim itself is is bad trouble, such as being unable to write to its log files, this ACL is not run, because it might try to do things (such as write to log files) that make the situation even worse.

Like the QUIT ACL, this ACL is provided to make it possible to do customized logging or to gather statistics, and its outcome is ignored. The delay modifier is forbidden in this ACL, and the only permitted verbs are accept and warn.

When the not-QUIT ACL is running, the variable $smtp_notquit_reason is set to a string that indicates the reason for the termination of the SMTP connection. The possible values are:

    acl-dropAnother ACL issued a drop command
    bad-commandsToo many unknown or non-mail commands
    command-timeoutTimeout while reading SMTP commands
    connection-lostThe SMTP connection has been lost
    data-timeoutTimeout while reading message data
    local-scan-errorThe local_scan() function crashed
    local-scan-timeoutThe local_scan() function timed out
    signal-exitSIGTERM or SIGINT
    synchronization-errorSMTP synchronization error
    tls-failedTLS failed to start

In most cases when an SMTP connection is closed without having received QUIT, Exim sends an SMTP response message before actually closing the connection. With the exception of the acl-drop case, the default message can be overridden by the message modifier in the not-QUIT ACL. In the case of a drop verb in another ACL, it is the message from the other ACL that is used.

The value of an acl_smtp_xxx option is expanded before use, so you can use different ACLs in different circumstances. For example,

acl_smtp_rcpt = ${if ={25}{$interface_port} \
                     {acl_check_rcpt} {acl_check_rcpt_submit} }

In the default configuration file there are some example settings for providing an RFC 4409 message submission service on port 587 and a non-standard “smtps” service on port 465. You can use a string expansion like this to choose an ACL for MUAs on these ports which is more appropriate for this purpose than the default ACL on port 25.

The expanded string does not have to be the name of an ACL in the configuration file; there are other possibilities. Having expanded the string, Exim searches for an ACL as follows:

  • If the string begins with a slash, Exim uses it as a file name, and reads its contents as an ACL. The lines are processed in the same way as lines in the Exim configuration file. In particular, continuation lines are supported, blank lines are ignored, as are lines whose first non-whitespace character is “#”. If the file does not exist or cannot be read, an error occurs (typically causing a temporary failure of whatever caused the ACL to be run). For example:

    acl_smtp_data = /etc/acls/\
      ${lookup{$sender_host_address}lsearch\
      {/etc/acllist}{$value}{default}}
    

    This looks up an ACL file to use on the basis of the host’s IP address, falling back to a default if the lookup fails. If an ACL is successfully read from a file, it is retained in memory for the duration of the Exim process, so that it can be re-used without having to re-read the file.

  • If the string does not start with a slash, and does not contain any spaces, Exim searches the ACL section of the configuration for an ACL whose name matches the string.

  • If no named ACL is found, or if the string contains spaces, Exim parses the string as an inline ACL. This can save typing in cases where you just want to have something like

    acl_smtp_vrfy = accept
    

    in order to allow free use of the VRFY command. Such a string may contain newlines; it is processed in the same way as an ACL that is read from a file.

Except for the QUIT ACL, which does not affect the SMTP return code (see section 40.8 above), the result of running an ACL is either “accept” or “deny”, or, if some test cannot be completed (for example, if a database is down), “defer”. These results cause 2xx, 5xx, and 4xx return codes, respectively, to be used in the SMTP dialogue. A fourth return, “error”, occurs when there is an error such as invalid syntax in the ACL. This also causes a 4xx return code.

For the non-SMTP ACL, “defer” and “error” are treated in the same way as “deny”, because there is no mechanism for passing temporary errors to the submitters of non-SMTP messages.

ACLs that are relevant to message reception may also return “discard”. This has the effect of “accept”, but causes either the entire message or an individual recipient address to be discarded. In other words, it is a blackholing facility. Use it with care.

If the ACL for MAIL returns “discard”, all recipients are discarded, and no ACL is run for subsequent RCPT commands. The effect of “discard” in a RCPT ACL is to discard just the one recipient address. If there are no recipients left when the message’s data is received, the DATA ACL is not run. A “discard” return from the DATA or the non-SMTP ACL discards all the remaining recipients. The “discard” return is not permitted for the acl_smtp_predata ACL.

The local_scan() function is always run, even if there are no remaining recipients; it may create new recipients.

The default actions when any of the acl_xxx options are unset are not all the same. Note: These defaults apply only when the relevant ACL is not defined at all. For any defined ACL, the default action when control reaches the end of the ACL statements is “deny”.

For acl_smtp_quit and acl_not_smtp_start there is no default because these two are ACLs that are used only for their side effects. They cannot be used to accept or reject anything.

For acl_not_smtp, acl_smtp_auth, acl_smtp_connect, acl_smtp_data, acl_smtp_helo, acl_smtp_mail, acl_smtp_mailauth, acl_smtp_mime, acl_smtp_predata, and acl_smtp_starttls, the action when the ACL is not defined is “accept”.

For the others (acl_smtp_etrn, acl_smtp_expn, acl_smtp_rcpt, and acl_smtp_vrfy), the action when the ACL is not defined is “deny”. This means that acl_smtp_rcpt must be defined in order to receive any messages over an SMTP connection. For an example, see the ACL in the default configuration file.

When a MAIL or RCPT ACL, or either of the DATA ACLs, is running, the variables that contain information about the host and the message’s sender (for example, $sender_host_address and $sender_address) are set, and can be used in ACL statements. In the case of RCPT (but not MAIL or DATA), $domain and $local_part are set from the argument address. The entire SMTP command is available in $smtp_command.

When an ACL for the AUTH parameter of MAIL is running, the variables that contain information about the host are set, but $sender_address is not yet set. Section 33.2 contains a discussion of this parameter and how it is used.

The

Except for the QUIT ACL, which does not affect the SMTP return code (see section 40.8 above), the result of running an ACL is either “accept” or “deny”, or, if some test cannot be completed (for example, if a database is down), “defer”. These results cause 2xx, 5xx, and 4xx return codes, respectively, to be used in the SMTP dialogue. A fourth return, “error”, occurs when there is an error such as invalid syntax in the ACL. This also causes a 4xx return code.

For the non-SMTP ACL, “defer” and “error” are treated in the same way as “deny”, because there is no mechanism for passing temporary errors to the submitters of non-SMTP messages.

ACLs that are relevant to message reception may also return “discard”. This has the effect of “accept”, but causes either the entire message or an individual recipient address to be discarded. In other words, it is a blackholing facility. Use it with care.

If the ACL for MAIL returns “discard”, all recipients are discarded, and no ACL is run for subsequent RCPT commands. The effect of “discard” in a RCPT ACL is to discard just the one recipient address. If there are no recipients left when the message’s data is received, the DATA ACL is not run. A “discard” return from the DATA or the non-SMTP ACL discards all the remaining recipients. The “discard” return is not permitted for the acl_smtp_predata ACL.

The local_scan() function is always run, even if there are no remaining recipients; it may create new recipients.

The default actions when any of the acl_xxx options are unset are not all the same. Note: These defaults apply only when the relevant ACL is not defined at all. For any defined ACL, the default action when control reaches the end of the ACL statements is “deny”.

For acl_smtp_quit and acl_not_smtp_start there is no default because these two are ACLs that are used only for their side effects. They cannot be used to accept or reject anything.

For acl_not_smtp, acl_smtp_auth, acl_smtp_connect, acl_smtp_data, acl_smtp_helo, acl_smtp_mail, acl_smtp_mailauth, acl_smtp_mime, acl_smtp_predata, and acl_smtp_starttls, the action when the ACL is not defined is “accept”.

For the others (acl_smtp_etrn, acl_smtp_expn, acl_smtp_rcpt, and acl_smtp_vrfy), the action when the ACL is not defined is “deny”. This means that acl_smtp_rcpt must be defined in order to receive any messages over an SMTP connection. For an example, see the ACL in the default configuration file.

When a MAIL or RCPT ACL, or either of the DATA ACLs, is running, the variables that contain information about the host and the message’s sender (for example, $sender_host_address and $sender_address) are set, and can be used in ACL statements. In the case of RCPT (but not MAIL or DATA), $domain and $local_part are set from the argument address. The entire SMTP command is available in $smtp_command.

When an ACL for the AUTH parameter of MAIL is running, the variables that contain information about the host are set, but $sender_address is not yet set. Section 33.2 contains a discussion of this parameter and how it is used.

The

Except for the QUIT ACL, which does not affect the SMTP return code (see section 40.8 above), the result of running an ACL is either “accept” or “deny”, or, if some test cannot be completed (for example, if a database is down), “defer”. These results cause 2xx, 5xx, and 4xx return codes, respectively, to be used in the SMTP dialogue. A fourth return, “error”, occurs when there is an error such as invalid syntax in the ACL. This also causes a 4xx return code.

For the non-SMTP ACL, “defer” and “error” are treated in the same way as “deny”, because there is no mechanism for passing temporary errors to the submitters of non-SMTP messages.

ACLs that are relevant to message reception may also return “discard”. This has the effect of “accept”, but causes either the entire message or an individual recipient address to be discarded. In other words, it is a blackholing facility. Use it with care.

If the ACL for MAIL returns “discard”, all recipients are discarded, and no ACL is run for subsequent RCPT commands. The effect of “discard” in a RCPT ACL is to discard just the one recipient address. If there are no recipients left when the message’s data is received, the DATA ACL is not run. A “discard” return from the DATA or the non-SMTP ACL discards all the remaining recipients. The “discard” return is not permitted for the acl_smtp_predata ACL.

The local_scan() function is always run, even if there are no remaining recipients; it may create new recipients.

The default actions when any of the acl_xxx options are unset are not all the same. Note: These defaults apply only when the relevant ACL is not defined at all. For any defined ACL, the default action when control reaches the end of the ACL statements is “deny”.

For acl_smtp_quit and acl_not_smtp_start there is no default because these two are ACLs that are used only for their side effects. They cannot be used to accept or reject anything.

For acl_not_smtp, acl_smtp_auth, acl_smtp_connect, acl_smtp_data, acl_smtp_helo, acl_smtp_mail, acl_smtp_mailauth, acl_smtp_mime, acl_smtp_predata, and acl_smtp_starttls, the action when the ACL is not defined is “accept”.

For the others (acl_smtp_etrn, acl_smtp_expn, acl_smtp_rcpt, and acl_smtp_vrfy), the action when the ACL is not defined is “deny”. This means that acl_smtp_rcpt must be defined in order to receive any messages over an SMTP connection. For an example, see the ACL in the default configuration file.

When a MAIL or RCPT ACL, or either of the DATA ACLs, is running, the variables that contain information about the host and the message’s sender (for example, $sender_host_address and $sender_address) are set, and can be used in ACL statements. In the case of RCPT (but not MAIL or DATA), $domain and $local_part are set from the argument address. The entire SMTP command is available in $smtp_command.

When an ACL for the AUTH parameter of MAIL is running, the variables that contain information about the host are set, but $sender_address is not yet set. Section 33.2 contains a discussion of this parameter and how it is used.

The