.set I " "
.macro copyyear
-2019
+2020
.endmacro
. /////////////////////////////////////////////////////////////////////////////
.code
local_delivery:
driver = appendfile
- file = /var/mail/$local_part_verified
+ file = /var/mail/$local_part_data
delivery_date_add
envelope_to_add
return_path_add
.new
We prefer to avoid using &$local_part$& directly to define the mailbox filename,
as it is provided by a potential bad actor.
-Instead we use &$local_part_verified$&,
+Instead we use &$local_part_data$&,
the result of looking up &$local_part$& in the user database
(done by using &%check_local_user%& in the the router).
.wen
nunbered array element is selected.
Otherwise it must apply to a JSON object; the named element is selected.
The final resulting element can be a simple JSON type or a JSON object
-or array; for the latter two a string-representation os the JSON
+or array; for the latter two a string-representation of the JSON
is returned.
For elements of type string, the returned value is de-quoted.
.next
lookup types support only literal keys.
.next
+.cindex "spf lookup type"
.cindex "lookup" "spf"
-If Exim is built with SPF support, manual lookups can be done
-(as opposed to the standard ACL condition method.
+&(spf)&: If Exim is built with SPF support, manual lookups can be done
+(as opposed to the standard ACL condition method).
For details see section &<<SECSPF>>&.
.endlist ilist
+.new
+.section "Results of list checking" SECTlistresults
+The primary result of doing a list check is a truth value.
+In some contexts additional information is stored
+about the list element that matched:
+.vlist
+.vitem hosts
+A &%hosts%& ACL condition
+will store a result in the &$host_data$& variable.
+.vitem local_parts
+A &%local_parts%& router option or &%local_parts%& ACL condition
+will store a result in the &$local_part_data$& variable.
+.vitem domains
+A &%domains%& router option or &%domains%& ACL condition
+.vitem senders
+A &%senders%& router option or &%senders%& ACL condition
+will store a result in the &$sender_data$& variable.
+.vitem recipients
+A &%recipients%& ACL condition
+will store a result in the &$recipient_data$& variable.
+.endlist
+
+The detail of the additional information depends on the
+type of match and is given below as the &*value*& information.
+.wen
+
+
+
+
.section "Named lists" "SECTnamedlists"
.cindex "named lists"
.cindex "list" "named"
as set by the &%primary_hostname%& option (or defaulted). This makes it
possible to use the same configuration file on several different hosts that
differ only in their names.
+
+.new
+The value for a match will be the primary host name/
+.wen
+
+
.next
.cindex "@[] in a domain list"
.cindex "domain list" "matching local IP interfaces"
&%local_interfaces%& and &%extra_local_interfaces%& options can be used to
control which of a host's several IP addresses are treated as local.
In today's Internet, the use of domain literals is controversial.
+
+.new
+The value for a match will be the &`@[]`& string.
+.wen
+
+
.next
.cindex "@mx_any"
.cindex "@mx_primary"
domains = <? @mx_any/ignore=<;127.0.0.1;::1 ? \
an.other.domain ? ...
.endd
+.new
+The value for a match will be the list element string (starting &`@mx_`&).
+.wen
+
+
.next
.cindex "asterisk" "in domain list"
.cindex "domain list" "asterisk in"
list item such as &`*key.ex`& matches &'donkey.ex'& as well as
&'cipher.key.ex'&.
+.new
+The value for a match will be the list element string (starting with the asterisk).
+.wen
+
.next
.cindex "regular expressions" "in domain list"
.cindex "domain list" "matching regular expression"
use the special &`\N`& sequence (see chapter &<<CHAPexpand>>&) to specify that
it is not to be expanded (unless you really do want to build a regular
expression by expansion, of course).
+
+.new
+The value for a match will be the list element string (starting with the circumflex).
+.wen
+
+
+
.next
.cindex "lookup" "in domain list"
.cindex "domain list" "matching by lookup"
domains = cdb;/etc/mail/local_domains.cdb
.endd
The appropriate type of lookup is done on the file using the domain name as the
-key. In most cases, the data that is looked up is not used; Exim is interested
+key. In most cases, the value resulting from the lookup is not used; Exim is interested
only in whether or not the key is present in the file. However, when a lookup
is used for the &%domains%& option on a router
-or a &%domains%& condition in an ACL statement, the data is preserved in the
+or a &%domains%& condition in an ACL statement, the value is preserved in the
&$domain_data$& variable and can be referred to in other router options or
other statements in the same ACL.
+.cindex "tainted data" "de-tainting"
+The value will be untainted.
+
.next
Any of the single-key lookup type names may be preceded by
select particular domains (because any domain would match), but it might have
value if the result of the lookup is being used via the &$domain_data$&
expansion variable.
+
.next
If the pattern starts with the name of a query-style lookup type followed by a
semicolon (for example, &"nisplus;"& or &"ldap;"&), the remainder of the
hold_domains = mysql;select domain from holdlist \
where domain = '${quote_mysql:$domain}';
.endd
-In most cases, the data that is looked up is not used (so for an SQL query, for
+In most cases, the value resulting from the lookup is not used (so for an SQL query, for
example, it doesn't matter what field you select). Exim is interested only in
whether or not the query succeeds. However, when a lookup is used for the
-&%domains%& option on a router, the data is preserved in the &$domain_data$&
+&%domains%& option on a router, the value is preserved in the &$domain_data$&
variable and can be referred to in other options.
+.cindex "tainted data" "de-tainting"
+The value will be untainted.
+
.next
.new
If the pattern starts with the name of a lookup type
of either kind (single-key or query-style) it may be
-followed by a command and options,
+followed by a comma and options,
The options are lookup-type specific and consist of a comma-separated list.
Each item starts with a tag and and equals "=".
.wen
+
.next
.cindex "domain list" "matching literal domain name"
If none of the above cases apply, a caseless textual comparison is made
between the pattern and the domain.
+
+The value for a match will be the list element string.
+.cindex "tainted data" "de-tainting"
+Note that this is commonly untainted
+(depending on the way the list was created).
+This is a useful way of obtaining an untainted equivalent to
+the domain, for later operations.
.endlist
+
Here is an example that uses several different kinds of pattern:
.code
domainlist funny_domains = \
.endd
The third argument is a list of options, of which the first element is the timeout
-and must be present if the argument is given.
+and must be present if any options are given.
Further elements are options of form &'name=value'&.
-Two option types is currently recognised: shutdown and tls.
-The first defines whether (the default)
-or not a shutdown is done on the connection after sending the request.
-Example, to not do so (preferred, eg. by some webservers):
+Example:
.code
${readsocket{/socket/name}{request string}{3s:shutdown=no}}
.endd
-The second, tls, controls the use of TLS on the connection. Example:
-.code
-${readsocket{/socket/name}{request string}{3s:tls=yes}}
-.endd
-The default is to not use TLS.
+
+.new
+The following option names are recognised:
+.ilist
+&*cache*&
+Defines if the result data can be cached for use by a later identical
+request in the same process.
+Values are &"yes"& or &"no"& (the default).
+If not, all cached results for this connection specification
+will be invalidated.
+
+.next
+&*shutdown*&
+Defines whether or not a write-shutdown is done on the connection after
+sending the request. Values are &"yes"& (the default) or &"no"&
+(preferred, eg. by some webservers).
+
+.next
+&*tls*&
+Controls the use of TLS on the connection.
+Values are &"yes"& or &"no"& (the default).
If it is enabled, a shutdown as descripbed above is never done.
+.endlist
+.wen
+
A fourth argument allows you to change any newlines that are in the data
that is read, in the same way as for &%readfile%& (see above). This example
.cindex "tainted data"
If the origin of the data is an incoming message,
the result of expanding this variable is tainted.
-See also &$domain_verified$&.
+When un untainted version is needed, one should be obtained from
+looking up the value in a local (therefore trusted) database.
+Often &$domain_data$& is usable in this role.
.wen
for file access.
This presents issues for users' &_.forward_& and filter files.
For traditional full user accounts, use &%check_local_users%& and the
-&$local_part_verified$& variable rather than this one.
+&$local_part_data$& variable rather than this one.
For virtual users, store a suitable pathname component in the database
which is used for account name validation, and use that retrieved value
rather than this variable.
+Often &$local_part_data$& is usable in this role.
If needed, use a router &%address_data%& or &%set%& option for
the retrieved data.
.wen
-.vindex "&$local_part_prefix$&"
-.vindex "&$local_part_prefix_v$&"
-.vindex "&$local_part_suffix$&"
-.vindex "&$local_part_suffix_v$&"
-.cindex affix variables
-If a local part prefix or suffix has been recognized, it is not included in the
-value of &$local_part$& during routing and subsequent delivery. The values of
-any prefix or suffix are in &$local_part_prefix$& and
-&$local_part_suffix$&, respectively.
-.new
-If the affix specification included a wildcard then the portion of
-the affix matched by the wildcard is in
-&$local_part_prefix_v$& or &$local_part_suffix_v$& as appropriate.
-.wen
-
When a message is being delivered to a file, pipe, or autoreply transport as a
result of aliasing or forwarding, &$local_part$& is set to the local part of
the parent address, not to the filename or command (see &$address_file$& and
to a transport, the value is available in that transport. If the transport is
handling multiple addresses, the value from the first address is used.
+.new
+The &%check_local_user%& router option also sets this variable.
+.wen
+
&$local_part_data$& is also set when the &%local_parts%& condition in an ACL
matches a local part by means of a lookup. The data read by the lookup is
available during the rest of the ACL statement. In all other situations, this
variable expands to nothing.
-.vitem &$local_part_prefix$&
-.vindex "&$local_part_prefix$&"
+.vindex &$local_part_prefix$& &&&
+ &$local_part_prefix_v$& &&&
+ &$local_part_suffix$& &&&
+ &$local_part_suffix_v$&
.cindex affix variables
-When an address is being routed or delivered, and a
-specific prefix for the local part was recognized, it is available in this
-variable, having been removed from &$local_part$&.
-
-.new
-.vitem &$local_part_prefix_v$&
-.vindex "&$local_part_prefix_v$&"
-When &$local_part_prefix$& is valid and the prefix match used a wildcard,
-the portion matching the wildcard is available in this variable.
-.wen
-
-.vitem &$local_part_suffix$&
-.vindex "&$local_part_suffix$&"
-When an address is being routed or delivered, and a
-specific suffix for the local part was recognized, it is available in this
-variable, having been removed from &$local_part$&.
-
+If a local part prefix or suffix has been recognized, it is not included in the
+value of &$local_part$& during routing and subsequent delivery. The values of
+any prefix or suffix are in &$local_part_prefix$& and
+&$local_part_suffix$&, respectively.
.new
-.vitem &$local_part_suffix_v$&
-.vindex "&$local_part_suffix_v$&"
-When &$local_part_suffix$& is valid and the suffix match used a wildcard,
-the portion matching the wildcard is available in this variable.
-.wen
+.cindex "tainted data"
+If the specification did not include a wildcard then
+the affix variable value is not tainted.
-.new
-.vitem &$local_part_verified$&
-.vindex "&$local_part_verified$&"
-If the router generic option &%check_local_part%& has run successfully,
-this variable has the user database version of &$local_part$&.
-Such values are not tainted and hence usable for building file names.
+If the affix specification included a wildcard then the portion of
+the affix matched by the wildcard is in
+&$local_part_prefix_v$& or &$local_part_suffix_v$& as appropriate,
+and both the whole and varying values are tainted.
.wen
.vitem &$local_scan_data$&
.table2
.row &%dkim_verify_hashes%& "DKIM hash methods accepted for signatures"
.row &%dkim_verify_keytypes%& "DKIM key types accepted for signatures"
+.row &%dkim_verify_min_keysizes%& "DKIM key sizes accepted for signatures"
.row &%dkim_verify_signers%& "DKIM domains for which DKIM ACL is run"
.row &%host_lookup%& "host name looked up for these hosts"
.row &%host_lookup_order%& "order of DNS and local name lookups"
required, it must come from the &%-oA%& command line option.
-.option bounce_message_file main string unset
+.option bounce_message_file main string&!! unset
.cindex "bounce message" "customizing"
.cindex "customizing" "bounce message"
This option defines a template file containing paragraphs of text to be used
for constructing bounce messages. Details of the file's contents are given in
-chapter &<<CHAPemsgcust>>&. See also &%warn_message_file%&.
+chapter &<<CHAPemsgcust>>&.
+.new
+.cindex bounce_message_file "tainted data"
+The option is expanded to give the file path, which must be
+absolute and untainted.
+.wen
+See also &%warn_message_file%&.
.option bounce_message_text main string unset
and an order of processing.
Signatures with algorithms not in the list will be ignored.
+
+.new
+.option dkim_verify_min_keysizes main "string list" "rsa=1024 ed25519=250"
+This option gives a list of key sizes which are acceptable in signatures.
+The list is keyed by the algorithm type for the key; the values are in bits.
+Signatures with keys smaller than given by this option will fail verification.
+
+The default enforces the RFC 8301 minimum key size for RSA signatures.
+.wen
+
.option dkim_verify_minimal main boolean false
If set to true, verification of signatures will terminate after the
first success.
See &%uucp_from_pattern%& above.
-.option warn_message_file main string unset
+.option warn_message_file main string&!! unset
.cindex "warning of delay" "customizing the message"
.cindex "customizing" "warning message"
This option defines a template file containing paragraphs of text to be used
for constructing the warning message which is sent by Exim when a message has
been in the queue for a specified amount of time, as specified by
&%delay_warning%&. Details of the file's contents are given in chapter
-&<<CHAPemsgcust>>&. See also &%bounce_message_file%&.
+&<<CHAPemsgcust>>&.
+.new
+.cindex warn_message_file "tainted data"
+The option is expanded to give the file path, which must be
+absolute and untainted.
+.wen
+See also &%bounce_message_file%&.
.option write_rejectlog main boolean true
used. For example:
.code
require_files = mail:/some/file
-require_files = $local_part:$home/.procmailrc
+require_files = $local_part_data:$home/.procmailrc
.endd
If a user or group name in a &%require_files%& list does not exist, the
&%require_files%& condition fails.
# This transport overrides the group
group_delivery:
driver = appendfile
- file = /var/spool/mail/$local_part
+ file = /var/spool/mail/$local_part_data
group = mail
.endd
If &%user%& is set for a transport, its value overrides what is set in the
way of handling this requirement:
.code
file = ${if eq{$address_file}{inbox} \
- {/var/mail/$local_part} \
+ {/var/mail/$local_part_data} \
{${if eq{${substr_0_1:$address_file}}{/} \
{$address_file} \
{$home/mail/$address_file} \
path. The most common settings of this option are variations on one of these
examples:
.code
-file = /var/spool/mail/$local_part
-file = /home/$local_part/inbox
+file = /var/spool/mail/$local_part_data
+file = /home/$local_part_data/inbox
file = $home/inbox
.endd
.cindex "&""sticky""& bit"
folders. Consider this example:
.code
maildir_format = true
-directory = /var/mail/$local_part\
+directory = /var/mail/$local_part_data\
${if eq{$local_part_suffix}{}{}\
{/.${substr_1:$local_part_suffix}}}
maildirfolder_create_regex = /\.[^/]+$
# transport
procmail_pipe:
driver = pipe
- command = /usr/local/bin/procmail -d $local_part
+ command = /usr/local/bin/procmail -d $local_part_data
return_path_add
delivery_date_add
envelope_to_add
check_string = "From "
escape_string = ">From "
umask = 077
- user = $local_part
+ user = $local_part_data
group = mail
# router
check_local_user
driver = redirect
domains = +local_domains
- file = /central/filters/$local_part
+ file = /central/filters/$local_part_data
no_verify
allow_filter
allow_freeze
lists:
driver = redirect
domains = lists.example
- file = /usr/lists/$local_part
+ file = ${lookup {$local_part} dsearch,ret=full {/usr/lists}}
forbid_pipe
forbid_file
- errors_to = $local_part-request@lists.example
+ errors_to = ${quote_local_part:$local_part-request}@lists.example
no_more
.endd
This router is skipped for domains other than &'lists.example'&. For addresses
driver = redirect
domains = lists.example
local_part_suffix = -request
- file = /usr/lists/$local_part$local_part_suffix
+ local_parts = ${lookup {$local_part} dsearch,filter=file {/usr/lists}}
+ file = /usr/lists/${local_part_data}-request
no_more
lists_post:
domains = lists.example
senders = ${if exists {/usr/lists/$local_part}\
{lsearch;/usr/lists/$local_part}{*}}
- file = /usr/lists/$local_part
+ file = ${lookup {$local_part} dsearch,ret=full {/usr/lists}}
forbid_pipe
forbid_file
- errors_to = $local_part-request@lists.example
+ errors_to = ${quote_local_part:$local_part-request}@lists.example
no_more
lists_closed:
max_rcpt = 1
return_path = \
${if match {$return_path}{^(.+?)-request@your.dom.example\$}\
- {$1-request+$local_part=$domain@your.dom.example}fail}
+ {${quote_local_part:$1-request+$local_part=$domain}@your.dom.example}fail}
.endd
This has the effect of rewriting the return path (envelope sender) on outgoing
SMTP messages, if the local part of the original return path ends in
transport = remote_smtp
errors_to = \
${if match {$return_path}{^(.+?)-request@your.dom.example\$}}
- {$1-request+$local_part=$domain@your.dom.example}fail}
+ {${quote_local_part:$1-request+$local_part=$domain}@your.dom.example}fail}
no_more
.endd
Before you start sending out messages with VERPed return paths, you must also
.code
my_mailboxes:
driver = appendfile
- file = /var/mail/$domain/$local_part
+ file = /var/mail/$domain/$local_part_data
user = mail
.endd
This uses a directory of mailboxes for each domain. The &%user%& setting is
userforward:
driver = redirect
check_local_user
- file = $home/.forward$local_part_suffix
local_part_suffix = -*
local_part_suffix_optional
+ file = ${lookup {.forward$local_part_suffix} dsearch,ret=full {$home} {$value}fail}
allow_filter
.endd
If there is no suffix, &_.forward_& is used; if the suffix is &'-special'&, for
.vitem &%$dkim_key_length%&
Number of bits in the key.
+.new
+Valid only once the key is loaded, which is at the time the header signature
+is verified, which is after the body hash is.
+.wen
Note that RFC 8301 says:
.code
less than 1024 bits as valid signatures.
.endd
-To enforce this you must have a DKIM ACL which checks this variable
-and overwrites the &$dkim_verify_status$& variable as discussed above.
-As EC keys are much smaller, the check should only do this for RSA keys.
+This is enforced by the default setting for the &%dkim_verify_min_keysizes%&
+option.
.endlist