MOPHERD.ACL(5)

NAME
mopherd.acl - the mopher daemon access control list

DESCRIPTION
The mopherd.acl file contains a list of rules enforced by mopherd(8) at one or more milter stages.

Comment lines in mopherd.acl start with the ‘#’ character, empty lines are treated as comments. Statements are either definitions or rules and can span multiple lines.

RULES
A statement is a rule if it has the following structure:

stage condition action

A stage is generally named after a milter stage and it is therefore necessary to know how the available milter stages correspond to the various stages of a SMTP transaction:
milter stage | SMTP stage
connect | (connection established)
helo | HELO (hostname)
envfrom | MAIL FROM: (sender)
envrcpt | RCPT TO: (one recipient)
data | DATA
header | (one header)
eoh | (empty line)
body | (one line of body)
eom |.
close | QUIT

The milter stages envrcpt, header and body can be entered one or more times during a SMTP transaction. If the remote host or the MTA closes the connection prematurely while being in any stage between envfrom and eom, the additional stage abort will be entered before entering close. If the remote host issues unknown commands during a SMTP transaction, the additional stage unknown will be entered.

After entering a milter stage, condition is evaluated. If the evaluation returns true, action is taken. A condition is an expression.

EXPRESSIONS
An expression is recursively defined as one or more expressions, associated by arithmetic, relational, pattern, list and boolean operators. Basic expressions are constants, variables, symbols, functions and lists.

A constant is either a string, integer, float or address:

    "foo"		# string
    "1"		# string
    ""		# string
    100		# integer
    1.1		# float
    ::1		# address
    127.0.0.1	# address

Each integer may have one of the following optional suffixes:
s[econd]
    multiply by 1
m[inute]
    multiply by 60
h[our]
    multiply by 3600
d[ay]
    multiply by 86400
K[ibi]
    multiply by 1024
M[ebi]
    multiply by 1048576
G[ibi]
    multiply by 1073741824

A variable begins with a ‘$’ and is a resolvable entity that may be set at any milter stage (see ACTIONS: set action).

A symbol is a resolvable entity that may or may not be available at a particular milter stage (see SYMBOLS).

A function is a resolvable entity that is always available and has zero or more parameters (see FUNCTIONS).

A list is a searchable entity with zero or more items (see LISTS).

Variables, symbols and functions will only be resolved if they appear in an expression that is being evaluated. Resolving variables, symbols and functions may yield unknown values alias null values. Unknown values have a certain effect on the way boolean operators work. If one or more operands in an arithmetic or relational operation is null, the result will be unknown and therefore null.

Arithmetic operations ( ‘+’, ‘-’, ‘*’, ‘/’, ‘%’) on integers and floats work as one might expect. Implicit type conversion will take place if necessary and possible. Division (‘/’) of integers may yield truncated results, addition (‘+’) of strings will concatenate them and modulo reduction (‘%’) is only defined on integers:

    "foo" + "bar"	# "foobar"
    3 / 2		# 1
    3 / 2.0		# 1.5
    3 % 2		# 1
    3 % 2.0		# error

Relational operations ( ‘<’, ‘<=’, ‘>’, ‘>=’, ‘==’, ‘!=’) on integers, floats and strings work as one might expect. Implicit type conversion will take place if necessary and possible.

Pattern operators ( ‘~’, ‘!~’) associate two string operands and interpret the operand on the right-hand side as a sequence pattern described using POSIX Extended Regular Expressions. The pattern is case-sensitive if it contains at least one upper case letter, case-insensitive otherwise.

‘~’ evaluates true if the string operand on the left-hand side matches the pattern, false othervise. ‘!~’ operates the same way, but inverts the evaluation result.

List operators ( ‘in’) are only defined on lists (see LISTS).

Boolean operators ( ‘’!, ‘&&’, ‘||’) mimic their counterparts within the Kleene logic which is a three-valued logic. Truth values of a 3VL consist of true, false and a third, indeterminate value unknown or null.

