2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-29 13:18:12 +00:00

snapshot-19990509

This commit is contained in:
Wietse Venema 1999-05-09 00:00:00 -05:00
parent 5d89d7ae94
commit 138a7cbb80
20 changed files with 786 additions and 496 deletions

View File

@ -2745,6 +2745,16 @@ Apologies for any names omitted.
= canonical, virtual, alias, forward, include" to restore
previous behavior.
Feature: command_expansion_filter and forward_expansion_filter
configuration parameters that control what characters may
appear in $name expansions of mailbox_command and forward_path.
Feature: forward_expansion_filter configuration parameter
that controls what characters may appear in $name expansions
of forward_path.
19990509
Feature: command_expansion_filter to control what characters
may appearin message attributes that are exported via
environment variables.
Cleanup: SMTPD reject messages are more informative, and
more complete sender/recipient information is logged for
the local sysadmin.

View File

@ -1,4 +1,4 @@
Incompatible changes with snapshot-19990504:
Incompatible changes with snapshot-19990509:
===========================================
- The Postfix local delivery agent no longer automatically propagates
@ -6,39 +6,41 @@ the address extension to aliases/include/forward addresses. Specify
"propagate_unmatched_extensions = canonical, virtual, alias, forward,
include" to restore the old behavior.
- The luser_relay syntax has changed. You can specify one address,
and it is subjected to $user, etc. expansions. See conf/main.cf.
- The mailbox_command parameter is now subjected to $name expansion
(see below). This means that you can no longer use shell variables
in mailbox_command, or that you have to use $$ instead of $.
- The luser_relay syntax has changed. You can specify one address;
it is subjected to $user, etc. expansions. See conf/main.cf.
- File system reorganization: daemon executables are in the libexec
subdirectory, command executables in the bin subdirectory. The
INSTALL instructions now recommend installing daemons and commands
into separate directories.
Major changes with snapshot-19990504:
Major changes with snapshot-19990509:
=====================================
In addition to several little bugfixes, none related to security,
lots of internal code cleanup, lots of new functionality, and lots
of Solaris workarounds.
- New USER, EXTENSION and DOMAIN environment variables for delivery
to command by the local delivery agent. As you might expect, the
information is censored. The list of acceptable characters is
specified with the command_expansion_filter configuration parameter.
Unacceptable characters are replaced by underscores.
- Specify "forward_path = /var/forward/$user" to avoid looking up
.forward files in user home directories. The default value is
$home/.forward$recipient_delimiter$extension, $home/.forward.
Initial code by Philip A. Prindeville, Mirapoint, Inc., USA.
- Conditional $name expansion in forward_path, mailbox_command,
and luser_relay. Available names are: $user (bare user name) $shell
(user login shell), $home (user home directory), $recipient
(everything to the left of @), $extension (optional address
extension), $domain (everything to the right of @), and
$recipient_delimiter. A simple $name expands as usual. ${name?value}
expands to value when $name is defined. ${name:value} expands to
value when $name is not defined. With ${name?value} and ${name:value},
the value is subject to another iteration of $name expansion.
- Conditional $name expansion in forward_path and luser_relay.
Available names are: $user (bare user name) $shell (user login
shell), $home (user home directory), $recipient (everything to the
left of @), $extension (optional address extension), $domain
(everything to the right of @), and $recipient_delimiter. A simple
$name expands as usual. ${name?value} expands to value when $name
is defined. ${name:value} expands to value when $name is not
defined. With ${name?value} and ${name:value}, the value is subject
to another iteration of $name expansion.
- POSIX regular expression support, enabled by default on 4.4BSD,
LINUX, HP-UX, and Solaris 2.5 and later. See conf/sample-regexp.cf.

View File

@ -63,7 +63,7 @@ luser_relay =
mail_name = Postfix
mail_owner = postfix
mail_spool_directory = /var/mail
mail_version = Snapshot-19990508
mail_version = Snapshot-19990509
mailbox_command =
mailbox_transport =
maps_rbl_domains = rbl.maps.vix.com

View File

@ -340,13 +340,13 @@ extern char *var_rcpt_delim;
#define DEF_CMD_EXP_FILTER "1234567890!@%-_=+:,./\
abcdefghijklmnopqrstuvwxyz\
ABCDEFGHIJKLMNOPQRSTUVWXYZ"
extern char *var_cmd_exp_filter;;
extern char *var_cmd_exp_filter;
#define VAR_FWD_EXP_FILTER "forward_expansion_filter"
#define DEF_FWD_EXP_FILTER "1234567890!@%-_=+:,./\
abcdefghijklmnopqrstuvwxyz\
ABCDEFGHIJKLMNOPQRSTUVWXYZ"
extern char *var_fwd_exp_filter;;
extern char *var_fwd_exp_filter;
#define VAR_RCPT_FDELIM "recipient_feature_delimiter"
#define DEF_RCPT_FDELIM ""

View File

