mvmf: mvmtr man page
mvmf: mvmtr man page
MVMTR(1) MVMTR(1)
NAME
mvmtr - mvmf's Mail Transport Agent (MTA) receiver
SYNOPSIS
mvmtr [-b bodycache] [-C startfile] [-h hostname] [-v]
[-V]
DESCRIPTION
mvmtr implements a receiver portion of a mail transport
agent (MTA) designed to be used in conjunction with the
mvmda mail delivery agent (MDA). mvmtr, at least in its
initial incarnation, is designed to be used in place of
qmail's qmail-smtpd program.
It is not a drop-in replacment for qmail-smtpd, as it uses
its own control interface. However it can be configured
at compile-time to use the same control files as (and be
generally drop-in-compatible with) stock, unpatched qmail-
smtpd version 1.03 . (See qmail-smtpd compatibility notes
elsewhere.)
mvmtr includes an interpreter for its built-in mfl lan-
guage, which is a sort of mongrelization of C and Sieve.
mfl, which is described in another document, allows pro-
grammed control over what happens to email, and includes a
number of intrinsics related to processing email.
Options which may be given are as follows:
-b bodycache
Says how many bytes of message body to cache in
memory. The number given is constrained to lie
between a minimum and maximum specified at compile
time. The actual limit is somewhat fuzzy: regard-
less of the number specified and regardless of the
total number already cached, there is also a mini-
mum amount that will be cached in each MIME part.
-C startfile
The name of a startup file. The startup file is
simply mfl code, it is run in admin mode (with
regards to the "admin" mfl control). If this
option is omitted, a default is used if configured
at compile time. The startfile name must be found
within the system-wide mfl include path, and should
therefore not be a full path to the file.
This option will override any default startfile or
one specified via an environment variable.
-h hostname
specifies a host name to use in the SMTP dialog
when accepting email. The SMTP server must iden-
tify the server's host name to the connecting
client. If this option is not given, the host name
determined by a system call (e.g. gethostname())
is used.
-v prints mvtr's version number. The version number
has three decimal parts separated by periods: first
a major version number, next a minor version num-
ber, and finally a fix number. The fix number is
incremented whenever a new version contains only
fixes and enhancements to existing features. The
minor number is incremented whenever a new facility
or technique is added, and the major number is
incremented when enough new things have been added
to consider it a major new edition of the program.
A major number of zero (0) indicates a prerelease
version (one that doesn't yet include all its ini-
tial release features or that may not yet be con-
sidered fully tested).
-V prints mvmtr's version and control settings, in a
form suitable to be re-read via MFL. This will
show the effects of any initial startup configura-
tion.
MODES and CONTROLS
mvmtr is controlled by its command line options, various
environment variables, and some control files. Each of
these controls is described in a separate section (command
line options have been addressed earlier).
mvmtr may operate in one of several modes, as described
here. Of these modes, only ucspi-tcp mode is implemented
at this time; the others, however, are planned.
inetd mode
In this mode, there is some daemon process such as
inetd, outside of mvmtr's scope, that accepts
incoming TCP/IP connections. For each SMTP connec-
tion, that process invokes a specific program (in
this case, mvmtr) with the network connection set
up on stdin and stdout. No other information is
given to mvmtr.
ucspi-tcp mode
is somewhat like inetd mode. Here, there is also a
daemon process, again outside of mvmtr's scope,
that accepts incoming TCP/IP connections. In this
case, though, that daemon process is known either
to be the tcpserver program that's part of D. J.
Bernstein's ucspi-tcp package, or a functional
equivalent of that program. The network connection
is set up on stdin and stdout, but a number of
environment variables are set by the parent program
that give information about the connection, and
other variables may be set as control parameters.
Additionally, stderr is assumed to be set up to
accept log messages.
daemon mode
assumes no parent process at all. In this mode,
mvmtr listens on specific network ports for incom-
ing SMTP connections. It will then handle each of
these connections (specifically by forking a child
process of itself).
ENVIRONMENT VARIABLES
The following environment variables are significant to
mvmtr. Not all variables are relevant to all operating
modes.
inetd mode
There are no specific environment variables associated
with this mode.
ucspi-tcp mode
When operating in this mode, mvmtr is invoked once for
each incoming SMTP connection. The parent process is
expected to set a number of environment variables that
describe the connection to the client and offer some guid-
ance about how to treat the client. Each of the variable
names listed below is followed in parentheses by an indi-
cation of whether it's required or optional, plus an indi-
cation of the reference application from which this vari-
able use is derived. For example, a note of "(required,
ucspi-tcp)" means that the environment variable is manda-
tory, and that the use of this variable stems from prece-
dent set by the ucspi-tcp utility.
TCPLOCALHOST (required, ucspi-tcp)
is the name of the local host.
TCPLOCALIP (required, ucspi-tcp)
is the IP address of the local system; i.e. the IP
address on which the SMTP connection arrived.
TCPREMOTEHOST (optional, ucspi-tcp)
is the DNS name of the client system.
TCPREMOTEIP (required, ucspi-tcp)
is the IP address of the client.
RELAYCLIENT (optional, qmail)
if this variable is set, the client has (somehow)
been validated as a host for whom it's OK to relay
messages to unrelated destinations. If this vari-
able is not set, then the client is assumed to be a
foreign system unrelated to the receiving system,
and will be required to authenticate (using SMTP
AUTH) before being allowed to relay such messages.
Use of this variable may be phased out in the
future (other than in qmail-smtpd compatibility
mode). Until that time, though, we simply support
this value.
Unlike stock qmail-smtpd, mvmtr does not append the
value of this environment variable to all incoming
addresses.
SUPPRESS_AUTH (optional, mvmtr and mem's qmail patches)
if this environment variable is present, mvmtr will
not advertise the SMTP AUTH capability in response
to EHLO greetings from the client. This should
only be used if RELAYCLIENT is also set, and is
merely a workaround for some buggy clients that
will always attempt to do SMTP AUTH if that capa-
bility is advertised. As with RELAYCLIENT, use of
this variable is expected to be removed when more
explicit authorization controls are added.
daemon mode
There are no specific environment variables associated
with this mode.
generic variables
This section lists variables that are may be relevant to
any operating mode.
MVMTR_RC (optional)
specifies a startup file for mvmtr. As with the -C
command line option, the startfile must be found
within the system-wide mfl include path. This
environment variable (if present and non-empty)
will override any default startfile, but may itself
be overridden by the -C command line option.
CONTROL FILES
mvmtr reads some control files for instructions.
startfile
The startfile contains mfl code to affect the oper-
ation of mvmtr. By default this file is
/usr/local/sys/mvmf/mvmtr/mvmtr.mfl but this may be
changed during the installation process. (It may
also be overridden via an environment variable or a
command line option, as described elsewhere in this
document.) This file should contain calls to
built-in mfl functions to set mvmtr control values,
as described in the CONTROL VALUES section later
on. This file may also define mfl "hook" functions
that may be called by mvmtr at various points in
its execution. The possible hook functions are
described in a later section called HOOKS
address map file
The address map file provides a database of known
email addresses and address patterns. It may be
consulted via one of the checks that is done at (or
after) RCPT TO commands in the SMTP dialog. This
is an indexed file using D. J. Bernstein's constant
database file format (cdb). It is typically named
addrmap.cdb in the mvmtr system directory (e.g.
/usr/local/sys/mvmf/mvmtr/) but this may be changed
during the installation process. Each entry in
this file has an address key and a map value.
Please note that this file and the format of its
keys and values are still subject to change while
this utility is evolving. It may also be removed
entirely since its functionality can easily be pro-
vided via an mfl hook (e.g., $hook_rcpt_to). On
the other hand, interesting ideas and suggestions
are welcome!
Keys have the following formats:
user@domain --
matches an email address exactly.
user*@domain --
matches any email address with the specific
domain name where the local part begins with
the the string "user".
domain --
matches any email address in the specified
domain name.
.domain --
matches any email address in any subdomain
of the specified domain name.
When mvmtr looks up an incoming email address in
this database, it finds the most exact match that
it can. When it finds a match, it returns a result
depending on the map value that corresponds to the
entry. The result values are analagous to the mail
disposition values described elsewhere in this doc-
ument, and are as follows:
accept --
this address is valid and will be accepted
(subject to any further test that mvmtr per-
forms).
deny --
this address is known to be invalid and will
be rejected.
defer --
this address is probably valid, but not for
this particular server. (This corresponds
to the "known" mail disposition value.)
mvmtr will only accept this address if the
client is allowed to relay (e.g. the client
has AUTHed or has otherwise has relay per-
mission). Otherwise it returns a "known"
result, which is likely to produce a tempo-
rary deferral SMTP dialog result, causing
the sending system to retry at some later
time. A value of defer may be used on any
server that's not the primary MX destination
for that address. Deferring acceptance of
addresses on backup MX servers is way to
politely refuse email, and can help turn
away connections from malware that tries to
send to backup MX servers only.
pass --
this address will be accepted, and it may
also be eligible for a pass from some of the
other checks (connect, helo, etc), if that
check is configured to test for a pass (see
the description of various check controls).
The source for the address map file is typically
maintained in a text file, with each line contain-
ing the email address key and the map value sepa-
rated by a colon. You can then use the cdbgen
utility that's included with the mvmf kit to gener-
ate the cdb file from that source. Consider this
source file named "addrmap":
.example.net:deny
example.net:deny
mark@example.net:accept
mem@example.org:defer
example.org:deny
.example.org:deny
An address of "mark@example.net" will be accepted;
an address of "mem@example.org" will be accepted
only if it's OK to accept submissions from (i.e.
relay for) the client; any other addresses in
"example.net" and "example.org" and any of their
subdomains will be rejected. Any other address
(i.e., anything not mentioned in the address map
file) are unknown and will only be accepted on a
submission basis.
This may be compiled into "addrmap.cdb" by issuing
shell commands such as:
cdbgen -o addrmap.tmp addrmap
if [ -s addrmap.tmp ] ; then
ln -f addrmap.cdb addrmap.cdb-;
chmod a+r addrmap.tmp;
mv -f addrmap.tmp addrmap.cdb;
fi
It's important to know a couple more things about
how mvmtr looks up wildcard local names in the
address map file. Checking against wildcards in
this file has to be done iteratively. In many
environments, wildcards are only relevant when they
follow a particular separator character such as a
hyphen (e.g., user "mark" might be able to have any
address "mark-*" but may not have any address
"mark*"), so mvmtr may be compiled and installed so
that it only checks for wildcards at particular
points (such as after hyphens). Also, mvmtr will
never attempt to look up an address key where the
local part is just "*". If your intent is to have
a key such as "*@example.com" you must use just the
naked "example.com" instead.
CONTROL VALUES
Various control values may be set by mfl code using the
$control_ functions (see the mfl language documentation
for more info on those). Control values are typically set
when the mvmtr program is started, by invoking the $con-
trol_ functions directly in the startfile. Values may
also be adjusted as part of hook processing.
Control values are described below. Each description
begins with the name of the value and the type of the
value (for example an integer or a string) and then fol-
lows with a brief description of the control.
add_x_peer_info (integer) -- Whether to add an "X-Peer-
Info" header on the message. Default is 0.
X-Peer-Info is an MV-centric header, most people probably
won't want it. It simply inserts the local and remote
host information in a convenient format for downstream
parsing. (This will likely be phased out in favor of
using a hook.)
admin (integer) -- This is a control that is required by
MFL's control system itself. It is set to 1, since it's
expected that mvmtr is being run by an administrator.
Care must be taken (e.g. to revoke this) if you want to
invoke user-supplied scripts.
data_directory (string) -- specifies the data directory
for some mfl functions. Currently not really needed by
mvmtr, but provided for mfl's sake.
log_private_name (string) -- The name of a "private" log-
file. This is not relevant to mvmtr but the control has
to exist for the benefit of low-level logging functions.
(Mentioned here only for completeness.)
log_program_name (string) -- The name of the program as
reported when logging. Default is mvmtr.
mvmcas (integer) -- Whether or not to consult mvmcas, the
mail client assessment server. 0 disables the use of mvm-
cas, 1 enables it. Default is 0.
Only available if mvmcas support has been configured into
mvmtr at compile time.
mvmcas_host (string) -- The name of the host where the
mvmcas server is to be found. May include an optional
colon and port number. Default is "localhost:nnnn" where
nnnn is the default port number.
Only available if mvmcas support has been configured into
mvmtr at compile time.
pipe_allow (integer) -- whether mfl code is allowed to
open a pipe. Set to 1 by default, since mvmtr is expected
to be run by an admin.
prog_checkpassword (string) -- The path to the djb-style
checkpassword program that is used by AUTH commands. This
may be one or two program paths separated by spaces. The
first path is the checkpassword program to use. The
underlying checkpassword program may need to run as a
privileged program, and so the one specified here might
actually be a wrapper program that is only available to
whatever uid/gid mvmtr runs as. The second path, if
given, is to the program that the checkpassword program
takes as an argument when authentication is successful
(typical mvmtr use is /usr/bin/true or equivalent).
qmail_smtpd_compatibility (integer) -- Whether to enable
compatibility with qmail-smtpd's control files. 0 dis-
ables this compatibility, 1 enables it; default is 1. If
this is enabled, the qmail-smtpd startup files in qmail's
"control" directory are consulted and used in ways similar
to qmail-smtpd. Because this program is not qmail-smtpd,
use of the controls may not exactly mirror qmail-smtpd's
use of them. (See the QMAIL-COMPATIBILITY notes in the
mvmtr source area for discussion.) However, this setting
will allow mvmtr to function as a drop-in replacement for
a stock qmail-smtpd.
Only available if qmail-smtpd compatibility has been con-
figured into mvmtr at compile time.
smtp_server_autoblock_enable (integer) -- Whether to honor
autoblocks (e.g. from mvmcas). Default is 1 (enabled).
smtp_server_badcmd_max (integer) -- How many bad (unknown)
SMTP commands to tolerate before closing the session.
Default is 3.
smtp_server_badrcpt_delay (integer) -- Number of seconds
to defer a response after a bad RCPT-TO has been received.
This is an attempt to delay bad senders, but probably
shouldn't be used if an assessment server (e.g. mvmcas) is
being consulted (as that will have a better, long-term
feedback process). Default is 5 (seconds).
smtp_server_badrcpt_max (integer) -- Maximum number of
bad/deferred RCPT-TO addresses allowed in a session before
we declare this a bad session. If this maximum is
reached, further RCPT-TO commands will be given a negative
response, and the mail will be refused at DATA time. Or,
if strict SMTP sessions adherence is turned off (see the
smtp_server_strict_sessions control) the connection may be
dropped immediately. Default is 2.
smtp_server_connect_check (string) -- A list of checks to
perform when a connection begins. This is an annotated
checklist (see the ANNOTATED CHECKLIST section) that spec-
ifies the checks to perform, in order. An "accept" check-
list result will cause the dialog to proceed as normal. A
"reject" checklist return will cause mvmtr to respond to
the client with a 421 "go-away" greeting and then discon-
nect. Any other checklist result will cause the session
to be dropped gracelessly (without notice).
The default value of this control is NULL (no checks).
smtp_server_greet_delay (integer) -- How many seconds the
SMTP server will delay after receiving a connection from
an unknown client before issuing the initial greeting. If
any commands are received prior to issuing the greeting,
the connection will be considered suspicious and the con-
versation will not be accepted. (Legitimate SMTP clients
will wait for a greeting before beginning the SMTP dialog;
malware often will not). If the client has otherwise been
identified as a local client, this delay may be sup-
pressed. When you use a greeting delay, you should be
aware of the negative effect that larger values will have
on your (and the senders') throughput. An intelligent
assessment server (such as mvmcas) will be able to adjust
this value dynamically on a per-sender basis. Default is
5 (which is only somewhat effective).
If the use of an mvmcas server is enabled, information
from that server will set the pre-greeting delay on a per-
client basis.
smtp_server_greet_delay_max (integer) -- The maximum smtp
server greet delay, regardless of any other setting or
input (e.g. from mvmcas). Default is 60.
smtp_server_greeting (string) -- Additional SMTP greeting
text. mvmtr will always emit a first standard line of
greeting; if any additional greeting text is supplied, it
follows that standard first line, and is itself followed
by another standard closing line. mvmtr adds its own text
around the additional greeting because RFC2821 requires a
particular format of the first line, and in order to deal
with potential client problems many clients can not deal
with a multi-line greeting without particular formatting
in either the first or last line. The additional greeting
text may itself be multi-line.
smtp_server_greylisting (integer) -- Whether to enable
greylisting (0 = off, 1 or 2 = on). Greylisting is accom-
plished by consulting an outside agent (e.g. mvmcas); it
is useful to disable greylisting for a good amount of time
(days or weeks) in order to train the greylisting
database. The greylisting used by mvmtr and mvmcas is a
degenerate form that only pays attention to the IP address
and not to the specific email addresses used. Because
mvmcas makes other assessments, this form of greylisting
has proven to be quite effective.
When greylisting is enabled with a value of 1, mvmtr will
honor the smtp_server_strict_sessions control to decide
whether to keep the session open. Enabling with a value
of 2 will cause mvmtr to issue a greeting with a 421 code
and exit immediately when greylisted.
smtp_server_helo_check (string) -- A list of checks to
perform when a HELO/EHLO command has been received. This
is an annotated checklist (see the ANNOTATED CHECKLIST
section) that specifies checks to perform in order. An
"accept" or "dunno" checklist result will cause a positive
response to the command, and the dialog to continue; a
"reject" result will cause the HELO name to be rejected
with an appropriate SMTP reply, and the dialog to con-
tinue; other results will function the same as "reject"
but may be handled specially in future releases. See also
the controls smtp_server_strict_sessions and
smtp_server_ss_helo.
The default value of this control is "helo-syntax helo-
hook helo-me".
smtp_server_localip_host (string) -- The hostname that is
substituted for any bracketed IP address in a rcpt-to
address, when the IP address is one that belongs to the
local host (is on an "up" interface on the local host).
smtp_server_log_commands (integer) -- If non-zero, mvmtr
will log all of the commands received from the client.
This was originally a debugging instrument, but as of this
writing most commands are logged by default anyway.
smtp_server_mail_check (string) -- A list of checks to
perform when a MAIL FROM command has been received. This
is an annotated checklist (see the ANNOTATED CHECKLIST
section) that specifies checks to perform in order. An
"accept" or "dunno" checklist result will cause a positive
response to the command, and the dialog to continue; a
"reject" result will cause the MAIL FROM name to be
rejected with an appropriate SMTP reply, and the dialog to
continue; other results will function the same as "reject"
but may be handled specially in future releases. Also see
the smtp_server_strict_sessions control.
The default value of this control is "mail-hook". A rea-
sonable alternative might be something like: "
Pc,A:
r0:mail-dns
mail-hook
"
Note that the a null MAIL FROM address, i.e. <>, will
always be accepted and is not subject to MAIL FROM checks.
smtp_server_msgsize_max (integer) -- The maximum message
size, in bytes, that we will accept, or zero for no limit.
By default this is zero; you should probably set it to
something sane.
smtp_server_rcpt_check (string) -- A list of checks to
perform when a RCPT TO command has been received. This is
an annotated checklist (see the ANNOTATED CHECKLIST sec-
tion) that specifies checks to perform in order. An
"accept" or "dunno" checklist result will cause a positive
response to the command, and the dialog to continue; a
"reject" result will cause the MAIL FROM name to be
rejected with a reject SMTP reply (5xx), and the dialog to
continue; a "known" (aka "defer") result will cause the
MAIL FROM name to be given a deferral SMTP response (4xx),
and the dialog to continue; other results will function
the same as "reject" but may be handled specially in
future releases.
The default value of this control is "rcpt-hook". It is
likely that you'll want to have something more elaborate
instead.
smtp_server_reply_[cccc]_[ssss] (string) --
This is a set of controls that provide some guidance about
how SMTP replies are formatted for certain commands in
certain situations. The actual control names are formed
by replacing [cccc] with the lowercased context name and
by replacing [ssss] with a string representing the reply
severity. (The context name is usually the name of the
command being replied to.)
Valid values for [cccc] are data (for "DATA" command),
mail (for "MAIL FROM" command), and rcpt (for "RCPT TO"
command). A special value of grt is used to tailor the
initial greeting message when the session is rejected, in
some circumstances.
Valid values for [ssss] are hard (for a 5xx return) and
soft (for a 4xx return).
The relevant control value is consulted whenever mvmtr
issues an SMTP reply that is a rejection and that uses the
generic customizable format. See the CUSTOMIZABLE REJEC-
TION REPLIES section for a bit of a discussion about how
these are used.
smtp_server_ss_helo (integer) -- An override for the
smtp_server_strict_sessions control for the HELO command.
If set to -1, HELO processing will adhere to the
smtp_server_strict_sessions control. Otherwise this con-
trol's value will apply to HELO processing. Often it is
practical to drop the connection after identifying a bad
HELO, rather than continuing until the client quits as per
RFCs. Default is -1.
smtp_server_strict_sessions (integer) -- Enable or disable
strict SMTP session adherence. When enabled, once a
client has been greeted, the sessions will not be termi-
nated until the client ends (via QUIT or disconnect).
This is required by RFCs but is one of the many require-
ments that is often set aside due to today's pragmatism.
Some controls or other parameters might terminate a ses-
sion when this is disabled; when it is enabled, the effect
of those controls will be delayed appropriately. Default
is 1.
smtp_server_timeout (integer) -- General smtpd server
timeout. The maximum time, in seconds, to wait for data
from the client for general command states (i.e., not cov-
ered by another timeout). Default is 300 (seconds).
smtp_server_timeout_helo (integer) -- How many seconds the
SMTP server will wait for a HELO or EHLO command after
issuing a greeting. If this number of seconds elapses
before the HELO/EHLO is received, the connection will be
closed. Default is 30 (seconds).
CHECKS
mvmtr supports a number of built-in checks that may be
initiated at various times in the smtp dialog. The checks
may be specified as part of an annotated checklist (see
that section), or they may be invoked from an MFL hook
(see the section on hooks). Each check has a name,
reflecting what it does, and it makes a decision about
what to do with a particular SMTP dialog element or param-
eter. All checks are defined to take an optional argu-
ment, however most checks are self-contained and ignore
(do nothing with) any argument given to them.
Each check returns a mail disposition value as described
in the HOOKS section (should probably be described else-
where). Typically a check will return either "accept" or
"reject" (with the obvious meanings); in some contexts
some other returns may be valid. A check may also return
"dunno" to make no judgment. In the descriptions below,
some checks are described as "passing" or "failing" --
"pass" generally means returning "accept" or "dunno" and
"fail" generally means returning a "reject".
Each check, when returning a non-pass result (neither
"accept" nor "dunno"), will also "suggest" a score. This
is a numerical value that can be used in (say) accumulat-
ing a total before deciding to give up on the client. The
suggested score can be overridden in various ways (via an
annotation in an annotated checklist, or by MFL code which
invokes the check).
Checks are:
client-generic -- Tests whether the client is judged to be
coming from generic IP space. (See the discussion near
the presentation of the $hook_generic_ip hook for more.)
Any optional argument is ignored.
client-hook -- Attempts to invokes the MFL $hook_client
function, which can be supplied by the administrator. See
the HOOKS section for a description of how this function
is called. Any optional argument will be taken as an
alternative name for this hook.
helo-dns -- Passes if the HELO name resolves to an A entry
in the DNS; fails otherwise.
helo-dnsclient -- Passes if the HELO name resolves to an A
entry in the DNS which matches the IP address of the con-
necting client; fails otherwise.
helo-generic -- Tests whether the HELO name is judged to
indicate a name associated with generic IP space, taking
the client's IP address into account as well. (See the
discussion near the presentation of the $hook_generic_ip
hook for more.)
helo-hook -- Invokes the MFL hook $hook_helo if it has
been defined. See the HOOKS section for more info on this
and other hooks. Any optional argument will be taken as
an alternative name for this hook.
helo-me -- Looks at the HELO name to see if it is an
invalid impersonation of the receiving server (i.e., me).
This is not an exhaustive look, but it will catch HELO
names that look like one of the local IP addresses (with-
out the required square brackets).
helo-syntax -- Does a strict syntax check on the HELO
name. This is a syntax check only, making sure that the
HELO name contains valid characters put together in valid
ways. This test is highly recommended.
mail-dns -- Passes if the domain name in the MAIL FROM
address resolves to an A or MX record; fails otherwise.
Note that failure only occurs on a definitive DNS response
indicating lack of DNS record(s); soft failures will not
cause rejection.
mail-hook -- Invokes the MFL hook $hook_mail_from if it
has been defined. See the HOOKS section for more info on
this and other hooks. Any optional argument will be taken
as an alternative name for this hook.
mail-qmail -- Checks the MAIL FROM address in a way com-
patible with qmail's check, e.g. its badmailfrom check, as
described in the QMAIL-COMPATIBILITY notes provided with
the mvmtr source kit.
rcpt-addrmap -- Consults the address map file for this
RCPT TO address. The address map handling is described
elsewhere in this manpage.
rcpt-hook -- Invokes the MFL hook $hook_rcpt_to if it has
been defined. See the HOOKS section for more info on this
and other hooks. Any optional argument will be taken as
an alternative name for this hook.
rcpt-qmail -- Checks the RCPT TO address in a way compati-
ble with qmail's check, e.g. its rcpthosts and mor-
ercpthosts check, as described in the QMAIL-COMPATIBILITY
notes provided with the mvmtr source kit.
Beware that many strict HELO checks are infeasible as of
this writing, since there are so many poorly configured
email clients out in the world.
ANNOTATED CHECKLISTS
An annotated checklist is simply a string that is a list
of named checks to be done, along with (you guessed it)
some annotations that help to control the interpretation
and flow of the checks. Annotated checklists are speci-
fied via certain string controls that are referred to at
certain points in the SMTP dialog. (All of these controls
and where they are referenced have been described above.)
This facility provides a middle ground between having
every operational decision hard-coded in the mvmtr program
and having you (the administrator) write these decisions
in terms of MFL hooks. 80% (or so) of what most everyone
might want in an SMTP server ought to be provided via
built-in facilities, but you might want have some degree
of control over them. The other 20% may vary widely from
administrator to administrator, and these are the things
that are better done through external MFL code.
The annotated checklist is simply a list of annotated
checks separated by whitespace (spaces, tabs, newlines).
Each annotated check is the name of check (as described in
the CHECKS section), optionally preceded by a set of anno-
tations and a colon, and optionally followed by a colon
and a tail part. The tail part (if given) is used as an
argument to the check (but most checks don't take argu-
ments). The set of annotations is a comma- or slash- sep-
arated list of character notes, each of which may have an
argument. The check name may be left blank, in order to
process annotations only.
Each check is performed in turn, ignoring "accept"
results, until one of them returns a hard result (neither
a "soft" return nor a "dunno"). "Accept" results are
ignored so that subsequent checks can be processed, as
that's usually what's wanted; however, the 'y' note (see
below) can be used to force an "accept" to be taken. When
a hard result is given, the checklist processing stops and
this return is the result of the checklist. (Some annota-
tions may cause hard returns to be ignored). If the list
ends before a hard result is obtained, any soft result
will be turned into a hard result and that will be
returned. Otherwise the entire list returns "dunno."
These are the note characters that can be used in a set of
annotations:
# -- skip this check. This provides a way of commenting
out a check.
A -- skip all remaining checks if client is authenticated.
a -- skip this check if client is authenticated.
I -- skip all remaining checks if client is allowed to
relay (i.e., is considered "internal).
i -- skip this check if the client is allowed to relay.
P[t..] -- skip all remaining checks if there is a pass of
type t. The pass types are 'c' for client (client has a
pass, e.g. from mvmcas), and 'r' for recipient (recipient
has a pass, e.g. from addrmap).
p[t..] -- skip this check if there is a pass of type 't'.
Types are the same as for the 'P' note character.
r[nn] -- any "reject" return, instead of being used out-
right, accumulates a score. The 'r' may be followed by a
score value, otherwise the check's suggested score will be
used. A value of 0 makes this a soft check. If there is
no 'r' annotation, a reject value return will be used
absolutely.
s -- set the maximum score value. If the cumulative score
gets this high or higher, stop processing the namelist and
return a reject. This value is sticky across the rest of
the namelist (and may later be changed via another
y -- any yes ("accept") return is a hard accept: the
namelist ends and the accept is returned. Otherwise, the
accept return is advisory only and is treated as a
"dunno".
Consider this setting for the "smtp_server_rcpt_check"
control:
@define RCPT_CHECKS "
Prc,a:mail-dns
y:rcpt-addrmap
rcpt-hook
"
$control_string_set( "smtp_server_rcpt_check", RCPT_CHECKS );
This says that whenever an RCPT TO command is taken, the
MAIL FROM argument that was collected earlier will be
tested for legitimate DNS unless either the recipient or
the client has a pass or the client has been authenti-
cated; the RCPT TO address will be tested via the address
map and an "accept" from the address map is considered
absolute. The RCPT TO address is potentially tested via
any $hook_rcpt_to MFL hook.
CUSTOMIZABLE REJECTION REPLIES
For some SMTP commands where deliveries or transactions
can be rejected, mvmtr uses a standard reply format for
such rejections that can be customized via certain control
values, as described earlier for the
smtp_server_reply_[cccc]_[ssss] controls. As mentioned
there, the affected SMTP commands are "DATA", "MAIL FROM",
and "RCPT TO". While these replies aren't completely cus-
tomizable, this mechanism provides a way to tailor them
somewhat. (Later versions of mvmtr may indeed carry this
further).
The standard rejection message format approximately fol-
lows this template:
nnn [brief] [extended] [built-in]
where
"nnn" is the standard SMTP reply code that begins the
line; this may include a continuation indicator
and/or an extended reply code.
"brief"
is a brief explanation of the rejection, provided
by mvmtr. This brief string is only output if
there is an extended string or if there is no
built-in string.
"extended"
is optional extended reply information dictated by
the contents of the relevant control (i.e., the
appropriate smtp_server_reply_[cccc]_[ssss] con-
trol). This control value may be encoded to
include certain variable information; see below.
"built-in"
is any detailed message provided internally by
mvmtr.
To find the optional extended reply string, an appropriate
control value is consulted. As detailed earlier, the name
of the control is constructed according to the template
smtp_server_reply_[cccc]_[ssss] with [cccc] being replaced
with a string representing the SMTP command involved, and
[ssss] replaced by a string representing the severity of
the rejection (either "hard" or "soft"). The value of
this control is then used as the optional extended reply
component. (A blank string value is treated the same as a
missing value.)
When supplied, the value is subject to interpretation.
The value must start with zero or more flag characters,
ending with a comma. There is only one defined flag char-
acter at present: 'l' (the letter 'l'), which will cause
the extended reply string to be followed by a line-item
list of the keywords and detail text for each rejection
reason that has been given for the rejection. (These key-
word/text pairs are provided via the mechanism of
"RISET"s, aka result/reply information sets; see the
RISETs section.) The text following the comma is then
given as part of the reply, with some interpretation.
Two-character sequences beginning with a percent sign are
given special treatment:
%% results in a single percent-sign;
%k will be replaced by a list of the keywords associ-
ated with each reason that has been accumulated for
this rejection. The list will be comma-separated.
This is intented to be suitable for interpretation
by a web page or by a human who might be receiving
a report of this message.
%i is replaced by the IP address of the client. This
is likely to be useful when a sender reports an
error sending mail.
Let's say, for example, that a series of checks is done at
the time the "RCPT TO" command is processed, and that the
command is hard-rejected for two reasons: there is no DNS
record associated with the domain given in the "MAIL FROM"
command (and thus the mail can not be replied to), and the
IP address has been listed on a DNSBL called the "xyz".
The relevant control for the extended part of this
response is smtp_server_reply_rcpt_hard. If it is defined
like this (i.e. in the mvmtr.mfl startup file):
$control_string_set( "smtp_server_reply_rcpt_hard",
"l,ip=%i reason[s]=%k" );
then the client, connecting from IP address 10.0.1.2,
would likely see a reply similar to this:
550-Recipient rejected -- ip=10.0.1.2 reason[s]=mail-dns,xyz
550- mail-dns -- MAIL FROM name has no DNS record
550 xyz -- Your IP address is on the xyz DNSBL
The first line is enough for a human at the receiving site
to interpret. Instead of simply a "reason[s]" string,
this might be a pointer to a website that is capable of
explaining the rejection and perhaps doing something about
it.
RISETs
A lot of the decisions that mvmtr makes are the result of
a number of inputs. This is clear from the discussions of
annotated checklists and from descriptions of some of
mvmtr's processes. This gives a lot of flexibility to the
decision making, but also creates some problems in regards
to what to say about those decisions. mvmtr addresses
this with the option of associating a set of information
with each of the factors that contribute to a decision.
Each is known as reply/result information, or just RI, and
the set of these RI going into a decision is an RISET.
Each RI can be either for logging or for replying to the
client, and there will usually be both kinds present in an
RISET. Once a decision is acted on (e.g., an SMTP command
has completed), the log items in an RISET may be discarded
or they may be sent to the log. Similarly the reply items
may be used in the SMTP reply to the client (see the sec-
tion on CUSTOMIZABLE REJECTION REPLIES) or ignored.
Each RI consists of at least the following:
keyword
This is a short string that can be used to uniquely
identify the contributing reason. When logged, it
is enclosed in square brackets for easy analysis.
When given as part of a reply, it can be used as
part of a keyword string (e.g. to give to a web
URL), and it can also be used as part of a line-
item list of reasons.
disposition
Used mainly (exclusively?) for logging, this is a
code that indicates the nature of the input. Typi-
cally it is either a plus sign (for acceptance) or
a minus sign (for rejection) but can also be a
"?nn" sequence which represents a contribution of
nn to a score. This disposition can be adjusted
while the RI is queued and before it is used, e.g.
if a rejection is changed to a score.
detail This is any detail text associated with the RI. It
is used both in logging and in presenting a line-
item list of reasons as part of an SMTP reply.
HOOKS
At certain points in its execution, mvmtr may invoke
specifically-named mfl functions in order to give user or
admin options at these control points. In most cases, the
hook function is invoked via one of the checks in an anno-
tated checklist -- e.g., you may define the
"smtp_server_mail_check" control to include the "mail-
hook" check, and this will likely result in calling the
"$hook_mail_from" hook as part of running checks at MAIL
FROM time.
In a small number of other cases, the hook is simply
called at a defined point in mvmtr's execution if the
appropriately-named MFL function exists (i.e., if you have
defined it in the startup file or if it can be found in
the hook search path).
Mail Disposition Values
Some hook functions deal with a mail disposition value
(also known as an acceptance value). This is a string,
one of the following (most have fairly obvious meanings):
dunno -- no decision.
accept -- accept.
reject -- reject.
pass -- accept, and also exempt the sender from some
checks.
known -- address is known, but neither accepted nor
rejected. This value is sometimes interpreted as a defer-
ral request.
unknown -- address is unknown (probably foreign).
error -- some error has occured.
Often, the mail disposition value can be preceded with a
tilde character (~) to indicate a tentative decision that
can be overridden by some later step that chooses to.
hook dialog reply
Many hooks are documented as returning a "dialog reply".
This means that the function should be defined as return-
ing a string, and the string that is returned should match
this form:
mdv[:keyword[:detail]]
Here, mdv is a mail disposition value, as previously dis-
cussed. keyword, if given, is a keyword to associate with
this reply, and detail, if given, is a line of text that
gives more detail about that keyword. In most (all?)
cases, the keyword and detail elements are only relevant
for rejections.
If keyword is given without detail, the keyword is added
as a log item to the current result information set
(RISET) with some default text.
If keyword and detail are both provided, they are added as
both log item and return item to the current result infor-
mation set.
Hooks
The hooks are:
$hook_client
is called via the "client-hook" check function
(e.g. in an annotated checklist) to make a judge-
ment about the connecting client. This hook is
defined as
string $hook_client( string mdv, string ip ) { ... };
mdv is any mail disposition value already deter-
mined (which the hook can choose to take into
account). ip is the stringized IP address
(a.b.c.d) to check. This may be passed as 0.0.0.0
or 255.255.255.255 if unknown.
This function is expected to return a dialog return
string, typically one of "dunno", "accept", or
"reject".
An example:
string $hook_client( string mdv, string ip ) {
// Reject if it appears on some DNSBL. Better is to score
// multiple DNSBLs, as you might find in some examples
// outside this man page.
if ( sieve { dnsbl :ip [ip] "spamcop" "std" } )
return ( "reject:spamcop" );
return ( mdv );
};
$hook_data
is called after mvmtr receives an SMTP "DATA" com-
mand from the client. This hook is defined as
string $hook_data( string mdv ) { ... };
mdv is any mail disposition value already deter-
mined (which the hook can choose to take into
account). This function is expected to return a
dialog return string. The only legitimate mdv
returns are "dunno", "accept", and "reject".
An example:
string $hook_data( string mdv ) {
if ( sieve { not exists "To" } )
return ( "reject:no-to" ); // We reject mail without "to"
// Send the message through clamav. Assumes that the cusp
// has been defined, and that string variables s and *sP
// and constant NULL have been declared.
s = $cuspu_message( "clamdif" );
if ( s != "" ) {
sP = $str_find_token_delimited( s, "", " " );
sP = $str_find_token_delimited( s, "", " " );
if ( sP != NULL )
return ( (string)"reject:clamav:detected " + *sP );
}
return ( mdv );
};
$hook_generic_ip
may be called to help determine whether an IP
address looks generically assigned. This hook is
defined as
string $hook_generic_ip( string mdv, string ip, string hname ) { ... };
mdv is any mail disposition value already deter-
mined (which the hook can choose to take into
account). ip is the stringized IP address
(a.b.c.d) to check. This may be passed as 0.0.0.0
or 255.255.255.255 if unknown. hname is the host-
name to check. In some cases this function might
be called several times for a given IP address,
e.g. if there are multiple PTR records for the IP
address.
This function is expected to return a dialog return
string. The only legitimate mdv returns are
"dunno", "accept", "reject", and "pass".
An example:
string $hook_generic_ip( string mdv, string ip, string hname ) {
// Override any bad judgement about this IP
if ( ip == "127.0.0.1" )
return ( "accept" );
// Cancel any bad judgement about names containing ".staticip."
if ( hname =?^ "*.staticip.*" )
return ( "dunno" );
// Accept the already-determined disposition
return ( mdv );
};
Before calling this hook, mvmtr makes an internal assess-
ment about whether the IP address looks generic. It makes
this assessment based on whether the reverse DNS name(s)
seem to declare the IP address as being generically
assigned. Primarily, it checks to see whether the name
contains 3 or 4 of the adjacent IP address octets in deci-
mal or hex representation, separated by zero or more other
characters, either in forward or reverse order. If this
sort of pattern is found, it then applies some tests to
try to disprove the assessment by looking for a few key
strings (such as "static") that will not ordinarily appear
in generically assigned names.
Note that this initial assessment may be overly broad for
most environments. This hook may be used to further dis-
prove a positive initial judgement. The hook can also
completely disregard the initial internal assessment and
make one of its own, etc.
Note also that if an IP address has multiple reverse names
in the DNS, each name is tested until one is declared not
to be generic (or until all names have been tested). This
means that a non-generic assessment always wins.
$hook_helo
is called via the "helo-hook" check (e.g. appearing
in an annotated checklist), in order to make some
judgement about the HELO/EHLO name that the client
has given to mvmtr. This hook is defined as
string $hook_helo( string mdv, string heloname ) { ... };
mdv is any mail disposition value already deter-
mined (which the hook can choose to take into
account). heloname is the helo string given in the
"HELO" command. This function is expect to return
a dialog return string. The only legitimate mdv
returns are "dunno", "accept", and "reject".
An example:
string $hook_helo( string mdv, string heloname ) {
if ( heloname ==^ "friend" )
return ( (string)"reject:spamsign:
HELO (" + heloname + ") is a spam sign." );
if ( $cdbu_get_string( "bad-helo.cdb", heloname ) != 0 )
return ( "reject:bad-helo.cdb" );
return ( mdv );
};
$hook_mail_from
is called via the "mail-hook" check (e.g. appearing
in an annotated checklist), in order to make some
judgement about the address that the client has
given to mvmtr in the MAIL FROM command. This hook
is defined as
string $hook_mail_from( string mdv, string rpath ) { ... };
mdv is any mail disposition value already deter-
mined (which the hook can choose to take into
account). rpath is the email address given in the
"MAIL FROM" command.
Some firm decisions made by this hook may still be over-
ridden. For example, this hook may not refuse a null MAIL
FROM address. This function is expect to return a dialog
return string. The only legitimate mdv returns are
"dunno", "accept", and "reject".
An example:
string $hook_mail_from( string mdv, string rpath ) {
if ( rpath =?^ "*@optinrealbig.com" ) {
return ( "reject:blocked:sender domain is blocked" );
return ( mdv );
};
$hook_rcpt_to
is called via the "rcpt-hook" check (e.g. appearing
in an annotated checklist), in order to make some
judgement about the latest address that the client
has given to mvmtr in the RCPT TO command. This
hook is defined as
string $hook_rcpt_to( string mdv, string addr ) { ... };
mdv is any already-determined mail disposition
value value. addr is the email address given in
the "RCPT TO" command. This function is expect to
return a dialog return string. The only legitimate
mdv returns are "dunno", "accept", and "reject".
The "known" disposition value will be interpreted
as a request to defer the RCPT TO; "unknown" indi-
cates a relay attempt that will only be honored if
the client is OKed for relaying.
An example:
string $hook_rcpt_to( string mdv, string addr ) {
if ( addr =?^ "nobody@*" ) {
return ( "reject:silly" );
return ( mdv );
};
Your $hook_rcpt_to hook should be sure to accept the naked
"postmaster" address, per RFC2821, unless you specifically
want to violate that rule on your own say-so. Internally,
mvmtr will accept "postmaster" if the hook hasn't made a
decision; other policy hooks (such as deferred HELO name
checks, etc) may still be able to override this decision.
In this hook you might also want to make note of certain
addresses that shouldn't be subject to later filtering.
BUILT-IN MFL FUNCTIONS
mvmtr defines a number of built-in functions for use by
MFL code (e.g. in for use in hooks). These are described
in this section.
$mvmtr_log
Writes an entry to the mvmtr log. Each log entry
has a number of components, including a category
(with disposition), a keyword, and some detail
text. The category string represents the general
area of thing being logged, e.g. "RCPT" along with
some disposition indication such as a "+" for
acceptance or "-" for rejection. Ordinarily the
category and disposition are separate, but for this
function they are combined for simplicity.
The function is defined as
BOOL $mvmtr_log( string cat, string keyword, string detail )
and might be used like this:
$mvmtr_log( "INFO", "startup", "mvmtr starting up" );
$smtpd_riset_add
Adds an RI to the current RISET (see the RISET sec-
tion). The function is defined:
BOOL $smtpd_riset_add( string type, string cat, string catdisp,
string kwd, string detail)
type is the RI type, either "log" or "reply". cat
is the log category string for use with "log" type
RIs. This may be passed as blank to use an appro-
priate default. catdisp is a disposition string
somewhat indicative of the action taken; this is
often "-" or "+". kwd is the RI keyword, and
detail is the RI detail.
For an example, let's say you have a client-hook
that is called at RCPT-TO time and it checks to see
if the client address is listed on a mythical DNSBL
which we'll call the "zbl". It might contain this
fragment:
if ( $dns_query( $ip_rev(ip) + ".zbl.example.org", "a" ) != 0 ) {
$smtpd_riset_add( "reply", "", "", "zbl", "Your IP address is on the zbl" );
$smtpd_riset_add( "log", "", "-", "zbl", "IP is on the ZBL" );
return ( "reject" );
}
$smtpd_score1_set
This sets the "score1" value. Each check that con-
tributes to an annotated namelist set can declare a
score value, which the namelist processing can take
into account. This score value is called the
"score1" value since it is associated with that
single check and not with the entire namelist. If
you have an MFL hook that is returning a reject,
you might want to have it declare the score1 value.
This function is defined as:
BOOL $smtpd_score1_set( int value )
where value is the value to set.
FILES
/usr/local/sys/mvmf/mvmtr/mvmtr.mfl is the default start-
file.
/usr/local/sys/mvmf/mvmtr/addrmap.cdb is the address map
file.
SEE ALSO
mfl -- the mfl language description.
http://www.mvmf.org/ -- the official web site.
CREDITS TO
M. Mallett (mem@mv.mv.com) 2003,2004,2005,2006,2007
BUGS
You tell me..