The truth table for ‘’! (NOT) and any expression A:
A | !A
false | true
null | null
true | false

The truth table for ‘&&’ (AND), ‘||’ (OR) and any expression A and B:
A | B | A && B | A || B
false | false | false | false
false | null | false | null
false | true | false | true
null | false | false | null
null | null | null | null
null | true | null | true
true | false | false | true
true | null | null | true
true | true | true | true

Evaluating an integer or a float will yield false if the particular value is 0, true otherwise.

Evaluating a string will yield false if its value is "" (empty) or "0", true otherwise.

Evaluating an address will yield false if the address is invalid, true otherwise.

Evaluating a list will yield false if the list is empty, true otherwise.

Note: During the evaluation of any rule, action will only be taken if condition is true. false and null are equivalent in that case.

ACTIONS
An action describes how mopherd(8) and therefore the MTA, should handle the current SMTP transaction. Actions may have parameters that may or may not be omitted.

If the examples in the following list do not explicitly mention the stage and condition part of a rule, they are implied but omitted for reasons of brevity.

continue
    The continue action will stop the evaluation of any remaining rules tied to the current milter stage. Evaluation will continue at the next milter stage.

reject
    The reject action will reject the current SMTP transaction with a permanent error code and stop any further processing.

discard
    The discard action will accept the current SMTP transaction, discard the message silently and stop any further processing.

accept
    The accept action will accept the current SMTP transaction and stop any further processing.

tempfail
    The tempfail action will reject the current SMTP transaction with a temporary error code and stop any further processing.

greylist [delay exp] [attempts exp] [deadline exp] [visa exp]
    Until one of two possible thresholds are met, the greylist action will reject the current SMTP transaction with a temporary error code and stop any further processing.

    Greylisting an origin (address or domain) means keeping track of the effort made by that origin to deliver a message by a specific sender to a specific recipient. Effort is defined as either the number of attempts made by the origin or the delay he was willing to accept in order to carry out a particular SMTP transaction:

        # reject until 12 hours have passed
        #
        greylist delay 12h
        # reject until 2 attempts are recorded
        #
        greylist attempts 2
        # reject until 2 attempts are recorded within 4 hours
        #
        greylist attempts 2 deadline 4h
        # reject until 12 hours have passed
        #   or 5 attempts are recorded within 4 hours
        #
        greylist delay 12h attempts 5 deadline 4h

    After the required effort has been made, mopherd(8) will upgrade the greylist triplet (origin, sender and recipient combination) to a visa triplet. A visa triplet will allow for undelayed SMTP transactions until it expires:

        # reject until 12 hours have passed
        #   or 5 attempts are recorded within 4 hours
        #   and issue a visa for 7 days on success
        #
        greylist delay 12h attempts 5 deadline 4h visa 7d

    Successful SMTP transactions that resemble a valid visa triplet will automatically trigger the renewal of the corresponding visa.

    Note: Right before any greylist rules, your mopherd.acl should contain one empty greylist rule:

        # empty greylist rule
        #
        <stage> greylist

    An empty greylist rule will compare all existing greylist triplets with the current SMTP transaction and, in case a triplet matches, avoid the evaluation of subsequent greylist rules that are tied to potentially costly conditions.

tarpit exp
    The tarpit action will delay the current SMTP transaction (without rejecting it):

        # delay for 60 seconds
        #
        tarpit 60s

log exp
    The log action will log any custom message:

        # log "New connection from some.host.name!"
        #
        log "New connection from " + hostname + "!"

set $id = exp
    The set action will set a variable:

        # set $flag to 1
        #
        set $flag = 1

jump exp
    The jump action will stop the evaluation of any remaining rules tied to the current stage and jump to a different stage:

        # jump to first rule of stage2 if <condition> is true
        #
        stage1 <condition> jump stage2
        stage1 ...	# not evaluated if <condition> is true
        stage1 ...	# not evaluated if <condition> is true
        stage2 ...
        stage2 ...
        stage2 ...

    From the perspective of mopherd(8), there are no special stages. Every stage is just a named list of rules, but only stages that are named after one of the known milter stages will be entered during SMTP transactions. Therefore, jumping stages is a way of conditionally extending milter stages.

    Warning: Beware of circular jumps.