@ -15,7 +15,7 @@
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "Snapshot-19990508"
#define DEF_MAIL_VERSION "Snapshot-19990509"
extern char *var_mail_version;
/* LICENSE

View File

@ -395,9 +395,41 @@ and <b>/usr/lib/Mail.rc</b>).
With mailing lists, <b>Delivered-To:</b> can get in the way when
the list exploder uses a "secret" alias that should not be shown
in outbound mail. In order to tackle this, look up the <b>FEATURE
CONTROL</b> section in the documentation of the <a
href="local.8.html">local</a> delivery agent.
in outbound mail. The recommended solution is to use a regular
expression-based filter at the SMTP port:
<p>
<dl>
<dt><b>/etc/postfix/main.cf:</b>
<dl>
<dt><tt>smtpd_recipients = ... regexp:/etc/postfix/access_regexp ...</tt>
<dt><tt>smtpd_recipients = ... pcre:/etc/postfix/access_regexp ...</tt>
</dl>
<p>
<dt><b>/etc/postfix/access_regexp:</b>
<dl>
<dt><tt>/^(.*)-outgoing@(.*)/ 554 Use $1@$2 instead</tt>
</dl>
</dl>
<p>
POSIX regular expression support (regexp) is enabled by default on
modern UNIX systems. Perl-compatible regular expression support
(pcre) is optional; see the PCRE_README file in the top-level
Postfix source directory.
<p>

View File

@ -76,8 +76,9 @@ is no direct path from the network to the security-sensitive local
delivery programs - an intruder has to break through several other
programs first. Postfix does not even trust the contents of its
own queue files, or the contents of its own IPC messages. Postfix
avoids placing sender-provided information into shell environment
variables. Last but not least, no Postfix program is <i>set-uid</i>.
filters sender-provided information before exporting it via
environment variables. Last but not least, no Postfix program is
<i>set-uid</i>.
</ul>

View File

@ -111,20 +111,20 @@ LOCAL(8) LOCAL(8)
ter. The command executes with the privileges of the
recipient user (exception: in case of delivery as root,
the command executes with the privileges of
<b>default</b><i>_</i><b>privs</b>). The command is subject to interpolation
of <b>$user</b> (recipient username), <b>$home</b> (recipient home
directory), <b>$shell</b> (recipient shell), <b>$recipient</b> (complete
recipient address), <b>$extension</b> (recipient address exten-
sion), <b>$domain</b> (recipient domain), <b>mailbox</b> (entire recipi-
ent address localpart) and <b>$recipient</b><i>_</i><b>delimiter.</b> The forms
<i>${name?value}</i> and <i>${name:value}</i> expand conditionally to
<i>value</i> when <i>$name</i> is (is not) defined. In the result of
<i>name</i> expansion, characters that have special meaning to
the shell are replaced by underscores. The list of legal
characters is specified with the <b>command</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>
configuration parameter.
<b>default</b><i>_</i><b>privs</b>).
Mailbox delivery can be delegated to alternative message
transports specified in the <b>master.cf</b> file. The <b>mail-</b>
<b>box</b><i>_</i><b>transport</b> configuration parameter specifies a message
transport that is to be used for all local recipients,
regardless of whether they are found in the UNIX passwd
database. The <b>fallback</b><i>_</i><b>transport</b> parameter specifies a
message transport for recipients that are not found in the
UNIX passwd database.
In the case of UNIX-style mailbox delivery, the <b>local</b> dae-
mon prepends a "<b>From</b> <i>sender</i> <i>time_stamp</i>" envelope header to
each message, prepends a <b>Delivered-To:</b> header with the
@ -137,17 +137,6 @@ LOCAL(8) LOCAL(8)
LOCAL(8) LOCAL(8)
transports specified in the <b>master.cf</b> file. The <b>mail-</b>
<b>box</b><i>_</i><b>transport</b> configuration parameter specifies a message
transport that is to be used for all local recipients,
regardless of whether they are found in the UNIX passwd
database. The <b>fallback</b><i>_</i><b>transport</b> parameter specifies a
message transport for recipients that are not found in the
UNIX passwd database.
In the case of UNIX-style mailbox delivery, the <b>local</b> dae-
mon prepends a "<b>From</b> <i>sender</i> <i>time_stamp</i>" envelope header to
each message, prepends a <b>Delivered-To:</b> header with the
envelope recipient address, prepends a <b>Return-Path:</b> header
with the envelope sender address, prepends a &gt; character
to lines beginning with "<b>From</b> ", and appends an empty
@ -178,19 +167,30 @@ LOCAL(8) LOCAL(8)
Command exit status codes are expected to follow the con-
ventions defined in &lt;<b>sysexits.h</b>&gt;.
When mail is delivered on behalf of a user, the <b>HOME</b>, <b>LOG-</b>
<b>NAME</b>, and <b>SHELL</b> environment variables are set accordingly.
A limited amount of message context is exported via envi-
ronment variables. Characters that may have special mean-
ing to the shell are replaced by underscores. The list of
acceptable characters is specified with the <b>command</b><i>_</i><b>expan-</b>
<b>sion</b><i>_</i><b>filter</b> configuration parameter.
<b>SHELL</b> The recipient user's login shell.
<b>HOME</b> The recipient user's home directory.
<b>USER</b> The bare recipient name.
<b>EXTENSION</b>
The optional recipient address extension.
<b>DOMAIN</b> The recipient address domain part.
<b>LOGNAME</b>
The bare recipient name.
The <b>PATH</b> environment variable is always reset to a system-
dependent default path, and the <b>TZ</b> (time zone) environment
variable is always passed on without change.
The current working directory is the mail queue directory.
The <b>local</b> daemon prepends a "<b>From</b> <i>sender</i> <i>time_stamp</i>" enve-
lope header to each message, prepends a <b>Delivered-To:</b>
header with the recipient envelope address, prepends a
<b>Return-Path:</b> header with the sender envelope address, and
appends an empty line.
@ -203,6 +203,14 @@ LOCAL(8) LOCAL(8)
LOCAL(8) LOCAL(8)
The current working directory is the mail queue directory.
The <b>local</b> daemon prepends a "<b>From</b> <i>sender</i> <i>time_stamp</i>" enve-
lope header to each message, prepends a <b>Delivered-To:</b>
header with the recipient envelope address, prepends a
<b>Return-Path:</b> header with the sender envelope address, and
appends an empty line.
<b>EXTERNAL</b> <b>FILE</b> <b>DELIVERY</b>
The <b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>files</b> configuration parameter restricts
delivery to external files. The default setting (<b>alias,</b>
@ -248,15 +256,7 @@ LOCAL(8) LOCAL(8)
superuser, delivery is made with the rights specified with
the <b>default</b><i>_</i><b>privs</b> configuration parameter.
<b>STANDARDS</b>
RFC 822 (ARPA Internet Text Messages)
<b>DIAGNOSTICS</b>
Problems and transactions are logged to <b>syslogd</b>(8). Cor-
rupted message files are marked so that the queue manager
can move them to the <b>corrupt</b> queue afterwards.
Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
@ -269,6 +269,15 @@ LOCAL(8) LOCAL(8)
LOCAL(8) LOCAL(8)
<b>STANDARDS</b>
RFC 822 (ARPA Internet Text Messages)
<b>DIAGNOSTICS</b>
Problems and transactions are logged to <b>syslogd</b>(8). Cor-
rupted message files are marked so that the queue manager
can move them to the <b>corrupt</b> queue afterwards.
Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
the postmaster is notified of bounces and of other trou-
ble.
@ -314,15 +323,6 @@ LOCAL(8) LOCAL(8)
<b>Mailbox</b> <b>delivery</b>
<b>fallback</b><i>_</i><b>transport</b>
Message transport for recipients that are not found
in the UNIX passwd database. This parameter over-
rides <b>luser</b><i>_</i><b>relay</b>.
<b>home</b><i>_</i><b>mailbox</b>
Pathname of a mailbox relative to a user's home
directory. Specify a path ending in <b>/</b> for maildir-
style delivery.
@ -335,6 +335,14 @@ LOCAL(8) LOCAL(8)
LOCAL(8) LOCAL(8)
in the UNIX passwd database. This parameter over-
rides <b>luser</b><i>_</i><b>relay</b>.
<b>home</b><i>_</i><b>mailbox</b>
Pathname of a mailbox relative to a user's home
directory. Specify a path ending in <b>/</b> for maildir-
style delivery.
<b>luser</b><i>_</i><b>relay</b>
Destination (<i>@domain</i> or <i>address</i>) for non-existent
users. The <i>address</i> is subjected to <i>$name</i> expan-
@ -382,14 +390,6 @@ LOCAL(8) LOCAL(8)
Limit the amount of memory used for processing a
partial input line.
<b>local</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
Limit the number of parallel deliveries to the same
user. The default limit is taken from the
<b>default</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> parameter.
<b>local</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
Limit the number of recipients per message
6
@ -401,7 +401,14 @@ LOCAL(8) LOCAL(8)
LOCAL(8) LOCAL(8)
delivery. The default limit is taken from the
<b>local</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
Limit the number of parallel deliveries to the same
user. The default limit is taken from the
<b>default</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b> parameter.
<b>local</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
Limit the number of recipients per message deliv-
ery. The default limit is taken from the
<b>default</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> parameter.
<b>Security</b> <b>controls</b>
@ -448,6 +455,18 @@ LOCAL(8) LOCAL(8)
<b>AUTHOR(S)</b>
Wietse Venema
IBM T.J. Watson Research
7
LOCAL(8) LOCAL(8)
P.O. Box 704
Yorktown Heights, NY 10598, USA
@ -458,7 +477,54 @@ LOCAL(8) LOCAL(8)
7
8
</pre> </body> </html>

View File

@ -116,11 +116,11 @@ decisions on the basis of first-hand information.
<p>
Of course, Postfix programs do not trust data received from the
network, either. In particular, no Postfix program places
sender-provided data into shell command lines or into environment
variables. If there is one lesson that people have learned from
Web site security disasters it is this one: <i> don't let any data
from the network near a shell</i>.
network, either. In particular, Postfix filters sender-provided
data before exporting it via environment variables. If there is one
lesson that people have learned from Web site security disasters
it is this one: <i> don't let any data from the network near a
shell</i>. Filtering is the best we can do.
<h2>Large inputs</h2>

View File

@ -15,6 +15,9 @@
/* input. A limited amount of standard output and standard error
/* output is captured for diagnostics purposes.
/* Duplicate commands for the same recipient are suppressed.
/* A limited amount of information is exported via the environment:
/* HOME, SHELL, LOGNAME, USER, EXTENSION, and DOMAIN. The exported
/* information is censored with var_cmd_filter.
/*
/* Arguments:
/* .IP state
@ -49,6 +52,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
/* Utility library. */
@ -57,7 +61,6 @@
#include <vstring.h>
#include <vstream.h>
#include <argv.h>
#include <mac_expand.h>
/* Global library. */
@ -83,8 +86,8 @@ int deliver_command(LOCAL_STATE state, USER_ATTR usr_attr, char *command)
int deliver_status;
ARGV *env;
int copy_flags;
VSTRING *expanded_cmd = 0;
char *xcommand ;
char **cpp;
char *cp;
/*
* Make verbose logging easier to understand.
@ -143,24 +146,27 @@ int deliver_command(LOCAL_STATE state, USER_ATTR usr_attr, char *command)
env = argv_alloc(1);
if (usr_attr.home)
argv_add(env, "HOME", usr_attr.home, ARGV_END);
if (usr_attr.logname)
argv_add(env, "LOGNAME", usr_attr.logname, ARGV_END);
argv_add(env, "LOGNAME", state.msg_attr.user, ARGV_END);
argv_add(env, "USER", state.msg_attr.user, ARGV_END);
if (usr_attr.shell)
argv_add(env, "SHELL", usr_attr.shell, ARGV_END);
if (state.msg_attr.domain)
argv_add(env, "DOMAIN", state.msg_attr.domain, ARGV_END);
if (state.msg_attr.extension)
argv_add(env, "EXTENSION", state.msg_attr.extension, ARGV_END);
argv_terminate(env);
if (command == var_mailbox_command) {
expanded_cmd = vstring_alloc(100);
local_expand(expanded_cmd, command, &state,
&usr_attr, var_cmd_exp_filter);
xcommand = vstring_str(expanded_cmd);
} else {
xcommand = command;
}
/*
* Censor out undesirable characters from exported data.
*/
for (cpp = env->argv; *cpp; cpp += 2)
for (cp = cpp[1]; *(cp += strspn(cp, var_cmd_exp_filter)) != 0;)
*cp++ = '_';
cmd_status = pipe_command(state.msg_attr.fp, why,
PIPE_CMD_UID, usr_attr.uid,
PIPE_CMD_GID, usr_attr.gid,
PIPE_CMD_COMMAND, xcommand,
PIPE_CMD_COMMAND, command,
PIPE_CMD_COPY_FLAGS, copy_flags,
PIPE_CMD_SENDER, state.msg_attr.sender,
PIPE_CMD_DELIVERED, state.msg_attr.delivered,
@ -170,8 +176,6 @@ int deliver_command(LOCAL_STATE state, USER_ATTR usr_attr, char *command)
PIPE_CMD_END);
argv_free(env);
if (expanded_cmd)
vstring_free(expanded_cmd);
/*
* Depending on the result, bounce or defer the message.

View File

@ -95,18 +95,6 @@
/* executes with the privileges of the recipient user (exception: in
/* case of delivery as root, the command executes with the privileges
/* of \fBdefault_privs\fR).
/* The command is subject to interpolation of \fB$user\fR (recipient
/* username), \fB$home\fR (recipient home directory), \fB$shell\fR
/* (recipient shell), \fB$recipient\fR (complete recipient address),
/* \fB$extension\fR (recipient address extension), \fB$domain\fR
/* (recipient domain), \fBmailbox\fR (entire recipient address
/* localpart) and \fB$recipient_delimiter.\fR The forms
/* \fI${name?value}\fR and \fI${name:value}\fR expand conditionally to
/* \fIvalue\fR when \fI$name\fR is (is not) defined.
/* In the result of \fIname\fR expansion, characters that have special
/* meaning to the shell are replaced by underscores. The list of legal
/* characters is specified with the \fBcommand_expansion_filter\fR
/* configuration parameter.
/*
/* Mailbox delivery can be delegated to alternative message transports
/* specified in the \fBmaster.cf\fR file.
@ -148,9 +136,24 @@
/* \fBcommand_time_limit\fR seconds. Command exit status codes are
/* expected to follow the conventions defined in <\fBsysexits.h\fR>.
/*
/* When mail is delivered on behalf of a user, the \fBHOME\fR,
/* \fBLOGNAME\fR, and \fBSHELL\fR environment variables are set
/* accordingly.
/* A limited amount of message context is exported via environment
/* variables. Characters that may have special meaning to the shell
/* are replaced by underscores. The list of acceptable characters
/* is specified with the \fBcommand_expansion_filter\fR configuration
/* parameter.
/* .IP \fBSHELL\fR
/* The recipient user's login shell.
/* .IP \fBHOME\fR
/* The recipient user's home directory.
/* .IP \fBUSER\fR
/* The bare recipient name.
/* .IP \fBEXTENSION\fR
/* The optional recipient address extension.
/* .IP \fBDOMAIN\fR
/* The recipient address domain part.
/* .IP \fBLOGNAME\fR
/* The bare recipient name.
/* .PP
/* The \fBPATH\fR environment variable is always reset to a
/* system-dependent default path, and the \fBTZ\fR (time zone)
/* environment variable is always passed on without change.

View File

@ -50,7 +50,7 @@ extension), \fB$domain\fR (recipient domain), \fBmailbox\fR
\fI$name\fR is (is not) defined.
In the result of \fIname\fR expansion, characters that have special
meaning to the shell are replaced by underscores. The list of legal
characters is specified with the \fBcommand_expansion_filter\fR
characters is specified with the \fBforward_expansion_filter\fR
configuration parameter.
An alias or ~/.\fBforward\fR file may list any combination of external
@ -107,18 +107,6 @@ with the \fBmailbox_command\fR configuration parameter. The command
executes with the privileges of the recipient user (exception: in
case of delivery as root, the command executes with the privileges
of \fBdefault_privs\fR).
The command is subject to interpolation of \fB$user\fR (recipient
username), \fB$home\fR (recipient home directory), \fB$shell\fR
(recipient shell), \fB$recipient\fR (complete recipient address),
\fB$extension\fR (recipient address extension), \fB$domain\fR
(recipient domain), \fBmailbox\fR (entire recipient address
localpart) and \fB$recipient_delimiter.\fR The forms
\fI${name?value}\fR and \fI${name:value}\fR expand conditionally to
\fIvalue\fR when \fI$name\fR is (is not) defined.
In the result of \fIname\fR expansion, characters that have special
meaning to the shell are replaced by underscores. The list of legal
characters is specified with the \fBforward_expansion_filter\fR
configuration parameter.
Mailbox delivery can be delegated to alternative message transports
specified in the \fBmaster.cf\fR file.
@ -162,9 +150,24 @@ A command is forcibly terminated if it does not complete within
\fBcommand_time_limit\fR seconds. Command exit status codes are
expected to follow the conventions defined in <\fBsysexits.h\fR>.
When mail is delivered on behalf of a user, the \fBHOME\fR,
\fBLOGNAME\fR, and \fBSHELL\fR environment variables are set
accordingly.
A limited amount of message context is exported via environment
variables. Characters that may have special meaning to the shell
are replaced by underscores. The list of acceptable characters
is specified with the \fBcommand_expansion_filter\fR configuration
parameter.
.IP \fBSHELL\fR
The recipient user's login shell.
.IP \fBHOME\fR
The recipient user's home directory.
.IP \fBUSER\fR
The bare recipient name.
.IP \fBEXTENSION\fR
The optional recipient address extension.
.IP \fBDOMAIN\fR
The recipient address domain part.
.IP \fBLOGNAME\fR
The bare recipient name.
.PP
The \fBPATH\fR environment variable is always reset to a
system-dependent default path, and the \fBTZ\fR (time zone)
environment variable is always passed on without change.
@ -301,7 +304,8 @@ Directory with UNIX-style mailboxes. The default pathname is system
dependent.
.IP \fBmailbox_command\fR
External command to use for mailbox delivery. The command executes
with the recipient privileges (exception: root).
with the recipient privileges (exception: root). The string is subject
to $name expansions.
.IP \fBmailbox_transport\fR
Message transport to use for mailbox delivery to all local
recipients, whether or not they are found in the UNIX passwd database.
@ -345,13 +349,13 @@ Restrict the usage of mail delivery to external command.
.IP \fBallow_mail_to_files\fR
Restrict the usage of mail delivery to external file.
.IP \fBcommand_expansion_filter\fR
What characters are allowed to appear in $name expansions
of mailbox_command.
What characters are allowed to appear in $name expansions of
mailbox_command. Illegal characters are replaced by underscores.
.IP \fBdefault_privs\fR
Default rights for delivery to external file or command.
.IP \fBforward_expansion_filter\fR
What characters are allowed to appear in $name expansions
of forward_path.
What characters are allowed to appear in $name expansions of
forward_path. Illegal characters are replaced by underscores.
.SH HISTORY
.na
.nf

View File

@ -174,6 +174,7 @@ smtpd_state.o: ../include/mymalloc.h
smtpd_state.o: ../include/vstream.h
smtpd_state.o: ../include/vbuf.h
smtpd_state.o: ../include/name_mask.h
smtpd_state.o: ../include/stringops.h
smtpd_state.o: ../include/cleanup_user.h
smtpd_state.o: ../include/mail_params.h
smtpd_state.o: ../include/mail_error.h

View File

@ -314,11 +314,6 @@ static int helo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
return (-1);
}
collapse_args(argc, argv);
if (SMTPD_STAND_ALONE(state) == 0
&& (err = smtpd_check_helo(state, argv[1].strval)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
}
state->helo_name = mystrdup(printable(argv[1].strval, '?'));
state->protocol = "SMTP";
smtpd_chat_reply(state, "250 %s", var_myhostname);
@ -342,11 +337,6 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
return (-1);
}
collapse_args(argc, argv);
if (SMTPD_STAND_ALONE(state) == 0
&& (err = smtpd_check_helo(state, argv[1].strval)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
}
state->helo_name = mystrdup(printable(argv[1].strval, '?'));
state->protocol = "ESMTP";
smtpd_chat_reply(state, "250-%s", var_myhostname);
@ -461,11 +451,6 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
}
}
state->time = time((time_t *) 0);
if (SMTPD_STAND_ALONE(state) == 0
&& (err = smtpd_check_mail(state, argv[3].strval)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
}
if ((err = smtpd_check_size(state, size)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
@ -548,11 +533,26 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
smtpd_chat_reply(state, "452 Error: too many recipients");
return (-1);
}
if (SMTPD_STAND_ALONE(state) == 0
&& (err = smtpd_check_rcpt(state, argv[3].strval)) != 0) {
if (SMTPD_STAND_ALONE(state) == 0) {
if ((err = smtpd_check_client(state)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
}
if (state->helo_name
&& (err = smtpd_check_helo(state, state->helo_name)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
}
if (state->sender
&& (err = smtpd_check_mail(state, state->sender)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
}
if ((err = smtpd_check_rcpt(state, argv[3].strval)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
}
}
/*
* Store the recipient. Remember the first one.
@ -795,8 +795,23 @@ static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
return (-1);
}
collapse_args(argc, argv);
if (SMTPD_STAND_ALONE(state) == 0)
if (SMTPD_STAND_ALONE(state) == 0) {
if ((err = smtpd_check_client(state)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
}
if (state->helo_name
&& (err = smtpd_check_helo(state, state->helo_name)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
}
if (state->sender
&& (err = smtpd_check_mail(state, state->sender)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
}
err = smtpd_check_rcpt(state, argv[1].strval);
}
/*
* End untokenize.
@ -847,11 +862,21 @@ static int etrn_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
* rejected. RFC 1985 requires that 459 be sent when the server refuses
* to perform the request.
*/
if (SMTPD_STAND_ALONE(state) == 0
&& (err = smtpd_check_etrn(state, argv[1].strval)) != 0) {
if (SMTPD_STAND_ALONE(state) == 0) {
if ((err = smtpd_check_client(state)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
}
if (state->helo_name
&& (err = smtpd_check_helo(state, state->helo_name)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
}
if ((err = smtpd_check_etrn(state, argv[1].strval)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
}
}
/*
* XXX The preliminary implementation causes a full deferred queue scan.
@ -1043,15 +1068,10 @@ static void smtpd_service(VSTREAM *stream, char *unused_service, char **argv)
debug_peer_check(state.name, state.addr);
/*
* See if we want to talk to this client at all. Then, log the connection
* event.
* Greet the client and log the connection event.
*/
if ((state.access_denied = smtpd_check_client(&state)) != 0) {
smtpd_chat_reply(&state, "%s", state.access_denied);
} else {
smtpd_chat_reply(&state, "220 %s", var_smtpd_banner);
msg_info("connect from %s[%s]", state.name, state.addr);
}
/*
* Provide the SMTP service.

View File

@ -33,6 +33,7 @@ typedef struct SMTPD_STATE {
time_t time;
char *name;
char *addr;
char *namaddr;
int error_count;
int error_mask;
int notify_mask;

View File

@ -217,6 +217,7 @@
#include <stdarg.h>
#include <netdb.h>
#include <setjmp.h>
#include <stdlib.h>
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
@ -293,6 +294,18 @@ static ARGV *mail_restrctions;
static ARGV *rcpt_restrctions;
static ARGV *etrn_restrctions;
/*
* Reject context.
*/
#define SMTPD_NAME_CLIENT "Client host"
#define SMTPD_NAME_HELO "Helo command"
#define SMTPD_NAME_SENDER "Sender address"
#define SMTPD_NAME_RECIPIENT "Recipient address"
#define SMTPD_NAME_ETRN "Etrn command"
/*
* YASLM.
*/
#define STR vstring_str
/* smtpd_check_parse - pre-parse restrictions */
@ -380,16 +393,6 @@ static int smtpd_check_reject(SMTPD_STATE *state, int error_class,
msg_warn("response code configuration error: %s", STR(error_text));
vstring_strcpy(error_text, "450 Service unavailable");
}
/*
* Give everyone involved a clue.
*/
if (state->sender) {
vstring_sprintf_append(error_text, " (from=<%s>", state->sender);
if (state->recipient)
vstring_sprintf_append(error_text, " to=<%s>", state->recipient);
VSTRING_ADDCH(error_text, ')');
}
printable(STR(error_text), ' ');
/*
@ -397,9 +400,21 @@ static int smtpd_check_reject(SMTPD_STATE *state, int error_class,
* postmaster notices, this may be the only trace left that service was
* rejected. Print the request, client name/address, and response.
*/
msg_info("%s: reject: %s from %s[%s]: %s", state->queue_id, state->where,
state->name, state->addr, STR(error_text));
msg_info("%s: reject: %s from %s: %s",
state->queue_id, state->where,
state->namaddr, STR(error_text));
/*
* Log from/to information if available, for the benefit of the local
* sysadmin.
*/
if (state->sender) {
msg_info(state->recipient ?
"%s: reject: %s from %s: from=<%s> to=<%s>" :
"%s: reject: %s from %s: from=<%s>",
state->queue_id, state->where, state->namaddr,
state->sender, state->recipient);
}
return (SMTPD_CHECK_REJECT);
}
@ -414,7 +429,7 @@ static int reject_unknown_client(SMTPD_STATE *state)
if (strcasecmp(state->name, "unknown") == 0)
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
"%d Cannot find your hostname, [%s]",
"%d Client host rejected: cannot find your hostname, [%s]",
var_unk_client_code, state->addr));
return (SMTPD_CHECK_DUNNO);
}
@ -454,7 +469,8 @@ static char *dup_if_truncate(char *name)
/* reject_invalid_hostaddr - fail if host address is incorrect */
static int reject_invalid_hostaddr(SMTPD_STATE *state, char *addr)
static int reject_invalid_hostaddr(SMTPD_STATE *state, char *addr,
char *reply_name, char *reply_class)
{
char *myname = "reject_invalid_hostaddr";
int len;
@ -474,8 +490,8 @@ static int reject_invalid_hostaddr(SMTPD_STATE *state, char *addr)
*/
if (!valid_hostaddr(test_addr))
stat = smtpd_check_reject(state, MAIL_ERROR_POLICY,
"%d <%s>: Invalid ip address",
var_bad_name_code, addr);
"%d <%s>: %s rejected: invalid ip address",
var_bad_name_code, reply_name, reply_class);
else
stat = SMTPD_CHECK_DUNNO;
@ -490,7 +506,8 @@ static int reject_invalid_hostaddr(SMTPD_STATE *state, char *addr)
/* reject_invalid_hostname - fail if host/domain syntax is incorrect */
static int reject_invalid_hostname(SMTPD_STATE *state, char *name)
static int reject_invalid_hostname(SMTPD_STATE *state, char *name,
char *reply_name, char *reply_class)
{
char *myname = "reject_invalid_hostname";
char *test_name;
@ -509,8 +526,8 @@ static int reject_invalid_hostname(SMTPD_STATE *state, char *name)
*/
if (!valid_hostname(test_name))
stat = smtpd_check_reject(state, MAIL_ERROR_POLICY,
"%d <%s>: Invalid name",
var_bad_name_code, name);
"%d <%s>: %s rejected: Invalid name",
var_bad_name_code, reply_name, reply_class);
else
stat = SMTPD_CHECK_DUNNO;
@ -525,7 +542,8 @@ static int reject_invalid_hostname(SMTPD_STATE *state, char *name)
/* reject_non_fqdn_hostname - fail if host name is not in fqdn form */
static int reject_non_fqdn_hostname(SMTPD_STATE *state, char *name)
static int reject_non_fqdn_hostname(SMTPD_STATE *state, char *name,
char *reply_name, char *reply_class)
{
char *myname = "reject_non_fqdn_hostname";
char *test_name;
@ -544,8 +562,8 @@ static int reject_non_fqdn_hostname(SMTPD_STATE *state, char *name)
*/
if (!valid_hostname(test_name) || !strchr(test_name, '.'))
stat = smtpd_check_reject(state, MAIL_ERROR_POLICY,
"%d <%s>: need fully-qualified hostname",
var_non_fqdn_code, name);
"%d <%s>: %s rejected: need fully-qualified hostname",
var_non_fqdn_code, reply_name, reply_class);
else
stat = SMTPD_CHECK_DUNNO;
@ -560,7 +578,8 @@ static int reject_non_fqdn_hostname(SMTPD_STATE *state, char *name)
/* reject_unknown_hostname - fail if name has no A or MX record */
static int reject_unknown_hostname(SMTPD_STATE *state, char *name)
static int reject_unknown_hostname(SMTPD_STATE *state, char *name,
char *reply_name, char *reply_class)
{
char *myname = "reject_unknown_hostname";
int dns_status;
@ -572,15 +591,17 @@ static int reject_unknown_hostname(SMTPD_STATE *state, char *name)
(VSTRING *) 0, T_A, T_MX, 0);
if (dns_status != DNS_OK)
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
"%d <%s>: Host not found",
"%d <%s>: %s rejected: Host not found",
dns_status == DNS_NOTFOUND ?
var_unk_name_code : 450, name));
var_unk_name_code : 450,
reply_name, reply_class));
return (SMTPD_CHECK_DUNNO);
}
/* reject_unknown_mailhost - fail if name has no A or MX record */
static int reject_unknown_mailhost(SMTPD_STATE *state, char *name)
static int reject_unknown_mailhost(SMTPD_STATE *state, char *name,
char *reply_name, char *reply_class)
{
char *myname = "reject_unknown_mailhost";
int dns_status;
@ -592,15 +613,17 @@ static int reject_unknown_mailhost(SMTPD_STATE *state, char *name)
(VSTRING *) 0, T_A, T_MX, 0);
if (dns_status != DNS_OK)
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
"%d <%s>: Domain not found",
"%d <%s>: %s rejected: Domain not found",
dns_status == DNS_NOTFOUND ?
var_unk_addr_code : 450, name));
var_unk_addr_code : 450,
reply_name, reply_class));
return (SMTPD_CHECK_DUNNO);
}
/* check_relay_domains - OK/FAIL for message relaying */
static int check_relay_domains(SMTPD_STATE *state, char *recipient)
static int check_relay_domains(SMTPD_STATE *state, char *recipient,
char *reply_name, char *reply_class)
{
char *myname = "check_relay_domains";
char *domain;
@ -639,8 +662,8 @@ static int check_relay_domains(SMTPD_STATE *state, char *recipient)
* Deny relaying between sites that both are not in relay_domains.
*/
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
"%d <%s>: Relay access denied",
var_relay_code, recipient));
"%d <%s>: %s rejected: Relay access denied",
var_relay_code, reply_name, reply_class));
}
/* has_my_addr - see if this host name lists one of my network addresses */
@ -770,7 +793,8 @@ static int permit_mx_backup(SMTPD_STATE *unused_state, const char *recipient)
/* reject_non_fqdn_address - fail if address is not in fqdn form */
static int reject_non_fqdn_address(SMTPD_STATE *state, char *addr)
static int reject_non_fqdn_address(SMTPD_STATE *state, char *addr,
char *reply_name, char *reply_class)
{
char *myname = "reject_non_fqdn_address";
char *domain;
@ -806,8 +830,8 @@ static int reject_non_fqdn_address(SMTPD_STATE *state, char *addr)
*/
if (!*test_dom || !valid_hostname(test_dom) || !strchr(test_dom, '.'))
stat = smtpd_check_reject(state, MAIL_ERROR_POLICY,
"%d <%s>: need fully-qualified address",
var_non_fqdn_code, addr);
"%d <%s>: %s rejected: need fully-qualified address",
var_non_fqdn_code, reply_name, reply_class);
else
stat = SMTPD_CHECK_DUNNO;
@ -822,7 +846,8 @@ static int reject_non_fqdn_address(SMTPD_STATE *state, char *addr)
/* reject_unknown_address - fail if address does not resolve */
static int reject_unknown_address(SMTPD_STATE *state, char *addr)
static int reject_unknown_address(SMTPD_STATE *state, char *addr,
char *reply_name, char *reply_class)
{
char *myname = "reject_unknown_address";
char *domain;
@ -851,15 +876,17 @@ static int reject_unknown_address(SMTPD_STATE *state, char *addr)
/*
* Look up the name in the DNS.
*/
return (reject_unknown_mailhost(state, domain));
return (reject_unknown_mailhost(state, domain, reply_name, reply_class));
}
/* check_table_result - translate table lookup result into pass/reject */
static int check_table_result(SMTPD_STATE *state, char *table,
const char *value, const char *datum)
const char *value, const char *datum,
char *reply_name, char *reply_class)
{
char *myname = "check_table_result";
int code;
if (msg_verbose)
msg_info("%s: %s %s %s", myname, table, value, datum);
@ -869,15 +896,21 @@ static int check_table_result(SMTPD_STATE *state, char *table,
*/
if (strcasecmp(value, "REJECT") == 0)
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
"%d <%s>: Access denied",
var_access_map_code, datum));
"%d <%s>: %s rejected: Access denied",
var_access_map_code, reply_name, reply_class));
/*
* 4xx or 5xx means NO as well. smtpd_check_reject() will validate the
* response status code.
*/
if (ISDIGIT(value[0]))
return (smtpd_check_reject(state, MAIL_ERROR_POLICY, "%s", value));
if (ISDIGIT(value[0]) && ISDIGIT(value[1]) && ISDIGIT(value[2])) {
code = atoi(value);
while (ISDIGIT(*value) || ISSPACE(*value))
value++;
return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
"%d <%s>: %s rejected: %s",
code, reply_name, reply_class, value));
}
/*
* OK or RELAY or whatever means YES.
@ -887,7 +920,8 @@ static int check_table_result(SMTPD_STATE *state, char *table,
/* check_access - table lookup without substring magic */
static int check_access(SMTPD_STATE *state, char *table, char *name, int flags)
static int check_access(SMTPD_STATE *state, char *table, char *name, int flags,
char *reply_name, char *reply_class)
{
char *myname = "check_access";
char *low_name = lowercase(mystrdup(name));
@ -905,7 +939,8 @@ static int check_access(SMTPD_STATE *state, char *table, char *name, int flags)
msg_panic("%s: dictionary not found: %s", myname, table);
if (flags == 0 || (flags & dict->flags) != 0) {
if ((value = dict_get(dict, low_name)) != 0)
CHK_ACCESS_RETURN(check_table_result(state, table, value, name));
CHK_ACCESS_RETURN(check_table_result(state, table, value, name,
reply_name, reply_class));
if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table);
}
@ -915,7 +950,8 @@ static int check_access(SMTPD_STATE *state, char *table, char *name, int flags)
/* check_domain_access - domainname-based table lookup */
static int check_domain_access(SMTPD_STATE *state, char *table,
char *domain, int flags)
char *domain, int flags,
char *reply_name, char *reply_class)
{
char *myname = "check_domain_access";
char *low_domain = lowercase(mystrdup(domain));
@ -937,7 +973,8 @@ static int check_domain_access(SMTPD_STATE *state, char *table,
msg_panic("%s: dictionary not found: %s", myname, table);
if (flags == 0 || (flags & dict->flags) != 0) {
if ((value = dict_get(dict, name)) != 0)
CHK_DOMAIN_RETURN(check_table_result(state, table, value, domain));
CHK_DOMAIN_RETURN(check_table_result(state, table, value,
domain, reply_name, reply_class));
if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table);
}
@ -948,8 +985,9 @@ static int check_domain_access(SMTPD_STATE *state, char *table,
/* check_addr_access - address-based table lookup */
static int check_addr_access(SMTPD_STATE *state, char *table, char *address,
int flags)
static int check_addr_access(SMTPD_STATE *state, char *table,
char *address, int flags,
char *reply_name, char *reply_class)
{
char *myname = "check_addr_access";
char *addr;
@ -969,7 +1007,8 @@ static int check_addr_access(SMTPD_STATE *state, char *table, char *address,
msg_panic("%s: dictionary not found: %s", myname, table);
if (flags == 0 || (flags & dict->flags) != 0) {
if ((value = dict_get(dict, addr)) != 0)
return (check_table_result(state, table, value, address));
return (check_table_result(state, table, value, address,
reply_name, reply_class));
if (dict_errno != 0)
msg_fatal("%s: table lookup problem", table);
}
@ -982,7 +1021,8 @@ static int check_addr_access(SMTPD_STATE *state, char *table, char *address,
/* check_namadr_access - OK/FAIL based on host name/address lookup */
static int check_namadr_access(SMTPD_STATE *state, char *table,
char *name, char *addr, int flags)
char *name, char *addr, int flags,
char *reply_name, char *reply_class)
{
char *myname = "check_namadr_access";
int status;
@ -994,13 +1034,15 @@ static int check_namadr_access(SMTPD_STATE *state, char *table,
* Look up the host name, or parent domains thereof. XXX A domain
* wildcard may pre-empt a more specific address table entry.
*/
if ((status = check_domain_access(state, table, name, flags)) != 0)
if ((status = check_domain_access(state, table, name, flags,
reply_name, reply_class)) != 0)
return (status);
/*
* Look up the network address, or parent networks thereof.
*/
if ((status = check_addr_access(state, table, addr, flags)) != 0)
if ((status = check_addr_access(state, table, addr, flags,
reply_name, reply_class)) != 0)
return (status);
/*
@ -1011,7 +1053,8 @@ static int check_namadr_access(SMTPD_STATE *state, char *table,
/* check_mail_access - OK/FAIL based on mail address lookup */
static int check_mail_access(SMTPD_STATE *state, char *table, char *addr)
static int check_mail_access(SMTPD_STATE *state, char *table, char *addr,
char *reply_name, char *reply_class)
{
char *myname = "check_mail_access";
char *ratsign;
@ -1039,13 +1082,15 @@ static int check_mail_access(SMTPD_STATE *state, char *table, char *addr)
/*
* Look up the full address.
*/
if ((status = check_access(state, table, STR(reply.recipient), FULL)) != 0)
if ((status = check_access(state, table, STR(reply.recipient), FULL,
reply_name, reply_class)) != 0)
return (status);
/*
* Look up the domain name, or parent domains thereof.
*/
if ((status = check_domain_access(state, table, ratsign + 1, PARTIAL)) != 0)
if ((status = check_domain_access(state, table, ratsign + 1, PARTIAL,
reply_name, reply_class)) != 0)
return (status);
/*
@ -1053,7 +1098,8 @@ static int check_mail_access(SMTPD_STATE *state, char *table, char *addr)
*/
local_at = mystrndup(STR(reply.recipient),
ratsign - STR(reply.recipient) + 1);
status = check_access(state, table, local_at, PARTIAL);
status = check_access(state, table, local_at, PARTIAL,
reply_name, reply_class);
myfree(local_at);
if (status != 0)
return (status);
@ -1149,7 +1195,8 @@ static int is_map_command(char *name, char *command, char ***argp)
/* generic_checks - generic restrictions */
static int generic_checks(SMTPD_STATE *state, char *name,
char ***cpp, int *status, char *what)
char ***cpp, int *status,
char *reply_name, char *reply_class)
{
/*
@ -1160,9 +1207,9 @@ static int generic_checks(SMTPD_STATE *state, char *name,
return (1);
}
if (strcasecmp(name, REJECT_ALL) == 0) {
*status = smtpd_check_reject(state, MAIL_ERROR_POLICY, *what ?
"%d <%s> Access denied" : "%d Access denied",
var_reject_code, what);
*status = smtpd_check_reject(state, MAIL_ERROR_POLICY,
"%d <%s>: %s rejected: Access denied",
var_reject_code, reply_name, reply_class);
return (1);
}
@ -1178,7 +1225,8 @@ static int generic_checks(SMTPD_STATE *state, char *name,
return (1);
}
if (is_map_command(name, CHECK_CLIENT_ACL, cpp)) {
*status = check_namadr_access(state, **cpp, state->name, state->addr, FULL);
*status = check_namadr_access(state, **cpp, state->name, state->addr,
FULL, state->namaddr, SMTPD_NAME_CLIENT);
return (1);
}
if (strcasecmp(name, REJECT_MAPS_RBL) == 0) {
@ -1191,31 +1239,37 @@ static int generic_checks(SMTPD_STATE *state, char *name,
*/
if (is_map_command(name, CHECK_HELO_ACL, cpp) && state->helo_name) {
if (state->helo_name)
*status = check_domain_access(state, **cpp, state->helo_name, FULL);
*status = check_domain_access(state, **cpp, state->helo_name, FULL,
state->helo_name, SMTPD_NAME_HELO);
return (1);
}
if (strcasecmp(name, REJECT_INVALID_HOSTNAME) == 0) {
if (state->helo_name) {
if (*state->helo_name != '[')
*status = reject_invalid_hostname(state, state->helo_name);
*status = reject_invalid_hostname(state, state->helo_name,
state->helo_name, SMTPD_NAME_HELO);
else
*status = reject_invalid_hostaddr(state, state->helo_name);
*status = reject_invalid_hostaddr(state, state->helo_name,
state->helo_name, SMTPD_NAME_HELO);
}
return (1);
}
if (strcasecmp(name, REJECT_UNKNOWN_HOSTNAME) == 0) {
if (state->helo_name) {
if (*state->helo_name != '[')
*status = reject_unknown_hostname(state, state->helo_name);
*status = reject_unknown_hostname(state, state->helo_name,
state->helo_name, SMTPD_NAME_HELO);
else
*status = reject_invalid_hostaddr(state, state->helo_name);
*status = reject_invalid_hostaddr(state, state->helo_name,
state->helo_name, SMTPD_NAME_HELO);
}
return (1);
}
if (strcasecmp(name, PERMIT_NAKED_IP_ADDR) == 0) {
if (state->helo_name) {
if (state->helo_name[strspn(state->helo_name, "0123456789.")] == 0
&& (*status = reject_invalid_hostaddr(state, state->helo_name)) == 0)
&& (*status = reject_invalid_hostaddr(state, state->helo_name,
state->helo_name, SMTPD_NAME_HELO)) == 0)
*status = SMTPD_CHECK_OK;
}
return (1);
@ -1223,9 +1277,11 @@ static int generic_checks(SMTPD_STATE *state, char *name,
if (strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) {
if (state->helo_name) {
if (*state->helo_name != '[')
*status = reject_non_fqdn_hostname(state, state->helo_name);
*status = reject_non_fqdn_hostname(state, state->helo_name,
state->helo_name, SMTPD_NAME_HELO);
else
*status = reject_invalid_hostaddr(state, state->helo_name);
*status = reject_invalid_hostaddr(state, state->helo_name,
state->helo_name, SMTPD_NAME_HELO);
}
return (1);
}
@ -1235,22 +1291,26 @@ static int generic_checks(SMTPD_STATE *state, char *name,
*/
if (is_map_command(name, CHECK_SENDER_ACL, cpp) && state->sender) {
if (state->sender)
*status = check_mail_access(state, **cpp, state->sender);
*status = check_mail_access(state, **cpp, state->sender,
state->sender, SMTPD_NAME_SENDER);
return (1);
}
if (strcasecmp(name, REJECT_UNKNOWN_ADDRESS) == 0) {
if (state->sender)
*status = reject_unknown_address(state, state->sender);
*status = reject_unknown_address(state, state->sender,
state->sender, SMTPD_NAME_SENDER);
return (1);
}
if (strcasecmp(name, REJECT_UNKNOWN_SENDDOM) == 0) {
if (state->sender)
*status = reject_unknown_address(state, state->sender);
*status = reject_unknown_address(state, state->sender,
state->sender, SMTPD_NAME_SENDER);
return (1);
}
if (strcasecmp(name, REJECT_NON_FQDN_SENDER) == 0) {
if (*state->sender)
*status = reject_non_fqdn_address(state, state->sender);
*status = reject_non_fqdn_address(state, state->sender,
state->sender, SMTPD_NAME_SENDER);
return (1);
}
return (0);
@ -1276,8 +1336,10 @@ char *smtpd_check_client(SMTPD_STATE *state)
*/
for (cpp = client_restrctions->argv; (name = *cpp) != 0; cpp++) {
if (strchr(name, ':') != 0) {
status = check_namadr_access(state, name, state->name, state->addr, FULL);
} else if (generic_checks(state, name, &cpp, &status, state->addr) == 0) {
status = check_namadr_access(state, name, state->name, state->addr,
FULL, state->namaddr, SMTPD_NAME_CLIENT);
} else if (generic_checks(state, name, &cpp, &status,
state->namaddr, SMTPD_NAME_CLIENT) == 0) {
msg_warn("unknown %s check: \"%s\"", VAR_CLIENT_CHECKS, name);
break;
}
@ -1310,8 +1372,10 @@ char *smtpd_check_helo(SMTPD_STATE *state, char *helohost)
state->helo_name = mystrdup(helohost);
for (cpp = helo_restrctions->argv; (name = *cpp) != 0; cpp++) {
if (strchr(name, ':') != 0) {
status = check_domain_access(state, name, helohost, FULL);
} else if (generic_checks(state, name, &cpp, &status, helohost) == 0) {
status = check_domain_access(state, name, helohost, FULL,
helohost, SMTPD_NAME_HELO);
} else if (generic_checks(state, name, &cpp, &status,
helohost, SMTPD_NAME_HELO) == 0) {
msg_warn("unknown %s check: \"%s\"", VAR_HELO_CHECKS, name);
break;
}
@ -1346,8 +1410,10 @@ char *smtpd_check_mail(SMTPD_STATE *state, char *sender)
state->sender = mystrdup(sender);
for (cpp = mail_restrctions->argv; (name = *cpp) != 0; cpp++) {
if (strchr(name, ':') != 0) {
status = check_mail_access(state, name, sender);
} else if (generic_checks(state, name, &cpp, &status, sender) == 0) {
status = check_mail_access(state, name, sender,
sender, SMTPD_NAME_SENDER);
} else if (generic_checks(state, name, &cpp, &status,
sender, SMTPD_NAME_SENDER) == 0) {
msg_warn("unknown %s check: \"%s\"", VAR_MAIL_CHECKS, name);
return (0);
}
@ -1382,18 +1448,24 @@ char *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient)
state->recipient = mystrdup(recipient);
for (cpp = rcpt_restrctions->argv; (name = *cpp) != 0; cpp++) {
if (strchr(name, ':') != 0) {
status = check_mail_access(state, name, recipient);
status = check_mail_access(state, name, recipient,
recipient, SMTPD_NAME_RECIPIENT);
} else if (is_map_command(name, CHECK_RECIP_ACL, &cpp)) {
status = check_mail_access(state, *cpp, recipient);
status = check_mail_access(state, *cpp, recipient,
recipient, SMTPD_NAME_RECIPIENT);
} else if (strcasecmp(name, PERMIT_MX_BACKUP) == 0) {
status = permit_mx_backup(state, recipient);
} else if (strcasecmp(name, CHECK_RELAY_DOMAINS) == 0) {
status = check_relay_domains(state, recipient);
status = check_relay_domains(state, recipient,
recipient, SMTPD_NAME_RECIPIENT);
} else if (strcasecmp(name, REJECT_UNKNOWN_RCPTDOM) == 0) {
status = reject_unknown_address(state, recipient);
status = reject_unknown_address(state, recipient,
recipient, SMTPD_NAME_RECIPIENT);
} else if (strcasecmp(name, REJECT_NON_FQDN_RCPT) == 0) {
status = reject_non_fqdn_address(state, recipient);
} else if (generic_checks(state, name, &cpp, &status, recipient) == 0) {
status = reject_non_fqdn_address(state, recipient,
recipient, SMTPD_NAME_RECIPIENT);
} else if (generic_checks(state, name, &cpp, &status,
recipient, SMTPD_NAME_RECIPIENT) == 0) {
msg_warn("unknown %s check: \"%s\"", VAR_RCPT_CHECKS, name);
break;
}
@ -1425,10 +1497,13 @@ char *smtpd_check_etrn(SMTPD_STATE *state, char *domain)
*/
for (cpp = etrn_restrctions->argv; (name = *cpp) != 0; cpp++) {
if (strchr(name, ':') != 0) {
status = check_domain_access(state, name, domain, FULL);
status = check_domain_access(state, name, domain, FULL,
domain, SMTPD_NAME_ETRN);
} else if (is_map_command(name, CHECK_ETRN_ACL, &cpp)) {
status = check_domain_access(state, *cpp, domain, FULL);
} else if (generic_checks(state, name, &cpp, &status, domain) == 0) {
status = check_domain_access(state, *cpp, domain, FULL,
domain, SMTPD_NAME_ETRN);
} else if (generic_checks(state, name, &cpp, &status,
domain, SMTPD_NAME_ETRN) == 0) {
msg_warn("unknown %s check: \"%s\"", VAR_RCPT_CHECKS, name);
break;
}
@ -1708,6 +1783,7 @@ main(int argc, char **argv)
int_init();
smtpd_check_init();
smtpd_state_init(&state, VSTREAM_IN, "", "");
state.queue_id = "<queue id>";
/*
* Main loop: update config parameters or test the client, helo, sender
@ -1748,6 +1824,10 @@ main(int argc, char **argv)
state.where = "CONNECT";
UPDATE_STRING(state.name, args->argv[1]);
UPDATE_STRING(state.addr, args->argv[2]);
if (state.namaddr)
myfree(state.namaddr);
state.namaddr = concatenate(state.name, "[", state.addr,
"]", (char *) 0);
resp = smtpd_check_client(&state);
}
break;

View File

@ -13,23 +13,23 @@ OK
>>> client_restrictions permit_mynetworks,reject_unknown_client,hash:./smtpd_check_access
OK
>>> client unknown 131.155.210.17
./smtpd_check: reject: CONNECT from unknown[131.155.210.17]: 450 Cannot find your hostname, [131.155.210.17]
450 Cannot find your hostname, [131.155.210.17]
./smtpd_check: <queue id>: reject: CONNECT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
>>> client random.bad.domain 123.123.123.123
./smtpd_check: reject: CONNECT from random.bad.domain[123.123.123.123]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: CONNECT from random.bad.domain[123.123.123.123]: 554 <random.bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
554 <random.bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
>>> client friend.bad.domain 123.123.123.123
OK
>>> client bad.domain 123.123.123.123
./smtpd_check: reject: CONNECT from bad.domain[123.123.123.123]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: CONNECT from bad.domain[123.123.123.123]: 554 <bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
554 <bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
>>> client wzv.win.tue.nl 131.155.210.17
OK
>>> client aa.win.tue.nl 131.155.210.18
./smtpd_check: reject: CONNECT from aa.win.tue.nl[131.155.210.18]: 554 match 131.155.210
554 match 131.155.210
./smtpd_check: <queue id>: reject: CONNECT from aa.win.tue.nl[131.155.210.18]: 554 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210
554 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210
>>> client_restrictions permit_mynetworks
OK
>>> #
@ -40,31 +40,31 @@ OK
>>> client unknown 131.155.210.17
OK
>>> helo foo.
./smtpd_check: reject: HELO from unknown[131.155.210.17]: 450 Cannot find your hostname, [131.155.210.17]
450 Cannot find your hostname, [131.155.210.17]
./smtpd_check: <queue id>: reject: HELO from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client foo 123.123.123.123
OK
>>> helo foo.
./smtpd_check: reject: HELO from foo[123.123.123.123]: 450 <foo.>: Host not found
450 <foo.>: Host not found
./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 <foo.>: Helo command rejected: Host not found
450 <foo.>: Helo command rejected: Host not found
>>> helo foo
./smtpd_check: reject: HELO from foo[123.123.123.123]: 450 <foo>: Host not found
450 <foo>: Host not found
./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 <foo>: Helo command rejected: Host not found
450 <foo>: Helo command rejected: Host not found
>>> helo spike.porcupine.org
OK
>>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,hash:./smtpd_check_access
OK
>>> helo random.bad.domain
./smtpd_check: reject: HELO from foo[123.123.123.123]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 554 <random.bad.domain>: Helo command rejected: match bad.domain
554 <random.bad.domain>: Helo command rejected: match bad.domain
>>> helo friend.bad.domain
OK
>>> helo_restrictions reject_invalid_hostname,reject_unknown_hostname
OK
>>> helo 123.123.123.123
./smtpd_check: warning: valid_hostname: numeric hostname: 123.123.123.123
./smtpd_check: reject: HELO from foo[123.123.123.123]: 450 <123.123.123.123>: Host not found
450 <123.123.123.123>: Host not found
./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 <123.123.123.123>: Helo command rejected: Host not found
450 <123.123.123.123>: Helo command rejected: Host not found
>>> helo_restrictions permit_naked_ip_address,reject_invalid_hostname,reject_unknown_hostname
OK
>>> helo 123.123.123.123
@ -77,8 +77,9 @@ OK
>>> client unknown 131.155.210.17
OK
>>> mail foo@watson.ibm.com
./smtpd_check: reject: MAIL from unknown[131.155.210.17]: 450 Cannot find your hostname, [131.155.210.17]
450 Cannot find your hostname, [131.155.210.17]
./smtpd_check: <queue id>: reject: MAIL from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
./smtpd_check: <queue id>: reject: MAIL from unknown[131.155.210.17]: from=<foo@watson.ibm.com>
450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
>>> mail foo@watson.ibm.com
@ -92,30 +93,37 @@ OK
>>> mail foo@watson.ibm.com
OK
>>> mail foo@bad.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 450 <bad.domain>: Domain not found
450 <bad.domain>: Domain not found
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 450 <foo@bad.domain>: Sender address rejected: Domain not found
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@bad.domain>
450 <foo@bad.domain>: Sender address rejected: Domain not found
>>> sender_restrictions hash:./smtpd_check_access
OK
>>> mail bad-sender@any.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match bad-sender@
554 match bad-sender@
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<bad-sender@any.domain>
554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
>>> mail bad-sender@good.domain
OK
>>> mail reject@this.address
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match reject@this.address
554 match reject@this.address
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <reject@this.address>: Sender address rejected: match reject@this.address
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<reject@this.address>
554 <reject@this.address>: Sender address rejected: match reject@this.address
>>> mail Reject@this.address
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match reject@this.address
554 match reject@this.address
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <Reject@this.address>: Sender address rejected: match reject@this.address
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<Reject@this.address>
554 <Reject@this.address>: Sender address rejected: match reject@this.address
>>> mail foo@bad.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@bad.domain>
554 <foo@bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@Bad.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@Bad.domain>: Sender address rejected: match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@Bad.domain>
554 <foo@Bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@random.bad.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@random.bad.domain>: Sender address rejected: match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@random.bad.domain>
554 <foo@random.bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@friend.bad.domain
OK
>>> #
@ -126,8 +134,9 @@ OK
>>> client unknown 131.155.210.17
OK
>>> rcpt foo@watson.ibm.com
./smtpd_check: reject: RCPT from unknown[131.155.210.17]: 450 Cannot find your hostname, [131.155.210.17]
450 Cannot find your hostname, [131.155.210.17]
./smtpd_check: <queue id>: reject: RCPT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
./smtpd_check: <queue id>: reject: RCPT from unknown[131.155.210.17]: from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
>>> rcpt foo@watson.ibm.com
@ -135,8 +144,9 @@ OK
>>> client foo 123.123.123.123
OK
>>> rcpt foo@watson.ibm.com
./smtpd_check: reject: RCPT from foo[123.123.123.123]: 554 <foo@watson.ibm.com>: Relay access denied
554 <foo@watson.ibm.com>: Relay access denied
./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
>>> recipient_restrictions check_relay_domains
@ -150,26 +160,31 @@ OK
>>> client foo 123.123.123.123
OK
>>> rcpt foo@watson.ibm.com
./smtpd_check: reject: RCPT from foo[123.123.123.123]: 554 <foo@watson.ibm.com>: Relay access denied
554 <foo@watson.ibm.com>: Relay access denied
./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
>>> recipient_restrictions hash:./smtpd_check_access
OK
>>> mail bad-sender@any.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match bad-sender@
554 match bad-sender@
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<bad-sender@any.domain>
554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
>>> mail bad-sender@good.domain
OK
>>> mail reject@this.address
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match reject@this.address
554 match reject@this.address
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <reject@this.address>: Sender address rejected: match reject@this.address
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<reject@this.address>
554 <reject@this.address>: Sender address rejected: match reject@this.address
>>> mail foo@bad.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@bad.domain>
554 <foo@bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@random.bad.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@random.bad.domain>: Sender address rejected: match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@random.bad.domain>
554 <foo@random.bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@friend.bad.domain
OK
>>> #
@ -180,7 +195,8 @@ OK
>>> client spike.porcupine.org 168.100.189.2
OK
>>> client foo 127.0.0.2
./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com
./smtpd_check: <queue id>: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com
./smtpd_check: <queue id>: reject: CONNECT from foo[127.0.0.2]: from=<foo@friend.bad.domain>
554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com
>>> #
>>> # Hybrids
@ -190,8 +206,9 @@ OK
>>> client foo 131.155.210.17
OK
>>> rcpt foo@watson.ibm.com
./smtpd_check: reject: RCPT from foo[131.155.210.17]: 554 <foo@watson.ibm.com>: Relay access denied
554 <foo@watson.ibm.com>: Relay access denied
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
>>> recipient_restrictions check_client_access,hash:./smtpd_check_access,check_relay_domains
OK
>>> client foo 131.155.210.17
@ -203,11 +220,13 @@ OK
>>> recipient_restrictions check_helo_access,hash:./smtpd_check_access,check_relay_domains
OK
>>> helo bad.domain
./smtpd_check: reject: HELO from foo[131.155.210.17]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 554 <bad.domain>: Helo command rejected: match bad.domain
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo@friend.bad.domain>
554 <bad.domain>: Helo command rejected: match bad.domain
>>> rcpt foo@porcupine.org
./smtpd_check: reject: RCPT from foo[131.155.210.17]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 <bad.domain>: Helo command rejected: match bad.domain
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: from=<foo@friend.bad.domain> to=<foo@porcupine.org>
554 <bad.domain>: Helo command rejected: match bad.domain
>>> helo 131.155.210.17
./smtpd_check: warning: valid_hostname: numeric hostname: 131.155.210.17
OK
@ -216,11 +235,13 @@ OK
>>> recipient_restrictions check_sender_access,hash:./smtpd_check_access,check_relay_domains
OK
>>> mail foo@bad.domain
./smtpd_check: reject: MAIL from foo[131.155.210.17]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[131.155.210.17]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[131.155.210.17]: from=<foo@bad.domain>
554 <foo@bad.domain>: Sender address rejected: match bad.domain
>>> rcpt foo@porcupine.org
./smtpd_check: reject: RCPT from foo[131.155.210.17]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: from=<foo@bad.domain> to=<foo@porcupine.org>
554 <foo@bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@friend.bad.domain
OK
>>> rcpt foo@porcupine.org
@ -237,8 +258,9 @@ OK
>>> rcpt wietse@wzv.win.tue.nl
OK
>>> rcpt wietse@trouble.org
./smtpd_check: reject: RCPT from foo[131.155.210.17]: 554 <wietse@trouble.org> Access denied
554 <wietse@trouble.org> Access denied
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 <wietse@trouble.org>: Recipient address rejected: Access denied
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: from=<foo@friend.bad.domain> to=<wietse@trouble.org>
554 <wietse@trouble.org>: Recipient address rejected: Access denied
>>> rcpt wietse@porcupine.org
OK
>>> #
@ -257,15 +279,17 @@ OK
>>> mail foo@good.domain
OK
>>> rcpt foo@porcupine.org
./smtpd_check: reject: RCPT from foo[131.155.210.17]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 <bad.domain>: Helo command rejected: match bad.domain
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: from=<foo@good.domain> to=<foo@porcupine.org>
554 <bad.domain>: Helo command rejected: match bad.domain
>>> helo good.domain
OK
>>> mail foo@bad.domain
OK
>>> rcpt foo@porcupine.org
./smtpd_check: reject: RCPT from foo[131.155.210.17]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: from=<foo@bad.domain> to=<foo@porcupine.org>
554 <foo@bad.domain>: Sender address rejected: match bad.domain
>>> #
>>> # FQDN restrictions
>>> #
@ -280,28 +304,33 @@ OK
>>> helo foo.bar
OK
>>> helo foo
./smtpd_check: reject: HELO from foo[131.155.210.17]: 504 <foo>: need fully-qualified hostname
504 <foo>: need fully-qualified hostname
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 504 <foo>: Helo command rejected: need fully-qualified hostname
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo@bad.domain>
504 <foo>: Helo command rejected: need fully-qualified hostname
>>> mail foo@foo.bar.
OK
>>> mail foo@foo.bar
OK
>>> mail foo@foo
./smtpd_check: reject: MAIL from foo[131.155.210.17]: 504 <foo@foo>: need fully-qualified address
504 <foo@foo>: need fully-qualified address
./smtpd_check: <queue id>: reject: MAIL from foo[131.155.210.17]: 504 <foo@foo>: Sender address rejected: need fully-qualified address
./smtpd_check: <queue id>: reject: MAIL from foo[131.155.210.17]: from=<foo@foo>
504 <foo@foo>: Sender address rejected: need fully-qualified address
>>> mail foo
./smtpd_check: reject: MAIL from foo[131.155.210.17]: 504 <foo>: need fully-qualified address
504 <foo>: need fully-qualified address
./smtpd_check: <queue id>: reject: MAIL from foo[131.155.210.17]: 504 <foo>: Sender address rejected: need fully-qualified address
./smtpd_check: <queue id>: reject: MAIL from foo[131.155.210.17]: from=<foo>
504 <foo>: Sender address rejected: need fully-qualified address
>>> rcpt foo@foo.bar.
OK
>>> rcpt foo@foo.bar
OK
>>> rcpt foo@foo
./smtpd_check: reject: RCPT from foo[131.155.210.17]: 504 <foo@foo>: need fully-qualified address
504 <foo@foo>: need fully-qualified address
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 504 <foo@foo>: Recipient address rejected: need fully-qualified address
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: from=<foo> to=<foo@foo>
504 <foo@foo>: Recipient address rejected: need fully-qualified address
>>> rcpt foo
./smtpd_check: reject: RCPT from foo[131.155.210.17]: 504 <foo>: need fully-qualified address
504 <foo>: need fully-qualified address
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: 504 <foo>: Recipient address rejected: need fully-qualified address
./smtpd_check: <queue id>: reject: RCPT from foo[131.155.210.17]: from=<foo> to=<foo>
504 <foo>: Recipient address rejected: need fully-qualified address
>>> #
>>> # Numerical HELO checks
>>> #
@ -315,83 +344,99 @@ OK
>>> helo [321.255.255.255]
./smtpd_check: reject_invalid_hostaddr: [321.255.255.255]
./smtpd_check: warning: valid_hostaddr: invalid octet value: 321.255.255.255
./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[321.255.255.255]>: Invalid ip address
501 <[321.255.255.255]>: Invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <[321.255.255.255]>: Helo command rejected: invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
501 <[321.255.255.255]>: Helo command rejected: invalid ip address
>>> helo [0.255.255.255]
./smtpd_check: reject_invalid_hostaddr: [0.255.255.255]
./smtpd_check: warning: valid_hostaddr: bad initial octet value: 0.255.255.255
./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[0.255.255.255]>: Invalid ip address
501 <[0.255.255.255]>: Invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <[0.255.255.255]>: Helo command rejected: invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
501 <[0.255.255.255]>: Helo command rejected: invalid ip address
>>> helo [1.2.3.321]
./smtpd_check: reject_invalid_hostaddr: [1.2.3.321]
./smtpd_check: warning: valid_hostaddr: invalid octet value: 1.2.3.321
./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.321]>: Invalid ip address
501 <[1.2.3.321]>: Invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.321]>: Helo command rejected: invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
501 <[1.2.3.321]>: Helo command rejected: invalid ip address
>>> helo [1.2.3]
./smtpd_check: reject_invalid_hostaddr: [1.2.3]
./smtpd_check: warning: valid_hostaddr: invalid octet count: 1.2.3
./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3]>: Invalid ip address
501 <[1.2.3]>: Invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3]>: Helo command rejected: invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
501 <[1.2.3]>: Helo command rejected: invalid ip address
>>> helo [1.2.3.4.5]
./smtpd_check: reject_invalid_hostaddr: [1.2.3.4.5]
./smtpd_check: warning: valid_hostaddr: invalid octet count: 1.2.3.4.5
./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.4.5]>: Invalid ip address
501 <[1.2.3.4.5]>: Invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.4.5]>: Helo command rejected: invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
501 <[1.2.3.4.5]>: Helo command rejected: invalid ip address
>>> helo [1..2.3.4]
./smtpd_check: reject_invalid_hostaddr: [1..2.3.4]
./smtpd_check: warning: valid_hostaddr: misplaced dot: 1..2.3.4
./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[1..2.3.4]>: Invalid ip address
501 <[1..2.3.4]>: Invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <[1..2.3.4]>: Helo command rejected: invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
501 <[1..2.3.4]>: Helo command rejected: invalid ip address
>>> helo [.1.2.3.4]
./smtpd_check: reject_invalid_hostaddr: [.1.2.3.4]
./smtpd_check: warning: valid_hostaddr: misplaced dot: .1.2.3.4
./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[.1.2.3.4]>: Invalid ip address
501 <[.1.2.3.4]>: Invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <[.1.2.3.4]>: Helo command rejected: invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
501 <[.1.2.3.4]>: Helo command rejected: invalid ip address
>>> helo [1.2.3.4.5.]
./smtpd_check: reject_invalid_hostaddr: [1.2.3.4.5.]
./smtpd_check: warning: valid_hostaddr: misplaced dot: 1.2.3.4.5.
./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.4.5.]>: Invalid ip address
501 <[1.2.3.4.5.]>: Invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.4.5.]>: Helo command rejected: invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
501 <[1.2.3.4.5.]>: Helo command rejected: invalid ip address
>>> helo 1.2.3.4
./smtpd_check: reject_invalid_hostaddr: 1.2.3.4
OK
>>> helo 321.255.255.255
./smtpd_check: reject_invalid_hostaddr: 321.255.255.255
./smtpd_check: warning: valid_hostaddr: invalid octet value: 321.255.255.255
./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <321.255.255.255>: Invalid ip address
501 <321.255.255.255>: Invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <321.255.255.255>: Helo command rejected: invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
501 <321.255.255.255>: Helo command rejected: invalid ip address
>>> helo 0.255.255.255
./smtpd_check: reject_invalid_hostaddr: 0.255.255.255
./smtpd_check: warning: valid_hostaddr: bad initial octet value: 0.255.255.255
./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <0.255.255.255>: Invalid ip address
501 <0.255.255.255>: Invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <0.255.255.255>: Helo command rejected: invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
501 <0.255.255.255>: Helo command rejected: invalid ip address
>>> helo 1.2.3.321
./smtpd_check: reject_invalid_hostaddr: 1.2.3.321
./smtpd_check: warning: valid_hostaddr: invalid octet value: 1.2.3.321
./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <1.2.3.321>: Invalid ip address
501 <1.2.3.321>: Invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <1.2.3.321>: Helo command rejected: invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
501 <1.2.3.321>: Helo command rejected: invalid ip address
>>> helo 1.2.3
./smtpd_check: reject_invalid_hostaddr: 1.2.3
./smtpd_check: warning: valid_hostaddr: invalid octet count: 1.2.3
./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <1.2.3>: Invalid ip address
501 <1.2.3>: Invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <1.2.3>: Helo command rejected: invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
501 <1.2.3>: Helo command rejected: invalid ip address
>>> helo 1.2.3.4.5
./smtpd_check: reject_invalid_hostaddr: 1.2.3.4.5
./smtpd_check: warning: valid_hostaddr: invalid octet count: 1.2.3.4.5
./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <1.2.3.4.5>: Invalid ip address
501 <1.2.3.4.5>: Invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <1.2.3.4.5>: Helo command rejected: invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
501 <1.2.3.4.5>: Helo command rejected: invalid ip address
>>> helo 1..2.3.4
./smtpd_check: reject_invalid_hostaddr: 1..2.3.4
./smtpd_check: warning: valid_hostaddr: misplaced dot: 1..2.3.4
./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <1..2.3.4>: Invalid ip address
501 <1..2.3.4>: Invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <1..2.3.4>: Helo command rejected: invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
501 <1..2.3.4>: Helo command rejected: invalid ip address
>>> helo .1.2.3.4
./smtpd_check: reject_invalid_hostaddr: .1.2.3.4
./smtpd_check: warning: valid_hostaddr: misplaced dot: .1.2.3.4
./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <.1.2.3.4>: Invalid ip address
501 <.1.2.3.4>: Invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <.1.2.3.4>: Helo command rejected: invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
501 <.1.2.3.4>: Helo command rejected: invalid ip address
>>> helo 1.2.3.4.5.
./smtpd_check: reject_invalid_hostaddr: 1.2.3.4.5.
./smtpd_check: warning: valid_hostaddr: misplaced dot: 1.2.3.4.5.
./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <1.2.3.4.5.>: Invalid ip address
501 <1.2.3.4.5.>: Invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: 501 <1.2.3.4.5.>: Helo command rejected: invalid ip address
./smtpd_check: <queue id>: reject: HELO from foo[131.155.210.17]: from=<foo>
501 <1.2.3.4.5.>: Helo command rejected: invalid ip address

View File

@ -13,23 +13,23 @@ OK
>>> client_restrictions permit_mynetworks,reject_unknown_client,check_client_access,hash:./smtpd_check_access
OK
>>> client unknown 131.155.210.17
./smtpd_check: reject: CONNECT from unknown[131.155.210.17]: 450 Cannot find your hostname, [131.155.210.17]
450 Cannot find your hostname, [131.155.210.17]
./smtpd_check: <queue id>: reject: CONNECT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
>>> client random.bad.domain 123.123.123.123
./smtpd_check: reject: CONNECT from random.bad.domain[123.123.123.123]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: CONNECT from random.bad.domain[123.123.123.123]: 554 <random.bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
554 <random.bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
>>> client friend.bad.domain 123.123.123.123
OK
>>> client bad.domain 123.123.123.123
./smtpd_check: reject: CONNECT from bad.domain[123.123.123.123]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: CONNECT from bad.domain[123.123.123.123]: 554 <bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
554 <bad.domain[123.123.123.123]>: Client host rejected: match bad.domain
>>> client wzv.win.tue.nl 131.155.210.17
OK
>>> client aa.win.tue.nl 131.155.210.18
./smtpd_check: reject: CONNECT from aa.win.tue.nl[131.155.210.18]: 554 match 131.155.210
554 match 131.155.210
./smtpd_check: <queue id>: reject: CONNECT from aa.win.tue.nl[131.155.210.18]: 554 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210
554 <aa.win.tue.nl[131.155.210.18]>: Client host rejected: match 131.155.210
>>> client_restrictions permit_mynetworks
OK
>>> #
@ -40,23 +40,23 @@ OK
>>> client unknown 131.155.210.17
OK
>>> helo foo.
./smtpd_check: reject: HELO from unknown[131.155.210.17]: 450 Cannot find your hostname, [131.155.210.17]
450 Cannot find your hostname, [131.155.210.17]
./smtpd_check: <queue id>: reject: HELO from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client foo 123.123.123.123
OK
>>> helo foo.
./smtpd_check: reject: HELO from foo[123.123.123.123]: 450 <foo.>: Host not found
450 <foo.>: Host not found
./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 <foo.>: Helo command rejected: Host not found
450 <foo.>: Helo command rejected: Host not found
>>> helo foo
./smtpd_check: reject: HELO from foo[123.123.123.123]: 450 <foo>: Host not found
450 <foo>: Host not found
./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 <foo>: Helo command rejected: Host not found
450 <foo>: Helo command rejected: Host not found
>>> helo spike.porcupine.org
OK
>>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,check_helo_access,hash:./smtpd_check_access
OK
>>> helo random.bad.domain
./smtpd_check: reject: HELO from foo[123.123.123.123]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 554 <random.bad.domain>: Helo command rejected: match bad.domain
554 <random.bad.domain>: Helo command rejected: match bad.domain
>>> helo friend.bad.domain
OK
>>> #
@ -67,8 +67,9 @@ OK
>>> client unknown 131.155.210.17
OK
>>> mail foo@watson.ibm.com
./smtpd_check: reject: MAIL from unknown[131.155.210.17]: 450 Cannot find your hostname, [131.155.210.17]
450 Cannot find your hostname, [131.155.210.17]
./smtpd_check: <queue id>: reject: MAIL from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
./smtpd_check: <queue id>: reject: MAIL from unknown[131.155.210.17]: from=<foo@watson.ibm.com>
450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
>>> mail foo@watson.ibm.com
@ -82,30 +83,37 @@ OK
>>> mail foo@watson.ibm.com
OK
>>> mail foo@bad.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 450 <bad.domain>: Domain not found
450 <bad.domain>: Domain not found
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 450 <foo@bad.domain>: Sender address rejected: Domain not found
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@bad.domain>
450 <foo@bad.domain>: Sender address rejected: Domain not found
>>> sender_restrictions check_sender_access,hash:./smtpd_check_access
OK
>>> mail bad-sender@any.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match bad-sender@
554 match bad-sender@
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<bad-sender@any.domain>
554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
>>> mail bad-sender@good.domain
OK
>>> mail reject@this.address
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match reject@this.address
554 match reject@this.address
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <reject@this.address>: Sender address rejected: match reject@this.address
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<reject@this.address>
554 <reject@this.address>: Sender address rejected: match reject@this.address
>>> mail Reject@this.address
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match reject@this.address
554 match reject@this.address
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <Reject@this.address>: Sender address rejected: match reject@this.address
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<Reject@this.address>
554 <Reject@this.address>: Sender address rejected: match reject@this.address
>>> mail foo@bad.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@bad.domain>
554 <foo@bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@Bad.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@Bad.domain>: Sender address rejected: match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@Bad.domain>
554 <foo@Bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@random.bad.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@random.bad.domain>: Sender address rejected: match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@random.bad.domain>
554 <foo@random.bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@friend.bad.domain
OK
>>> #
@ -116,8 +124,9 @@ OK
>>> client unknown 131.155.210.17
OK
>>> rcpt foo@watson.ibm.com
./smtpd_check: reject: RCPT from unknown[131.155.210.17]: 450 Cannot find your hostname, [131.155.210.17]
450 Cannot find your hostname, [131.155.210.17]
./smtpd_check: <queue id>: reject: RCPT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17]
./smtpd_check: <queue id>: reject: RCPT from unknown[131.155.210.17]: from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
450 Client host rejected: cannot find your hostname, [131.155.210.17]
>>> client unknown 168.100.189.13
OK
>>> rcpt foo@watson.ibm.com
@ -125,8 +134,9 @@ OK
>>> client foo 123.123.123.123
OK
>>> rcpt foo@watson.ibm.com
./smtpd_check: reject: RCPT from foo[123.123.123.123]: 554 <foo@watson.ibm.com>: Relay access denied
554 <foo@watson.ibm.com>: Relay access denied
./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
>>> recipient_restrictions check_relay_domains
@ -140,26 +150,31 @@ OK
>>> client foo 123.123.123.123
OK
>>> rcpt foo@watson.ibm.com
./smtpd_check: reject: RCPT from foo[123.123.123.123]: 554 <foo@watson.ibm.com>: Relay access denied
554 <foo@watson.ibm.com>: Relay access denied
./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: 554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
./smtpd_check: <queue id>: reject: RCPT from foo[123.123.123.123]: from=<foo@friend.bad.domain> to=<foo@watson.ibm.com>
554 <foo@watson.ibm.com>: Recipient address rejected: Relay access denied
>>> rcpt foo@porcupine.org
OK
>>> recipient_restrictions check_recipient_access,hash:./smtpd_check_access
OK
>>> mail bad-sender@any.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match bad-sender@
554 match bad-sender@
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<bad-sender@any.domain>
554 <bad-sender@any.domain>: Sender address rejected: match bad-sender@
>>> mail bad-sender@good.domain
OK
>>> mail reject@this.address
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match reject@this.address
554 match reject@this.address
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <reject@this.address>: Sender address rejected: match reject@this.address
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<reject@this.address>
554 <reject@this.address>: Sender address rejected: match reject@this.address
>>> mail foo@bad.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@bad.domain>: Sender address rejected: match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@bad.domain>
554 <foo@bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@random.bad.domain
./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 match bad.domain
554 match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: 554 <foo@random.bad.domain>: Sender address rejected: match bad.domain
./smtpd_check: <queue id>: reject: MAIL from foo[123.123.123.123]: from=<foo@random.bad.domain>
554 <foo@random.bad.domain>: Sender address rejected: match bad.domain
>>> mail foo@friend.bad.domain
OK
>>> #
@ -170,7 +185,8 @@ OK
>>> client spike.porcupine.org 168.100.189.2
OK
>>> client foo 127.0.0.2
./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com
./smtpd_check: <queue id>: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com
./smtpd_check: <queue id>: reject: CONNECT from foo[127.0.0.2]: from=<foo@friend.bad.domain>
554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com
>>> #
>>> # unknown sender/recipient domain
@ -184,10 +200,12 @@ OK
>>> rcpt wietse@porcupine.org
OK
>>> rcpt wietse@no.recipient.domain
./smtpd_check: reject: RCPT from foo[127.0.0.2]: 554 <no.recipient.domain>: Domain not found
554 <no.recipient.domain>: Domain not found
./smtpd_check: <queue id>: reject: RCPT from foo[127.0.0.2]: 554 <wietse@no.recipient.domain>: Recipient address rejected: Domain not found
./smtpd_check: <queue id>: reject: RCPT from foo[127.0.0.2]: from=<wietse@porcupine.org> to=<wietse@no.recipient.domain>
554 <wietse@no.recipient.domain>: Recipient address rejected: Domain not found
>>> mail wietse@no.sender.domain
OK
>>> rcpt wietse@porcupine.org
./smtpd_check: reject: RCPT from foo[127.0.0.2]: 554 <no.sender.domain>: Domain not found
554 <no.sender.domain>: Domain not found
./smtpd_check: <queue id>: reject: RCPT from foo[127.0.0.2]: 554 <wietse@no.sender.domain>: Sender address rejected: Domain not found
./smtpd_check: <queue id>: reject: RCPT from foo[127.0.0.2]: from=<wietse@no.sender.domain> to=<wietse@porcupine.org>
554 <wietse@no.sender.domain>: Sender address rejected: Domain not found

View File

@ -53,6 +53,7 @@
#include <mymalloc.h>
#include <vstream.h>
#include <name_mask.h>
#include <stringops.h>
/* Global library. */
@ -80,6 +81,7 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream,
state->buffer = vstring_alloc(100);
state->name = mystrdup(name);
state->addr = mystrdup(addr);
state->namaddr = concatenate(name, "[", addr, "]", (char *) 0);
state->error_count = 0;
state->error_mask = 0;
state->notify_mask = name_mask(mail_error_masks, var_notify_classes);
@ -118,4 +120,6 @@ void smtpd_state_reset(SMTPD_STATE *state)
myfree(state->name);
if (state->addr)
myfree(state->addr);
if (state->namaddr)
myfree(state->namaddr);
}

View File

@ -41,7 +41,6 @@
/* .IP "-R interval"
/* Wait for a random period of time 0 <= n <= interval between messages.
/* Suspending one thread does not affect other delivery threads.
/* threads keep running.
/* .IP "-w interval"
/* Wait a fixed time between messages.
/* Suspending one thread does not affect other delivery threads.