add header exp value exp
    The add header action will add header if it doesn't exist and replace its value otherwise.

insert header exp value exp [index exp]
    The insert header action will always add header. If index is greater than the number of existing headers, header will be added at the end of the list. If index is 0 (default), header will be added at the beginning of the list.

change header exp value exp [index exp]
    The change header action will replace the value of an existing header. If multiple headers exist, index may be used to replace only a particular occurence of header.

delete header exp [index exp]
    The delete header action will delete header. If multiple headers exist, index may be used to delete only a particular occurence of header.

change from exp [esmtp exp]
    The change from action will replace the envelope sender address. If esmtp is not null, it will be interpreted as a string containing additional ESMTP arguments.

add rcpt exp [esmtp exp]
    The add rcpt action will add an envelope recipient. If esmtp is not null, it will be interpreted as a string containing additional ESMTP arguments.

delete rcpt exp
    The delete rcpt action will remove an envelope recipient. The recipient address must be surrounded by angle brackets.

change body exp
    The change body action will replace the message body.

The actions greylist, tempfail and reject may be complemented by a custom SMTP reply:

<action> reply exp [xcode exp] message exp
    The MTA will use reply as the SMTP reply code, xcode as the extended SMTP reply code and message as the SMTP reply message:

        # reject known spammer
        #
        reject reply 550 xcode "5.7.1" message "No thanks, bye!"

The effect of accept, greylist, tempfail, reject and discard, the timing of a reply and the visibility of its message depend all on the way a particular MTA implementation handles SMTP transactions. In other words, mopherd(8) just passes its verdict (and a reply) but has no influence on whatever the MTA will do next.

DEFINITIONS
A definition is a placeholder for any expression:

    # simplify your mopherd.acl with definitions
    #
    define foo some complicated arithmetic expression
    define bar another complicated arithmetic expression
    connect log "foo = " + foo
    envrcpt log "bar = " + bar
    data    log "foo + bar = " + (foo + bar)

The evaluation of definitions is not limited in any way. Definitions may contain symbols, functions, operators or anything else that also makes up expressions as defined in the beginning of this document.

LISTS
A list is a searchable entity containing zero or more objects of any type. In mopherd.acl, a comma-separated list of expressions enclosed in parentheses constitutes a list:

    # list containing strings, floats and addresses
    #
    ("foo", "1", "", 100 + 1.1, ::1, 127.0.0.1)

Lists may be assigned to variables and searched with the ‘in’ operator:

    # assign list to $list
    #
    set $list = ("foo", "1", "", 100 + 1.1, ::1, 127.0.0.1)
    # search $list for items
    #
    "foo" in $list	# true
    100   in $list	# false
    101.1 in $list	# true
    ::1   in $list	# true

While there may be few use cases for custom lists, mopherd(8) often uses lists for certain multi-valued symbols.

SYMBOLS
The following list describes symbols known to mopherd(8). Type and stage availability are enclosed in parentheses. A symbol is either always available (any), exclusively bound to a milter stage (name) or bound to a milter stage and all stages following that stage (name*).

Note: Evaluating certain symbols will trigger queries or other costly operations. In such cases, mopherd(8) will save the result after the first evaluation and serve all subsequent lookups from its cache.

{id} (string)
    Content of Sendmail macro ‘{id}’, where id is an unquoted identifier string.

body (string, eom)
    String containing the whole message body.

body_size (int, eom)
    Size of message body in bytes.

counter_penpal (int, envrcpt)
    Number of previously delivered messages by origin for penpal.

counter_relay (int, any)
    Number of previously delivered messages by origin.

dnsbl (list, connect*)
    List of non-null DNSBL query results.

envfrom (string, envfrom*)
    Raw envelope from address.

envfrom_addr (string, envfrom*)
    Envelope from address.

envrcpt (string, envrcpt*)
    Raw envelope recipient address.

envrcpt_addr (string, envrcpt*)
    Envelope recipient address.

greylist_attempts (int, envfrom*)
    Number of delivery attempts required for origin to whitelist penpal.

greylist_connections (int, envfrom*)
    Number of attempts made by origin to deliver for penpal.

greylist_created (int, envfrom*)
    Time of first attempt made by origin to deliver for penpal.

greylist_deadline (int, envfrom*)
    Number of seconds given to origin to perform greylist_attempts, starting from greylist_created.

greylist_delay (int, envfrom*)
    Waiting period in seconds required for origin to whitelist penpal.

greylist_delayed (int, envfrom*)
    Number of seconds waited by origin to deliver for penpal.

greylist_expire (int, envfrom*)
    Expiration timestamp of greylist record created by origin trying to deliver for penpal at greylist_created.

greylist_listed (int, envfrom*)
    True (1), if an existing greylist record is associated with origin trying to deliver for penpal. False (0) otherwise.

greylist_passed (int, envfrom*)
    Number of delivered messages by origin for penpal after associated greylist record was upgraded to visa.

greylist_updated (int, envfrom*)
    Modification timestamp of greylist record created by origin trying to deliver for penpal at greylist_created.

greylist_visa (int, envfrom*)
    Validity period of upgraded greylist record in seconds.

header_name (string, header)
    Name of current header.

header_value (string, header)
    Value of current header.

headers (string, eoh*)
    String containing message headers.

headers_size (int, eoh*)
    Size of message headers in bytes.

helo (?, helo*)
    HELO identification as stated by origin.

hostaddr (addr, any)
    Address of origin.

hostaddr_str (string, any)
    Address string of connecting host.

hostname (istring, any)
    Name of origin, usually a forward-confirmed reverse DNS lookup.

id (int, any)
    Unique integer identifying current connection.

message_size (int, eom)
    Size of entire message in bytes.

origin (string, any)
    Origin identifier used for greylisting (address or domain).

received (string, any)
    Begin of connection timestamp.

recipient_list (list, data*)
    List of envelope recipient addresses.

recipients (int, envrcpt*)
    Number of recipients.

spamd_score (float, eom)
    SpamAssassin score of current message.

spamd_spam (int, eom)
    SpamAssassin verdict on current message.

spamd_symbols (list, eom)
    List of positive SpamAssassin tests for current message.

spf (string, envfrom*)
    Sender policy evaluation result for current host. Compareable with the following pre-defined symbols: SPF_NEUTRAL, SPF_PASS, SPF_FAIL, SPF_SOFTFAIL.

spf_reason (string, envfrom*)
    Reason for evaluation result in spf.

stagename (string, any)
    Name of current milter stage.

subject (string, eoh*)
    Content of ‘Subject’ header.

tarpit_delayed (int, any)
    Accumulated tarpit delay in seconds.

unknown_command (string, unknown)
    Unknown command issued by origin.

FUNCTIONS
The following list describes functions available in mopherd.acl.

Note: While all parameters are expressions, some functions expect a particular type after parameter evaluation.

cast(type, exp)
    Returns exp converted to type (string).

size(exp)
    Returns storage size (int) of exp.

mailaddr(str)
    Returns str without enclosing angle brackets ( ‘<’, ‘>’).

strcmp(str1, str2)
    Returns an integer greater than, equal to, or less than 0, according to whether str1 is greater than, equal to, or less than str2.

strlen(str)
    Returns length (int) of str.

type(exp)
    Returns type (string) of exp.

IMPLEMENTATION NOTES
Third party distributors of binary packages may split a full mopher build into several complementary packages in order to make some dependencies optional. In such cases, it is possible that some modules are not available on your system even though they are documented here.

SEE ALSO
mopher(7), mopherd(8), mopherctl(8)