From 138a7cbb806eb642fc2271eee701dec5846b92d5 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Sun, 9 May 1999 00:00:00 -0500 Subject: [PATCH] snapshot-19990509 --- postfix/HISTORY | 16 +- postfix/RELEASE_NOTES | 36 ++-- postfix/conf/main.cf.default | 2 +- postfix/global/mail_params.h | 4 +- postfix/global/mail_version.h | 2 +- postfix/html/faq.html | 38 +++- postfix/html/goals.html | 5 +- postfix/html/local.8.html | 324 +++++++++++++++++++------------- postfix/html/security.html | 10 +- postfix/local/command.c | 36 ++-- postfix/local/local.c | 39 ++-- postfix/man/man8/local.8 | 46 ++--- postfix/smtpd/Makefile.in | 1 + postfix/smtpd/smtpd.c | 84 +++++---- postfix/smtpd/smtpd.h | 1 + postfix/smtpd/smtpd_check.c | 254 ++++++++++++++++--------- postfix/smtpd/smtpd_check.ref | 259 ++++++++++++++----------- postfix/smtpd/smtpd_check.ref2 | 120 +++++++----- postfix/smtpd/smtpd_state.c | 4 + postfix/smtpstone/smtp-source.c | 1 - 20 files changed, 786 insertions(+), 496 deletions(-) diff --git a/postfix/HISTORY b/postfix/HISTORY index b2f54c9f6..005c7eacb 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -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. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 3c0413232..00f110894 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -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. diff --git a/postfix/conf/main.cf.default b/postfix/conf/main.cf.default index 102876586..c0a62a28e 100644 --- a/postfix/conf/main.cf.default +++ b/postfix/conf/main.cf.default @@ -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 diff --git a/postfix/global/mail_params.h b/postfix/global/mail_params.h index a6650583d..a51fc0e17 100644 --- a/postfix/global/mail_params.h +++ b/postfix/global/mail_params.h @@ -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 "" diff --git a/postfix/global/mail_version.h b/postfix/global/mail_version.h index 540f9a01f..f52bb08cb 100644 --- a/postfix/global/mail_version.h +++ b/postfix/global/mail_version.h @@ -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 diff --git a/postfix/html/faq.html b/postfix/html/faq.html index aabe60783..9070ba017 100644 --- a/postfix/html/faq.html +++ b/postfix/html/faq.html @@ -395,9 +395,41 @@ and /usr/lib/Mail.rc). With mailing lists, Delivered-To: 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 FEATURE -CONTROL section in the documentation of the local delivery agent. +in outbound mail. The recommended solution is to use a regular +expression-based filter at the SMTP port: + +

+ +

+ +
/etc/postfix/main.cf: + +
+ +
smtpd_recipients = ... regexp:/etc/postfix/access_regexp ... + +
smtpd_recipients = ... pcre:/etc/postfix/access_regexp ... + +
+ +

+ +

/etc/postfix/access_regexp: + +
+ +
/^(.*)-outgoing@(.*)/ 554 Use $1@$2 instead + +
+ +
+ +

+ +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.

diff --git a/postfix/html/goals.html b/postfix/html/goals.html index 1b8436d52..5dbe2000a 100644 --- a/postfix/html/goals.html +++ b/postfix/html/goals.html @@ -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 set-uid. +filters sender-provided information before exporting it via +environment variables. Last but not least, no Postfix program is +set-uid. diff --git a/postfix/html/local.8.html b/postfix/html/local.8.html index 099d80630..99a318052 100644 --- a/postfix/html/local.8.html +++ b/postfix/html/local.8.html @@ -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 - default_privs). The command is subject to interpolation - of $user (recipient username), $home (recipient home - directory), $shell (recipient shell), $recipient (complete - recipient address), $extension (recipient address exten- - sion), $domain (recipient domain), mailbox (entire recipi- - ent address localpart) and $recipient_delimiter. The forms - ${name?value} and ${name:value} expand conditionally to - value when $name is (is not) defined. In the result of - name expansion, characters that have special meaning to - the shell are replaced by underscores. The list of legal - characters is specified with the command_expansion_filter - configuration parameter. + default_privs). - Mailbox delivery can be delegated to alternative message + Mailbox delivery can be delegated to alternative message + transports specified in the master.cf file. The mail- + box_transport 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 fallback_transport 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 local dae- + mon prepends a "From sender time_stamp" envelope header to + each message, prepends a Delivered-To: header with the @@ -137,60 +137,60 @@ LOCAL(8) LOCAL(8) LOCAL(8) LOCAL(8) - transports specified in the master.cf file. The mail- - box_transport 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 fallback_transport 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 local dae- - mon prepends a "From sender time_stamp" envelope header to - each message, prepends a Delivered-To: header with the envelope recipient address, prepends a Return-Path: header - with the envelope sender address, prepends a > character - to lines beginning with "From ", and appends an empty - line. The mailbox is locked for exclusive access while - delivery is in progress. In case of problems, an attempt + with the envelope sender address, prepends a > character + to lines beginning with "From ", and appends an empty + line. The mailbox is locked for exclusive access while + delivery is in progress. In case of problems, an attempt is made to truncate the mailbox to its original length. In the case of maildir delivery, the local daemon prepends a Delivered-To: header with the envelope recipient address - and prepends a Return-Path: header with the envelope + and prepends a Return-Path: header with the envelope sender address. EXTERNAL COMMAND DELIVERY - The allow_mail_to_commands configuration parameter - restricts delivery to external commands. The default set- - ting (alias, forward) forbids command destinations in + The allow_mail_to_commands configuration parameter + restricts delivery to external commands. The default set- + ting (alias, forward) forbids command destinations in :include: files. - The command is executed directly where possible. Assis- - tance by the shell (/bin/sh on UNIX systems) is used only - when the command contains shell magic characters, or when + The command is executed directly where possible. Assis- + tance by the shell (/bin/sh on UNIX systems) is used only + when the command contains shell magic characters, or when the command invokes a shell built-in command. - A limited amount of command output (standard output and - standard error) is captured for inclusion with non-deliv- - ery status reports. A command is forcibly terminated if - it does not complete within command_time_limit seconds. - Command exit status codes are expected to follow the con- + A limited amount of command output (standard output and + standard error) is captured for inclusion with non-deliv- + ery status reports. A command is forcibly terminated if + it does not complete within command_time_limit seconds. + Command exit status codes are expected to follow the con- ventions defined in <sysexits.h>. - When mail is delivered on behalf of a user, the HOME, LOG- - NAME, and SHELL 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 command_expan- + sion_filter configuration parameter. + + SHELL The recipient user's login shell. + + HOME The recipient user's home directory. + + USER The bare recipient name. + + EXTENSION + The optional recipient address extension. + + DOMAIN The recipient address domain part. + + LOGNAME + The bare recipient name. + The PATH environment variable is always reset to a system- dependent default path, and the TZ (time zone) environment variable is always passed on without change. - The current working directory is the mail queue directory. - - The local daemon prepends a "From sender time_stamp" enve- - lope header to each message, prepends a Delivered-To: - header with the recipient envelope address, prepends a - Return-Path: header with the sender envelope address, and - appends an empty line. @@ -203,60 +203,60 @@ LOCAL(8) LOCAL(8) LOCAL(8) LOCAL(8) + The current working directory is the mail queue directory. + + The local daemon prepends a "From sender time_stamp" enve- + lope header to each message, prepends a Delivered-To: + header with the recipient envelope address, prepends a + Return-Path: header with the sender envelope address, and + appends an empty line. + EXTERNAL FILE DELIVERY - The allow_mail_to_files configuration parameter restricts - delivery to external files. The default setting (alias, - forward) forbids file destinations in :include: files. + The allow_mail_to_files configuration parameter restricts + delivery to external files. The default setting (alias, + forward) forbids file destinations in :include: files. Specify a pathname ending in / for qmail-compatible maildir delivery. The local daemon prepends a "From sender time_stamp" enve- - lope header to each message, prepends a Delivered-To: - header with the recipient envelope address, prepends a > - character to lines beginning with "From ", and appends an - empty line. The envelope sender address is available in - the Return-Path: header. When the destination is a regu- + lope header to each message, prepends a Delivered-To: + header with the recipient envelope address, prepends a > + character to lines beginning with "From ", and appends an + empty line. The envelope sender address is available in + the Return-Path: header. When the destination is a regu- lar file, it is locked for exclusive access while delivery is in progress. In case of problems, an attempt is made to truncate a regular file to its original length. In the case of maildir delivery, the local daemon prepends - a Delivered-To: header with the envelope recipient - address. The envelope sender address is available in the + a Delivered-To: header with the envelope recipient + address. The envelope sender address is available in the Return-Path: header. ADDRESS EXTENSION - The optional recipient_delimiter configuration parameter - specifies how to separate address extensions from local + The optional recipient_delimiter configuration parameter + specifies how to separate address extensions from local recipient names. - For example, with "recipient_delimiter = +", mail for - name+foo is delivered to the alias name+foo or to the - alias name, to the destinations listed in ~name/.for- + For example, with "recipient_delimiter = +", mail for + name+foo is delivered to the alias name+foo or to the + alias name, to the destinations listed in ~name/.for- ward+foo or in ~name/.forward, to the mailbox owned by the user name, or it is sent back as undeliverable. - In all cases the local daemon prepends a `Delivered-To: + In all cases the local daemon prepends a `Delivered-To: name+foo' header line. DELIVERY RIGHTS - Deliveries to external files and external commands are + Deliveries to external files and external commands are made with the rights of the receiving user on whose behalf - the delivery is made. In the absence of a user context, - the local daemon uses the owner rights of the :include: + the delivery is made. In the absence of a user context, + the local daemon uses the owner rights of the :include: file or alias database. When those files are owned by the superuser, delivery is made with the rights specified with the default_privs configuration parameter. -STANDARDS - RFC 822 (ARPA Internet Text Messages) -DIAGNOSTICS - Problems and transactions are logged to syslogd(8). Cor- - rupted message files are marked so that the queue manager - can move them to the corrupt queue afterwards. - - Depending on the setting of the notify_classes parameter, @@ -269,24 +269,33 @@ LOCAL(8) LOCAL(8) LOCAL(8) LOCAL(8) - the postmaster is notified of bounces and of other trou- +STANDARDS + RFC 822 (ARPA Internet Text Messages) + +DIAGNOSTICS + Problems and transactions are logged to syslogd(8). Cor- + rupted message files are marked so that the queue manager + can move them to the corrupt queue afterwards. + + Depending on the setting of the notify_classes parameter, + the postmaster is notified of bounces and of other trou- ble. BUGS - For security reasons, the message delivery status of - external commands or of external files is never check- + For security reasons, the message delivery status of + external commands or of external files is never check- pointed to file. As a result, the program may occasionally deliver more than once to a command or external file. Bet- ter safe than sorry. - Mutually-recursive aliases or ~/.forward files are not - detected early. The resulting mail forwarding loop is + Mutually-recursive aliases or ~/.forward files are not + detected early. The resulting mail forwarding loop is broken by the use of the Delivered-To: message header. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant - to this program. See the Postfix main.cf file for syntax - details and for default values. Use the postfix reload + The following main.cf parameters are especially relevant + to this program. See the Postfix main.cf file for syntax + details and for default values. Use the postfix reload command after a configuration change. Miscellaneous @@ -298,10 +307,10 @@ LOCAL(8) LOCAL(8) ject to $name expansion. local_command_shell - Shell to use for external command execution (for - example, /some/where/smrsh -c). When a shell is + Shell to use for external command execution (for + example, /some/where/smrsh -c). When a shell is specified, it is invoked even when the command con- - tains no shell built-in commands or meta charac- + tains no shell built-in commands or meta charac- ters. owner_request_special @@ -314,15 +323,6 @@ LOCAL(8) LOCAL(8) Mailbox delivery fallback_transport Message transport for recipients that are not found - in the UNIX passwd database. This parameter over- - rides luser_relay. - - home_mailbox - Pathname of a mailbox relative to a user's home - directory. Specify a path ending in / for maildir- - style delivery. - - @@ -335,35 +335,43 @@ LOCAL(8) LOCAL(8) LOCAL(8) LOCAL(8) + in the UNIX passwd database. This parameter over- + rides luser_relay. + + home_mailbox + Pathname of a mailbox relative to a user's home + directory. Specify a path ending in / for maildir- + style delivery. + luser_relay - Destination (@domain or address) for non-existent - users. The address is subjected to $name expan- + Destination (@domain or address) for non-existent + users. The address is subjected to $name expan- sion. mail_spool_directory - Directory with UNIX-style mailboxes. The default + Directory with UNIX-style mailboxes. The default pathname is system dependent. mailbox_command - External command to use for mailbox delivery. The + External command to use for mailbox delivery. The command executes with the recipient privileges - (exception: root). The string is subject to $name + (exception: root). The string is subject to $name expansions. mailbox_transport - Message transport to use for mailbox delivery to + Message transport to use for mailbox delivery to all local recipients, whether or not they are found - in the UNIX passwd database. This parameter over- - rides all other configuration parameters that con- + in the UNIX passwd database. This parameter over- + rides all other configuration parameters that con- trol mailbox delivery, including luser_relay. Locking controls deliver_lock_attempts - Limit the number of attempts to acquire an exclu- + Limit the number of attempts to acquire an exclu- sive lock on a mailbox or external file. deliver_lock_delay - Time in seconds between successive attempts to + Time in seconds between successive attempts to acquire an exclusive lock. stale_lock_time @@ -371,25 +379,17 @@ LOCAL(8) LOCAL(8) Resource controls command_time_limit - Limit the amount of time for delivery to external + Limit the amount of time for delivery to external command. duplicate_filter_limit - Limit the size of the duplicate filter for results + Limit the size of the duplicate filter for results from alias etc. expansion. line_length_limit - Limit the amount of memory used for processing a + Limit the amount of memory used for processing a partial input line. - local_destination_concurrency_limit - Limit the number of parallel deliveries to the same - user. The default limit is taken from the - default_destination_concurrency_limit parameter. - - local_destination_recipient_limit - Limit the number of recipients per message - 6 @@ -401,37 +401,44 @@ LOCAL(8) LOCAL(8) LOCAL(8) LOCAL(8) - delivery. The default limit is taken from the + local_destination_concurrency_limit + Limit the number of parallel deliveries to the same + user. The default limit is taken from the + default_destination_concurrency_limit parameter. + + local_destination_recipient_limit + Limit the number of recipients per message deliv- + ery. The default limit is taken from the default_destination_recipient_limit parameter. Security controls allow_mail_to_commands - Restrict the usage of mail delivery to external + Restrict the usage of mail delivery to external command. allow_mail_to_files - Restrict the usage of mail delivery to external + Restrict the usage of mail delivery to external file. command_expansion_filter - What characters are allowed to appear in $name - expansions of mailbox_command. Illegal characters + What characters are allowed to appear in $name + expansions of mailbox_command. Illegal characters are replaced by underscores. default_privs - Default rights for delivery to external file or + Default rights for delivery to external file or command. forward_expansion_filter - What characters are allowed to appear in $name - expansions of forward_path. Illegal characters are + What characters are allowed to appear in $name + expansions of forward_path. Illegal characters are replaced by underscores. HISTORY - The Delivered-To: header appears in the qmail system by + The Delivered-To: header appears in the qmail system by Daniel Bernstein. - The maildir structure appears in the qmail system by + The maildir structure appears in the qmail system by Daniel Bernstein. SEE ALSO @@ -442,12 +449,24 @@ LOCAL(8) LOCAL(8) qmgr(8) queue manager LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) 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 diff --git a/postfix/html/security.html b/postfix/html/security.html index 3dfcc7962..0619ef51e 100644 --- a/postfix/html/security.html +++ b/postfix/html/security.html @@ -116,11 +116,11 @@ decisions on the basis of first-hand information.

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: don't let any data -from the network near a shell. +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: don't let any data from the network near a +shell. Filtering is the best we can do.

Large inputs

diff --git a/postfix/local/command.c b/postfix/local/command.c index 4d61c7284..e96bc3af6 100644 --- a/postfix/local/command.c +++ b/postfix/local/command.c @@ -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 #include #include +#include /* Utility library. */ @@ -57,7 +61,6 @@ #include #include #include -#include /* 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. diff --git a/postfix/local/local.c b/postfix/local/local.c index a910855be..90c61da71 100644 --- a/postfix/local/local.c +++ b/postfix/local/local.c @@ -40,9 +40,9 @@ /* \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 +/* 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. /* /* An alias or ~/.\fBforward\fR file may list any combination of external @@ -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. diff --git a/postfix/man/man8/local.8 b/postfix/man/man8/local.8 index 7c9c5dea0..bb41b82b0 100644 --- a/postfix/man/man8/local.8 +++ b/postfix/man/man8/local.8 @@ -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 diff --git a/postfix/smtpd/Makefile.in b/postfix/smtpd/Makefile.in index ff849ac27..ca0276f1a 100644 --- a/postfix/smtpd/Makefile.in +++ b/postfix/smtpd/Makefile.in @@ -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 diff --git a/postfix/smtpd/smtpd.c b/postfix/smtpd/smtpd.c index 1ec0f2759..44322368b 100644 --- a/postfix/smtpd/smtpd.c +++ b/postfix/smtpd/smtpd.c @@ -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,10 +533,25 @@ 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) { - smtpd_chat_reply(state, "%s", err); - return (-1); + 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); + } } /* @@ -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,10 +862,20 @@ 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) { - smtpd_chat_reply(state, "%s", err); - return (-1); + 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); + } } /* @@ -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); - } + smtpd_chat_reply(&state, "220 %s", var_smtpd_banner); + msg_info("connect from %s[%s]", state.name, state.addr); /* * Provide the SMTP service. diff --git a/postfix/smtpd/smtpd.h b/postfix/smtpd/smtpd.h index f7c30615b..5d6623fe9 100644 --- a/postfix/smtpd/smtpd.h +++ b/postfix/smtpd/smtpd.h @@ -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; diff --git a/postfix/smtpd/smtpd_check.c b/postfix/smtpd/smtpd_check.c index d25e29da2..677fa8ee5 100644 --- a/postfix/smtpd/smtpd_check.c +++ b/postfix/smtpd/smtpd_check.c @@ -217,6 +217,7 @@ #include #include #include +#include #ifdef STRCASECMP_IN_STRINGS_H #include @@ -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 = ""; /* * 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; diff --git a/postfix/smtpd/smtpd_check.ref b/postfix/smtpd/smtpd_check.ref index 8bf92053f..7f26c23aa 100644 --- a/postfix/smtpd/smtpd_check.ref +++ b/postfix/smtpd/smtpd_check.ref @@ -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: : 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: : reject: CONNECT from random.bad.domain[123.123.123.123]: 554 : Client host rejected: match bad.domain +554 : 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: : reject: CONNECT from bad.domain[123.123.123.123]: 554 : Client host rejected: match bad.domain +554 : 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: : reject: CONNECT from aa.win.tue.nl[131.155.210.18]: 554 : Client host rejected: match 131.155.210 +554 : 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: : 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 : Host not found -450 : Host not found +./smtpd_check: : reject: HELO from foo[123.123.123.123]: 450 : Helo command rejected: Host not found +450 : Helo command rejected: Host not found >>> helo foo -./smtpd_check: reject: HELO from foo[123.123.123.123]: 450 : Host not found -450 : Host not found +./smtpd_check: : reject: HELO from foo[123.123.123.123]: 450 : Helo command rejected: Host not found +450 : 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: : reject: HELO from foo[123.123.123.123]: 554 : Helo command rejected: match bad.domain +554 : 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: : 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: : reject: MAIL from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17] +./smtpd_check: : reject: MAIL from unknown[131.155.210.17]: from= +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 : Domain not found -450 : Domain not found +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: 450 : Sender address rejected: Domain not found +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +450 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad-sender@ +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match reject@this.address +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match reject@this.address +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad.domain +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad.domain +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad.domain +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: RCPT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17] +./smtpd_check: : reject: RCPT from unknown[131.155.210.17]: from= to= +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 : Relay access denied -554 : Relay access denied +./smtpd_check: : reject: RCPT from foo[123.123.123.123]: 554 : Recipient address rejected: Relay access denied +./smtpd_check: : reject: RCPT from foo[123.123.123.123]: from= to= +554 : 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 : Relay access denied -554 : Relay access denied +./smtpd_check: : reject: RCPT from foo[123.123.123.123]: 554 : Recipient address rejected: Relay access denied +./smtpd_check: : reject: RCPT from foo[123.123.123.123]: from= to= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad-sender@ +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match reject@this.address +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad.domain +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad.domain +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com +./smtpd_check: : reject: CONNECT from foo[127.0.0.2]: from= 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 : Relay access denied -554 : Relay access denied +./smtpd_check: : reject: RCPT from foo[131.155.210.17]: 554 : Recipient address rejected: Relay access denied +./smtpd_check: : reject: RCPT from foo[131.155.210.17]: from= to= +554 : 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: : reject: HELO from foo[131.155.210.17]: 554 : Helo command rejected: match bad.domain +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +554 : 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: : reject: RCPT from foo[131.155.210.17]: 554 : Helo command rejected: match bad.domain +./smtpd_check: : reject: RCPT from foo[131.155.210.17]: from= to= +554 : 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: : reject: MAIL from foo[131.155.210.17]: 554 : Sender address rejected: match bad.domain +./smtpd_check: : reject: MAIL from foo[131.155.210.17]: from= +554 : 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: : reject: RCPT from foo[131.155.210.17]: 554 : Sender address rejected: match bad.domain +./smtpd_check: : reject: RCPT from foo[131.155.210.17]: from= to= +554 : 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 Access denied -554 Access denied +./smtpd_check: : reject: RCPT from foo[131.155.210.17]: 554 : Recipient address rejected: Access denied +./smtpd_check: : reject: RCPT from foo[131.155.210.17]: from= to= +554 : 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: : reject: RCPT from foo[131.155.210.17]: 554 : Helo command rejected: match bad.domain +./smtpd_check: : reject: RCPT from foo[131.155.210.17]: from= to= +554 : 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: : reject: RCPT from foo[131.155.210.17]: 554 : Sender address rejected: match bad.domain +./smtpd_check: : reject: RCPT from foo[131.155.210.17]: from= to= +554 : 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 : need fully-qualified hostname -504 : need fully-qualified hostname +./smtpd_check: : reject: HELO from foo[131.155.210.17]: 504 : Helo command rejected: need fully-qualified hostname +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +504 : 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 : need fully-qualified address -504 : need fully-qualified address +./smtpd_check: : reject: MAIL from foo[131.155.210.17]: 504 : Sender address rejected: need fully-qualified address +./smtpd_check: : reject: MAIL from foo[131.155.210.17]: from= +504 : Sender address rejected: need fully-qualified address >>> mail foo -./smtpd_check: reject: MAIL from foo[131.155.210.17]: 504 : need fully-qualified address -504 : need fully-qualified address +./smtpd_check: : reject: MAIL from foo[131.155.210.17]: 504 : Sender address rejected: need fully-qualified address +./smtpd_check: : reject: MAIL from foo[131.155.210.17]: from= +504 : 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 : need fully-qualified address -504 : need fully-qualified address +./smtpd_check: : reject: RCPT from foo[131.155.210.17]: 504 : Recipient address rejected: need fully-qualified address +./smtpd_check: : reject: RCPT from foo[131.155.210.17]: from= to= +504 : Recipient address rejected: need fully-qualified address >>> rcpt foo -./smtpd_check: reject: RCPT from foo[131.155.210.17]: 504 : need fully-qualified address -504 : need fully-qualified address +./smtpd_check: : reject: RCPT from foo[131.155.210.17]: 504 : Recipient address rejected: need fully-qualified address +./smtpd_check: : reject: RCPT from foo[131.155.210.17]: from= to= +504 : 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: : reject: HELO from foo[131.155.210.17]: 501 <[321.255.255.255]>: Helo command rejected: invalid ip address +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +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: : reject: HELO from foo[131.155.210.17]: 501 <[0.255.255.255]>: Helo command rejected: invalid ip address +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +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: : reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.321]>: Helo command rejected: invalid ip address +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +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: : reject: HELO from foo[131.155.210.17]: 501 <[1.2.3]>: Helo command rejected: invalid ip address +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +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: : reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.4.5]>: Helo command rejected: invalid ip address +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +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: : reject: HELO from foo[131.155.210.17]: 501 <[1..2.3.4]>: Helo command rejected: invalid ip address +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +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: : reject: HELO from foo[131.155.210.17]: 501 <[.1.2.3.4]>: Helo command rejected: invalid ip address +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +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: : reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.4.5.]>: Helo command rejected: invalid ip address +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +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: : reject: HELO from foo[131.155.210.17]: 501 <321.255.255.255>: Helo command rejected: invalid ip address +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +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: : reject: HELO from foo[131.155.210.17]: 501 <0.255.255.255>: Helo command rejected: invalid ip address +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +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: : reject: HELO from foo[131.155.210.17]: 501 <1.2.3.321>: Helo command rejected: invalid ip address +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +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: : reject: HELO from foo[131.155.210.17]: 501 <1.2.3>: Helo command rejected: invalid ip address +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +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: : reject: HELO from foo[131.155.210.17]: 501 <1.2.3.4.5>: Helo command rejected: invalid ip address +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +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: : reject: HELO from foo[131.155.210.17]: 501 <1..2.3.4>: Helo command rejected: invalid ip address +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +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: : reject: HELO from foo[131.155.210.17]: 501 <.1.2.3.4>: Helo command rejected: invalid ip address +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +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: : reject: HELO from foo[131.155.210.17]: 501 <1.2.3.4.5.>: Helo command rejected: invalid ip address +./smtpd_check: : reject: HELO from foo[131.155.210.17]: from= +501 <1.2.3.4.5.>: Helo command rejected: invalid ip address diff --git a/postfix/smtpd/smtpd_check.ref2 b/postfix/smtpd/smtpd_check.ref2 index 5d099bda4..12b3b352a 100644 --- a/postfix/smtpd/smtpd_check.ref2 +++ b/postfix/smtpd/smtpd_check.ref2 @@ -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: : 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: : reject: CONNECT from random.bad.domain[123.123.123.123]: 554 : Client host rejected: match bad.domain +554 : 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: : reject: CONNECT from bad.domain[123.123.123.123]: 554 : Client host rejected: match bad.domain +554 : 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: : reject: CONNECT from aa.win.tue.nl[131.155.210.18]: 554 : Client host rejected: match 131.155.210 +554 : 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: : 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 : Host not found -450 : Host not found +./smtpd_check: : reject: HELO from foo[123.123.123.123]: 450 : Helo command rejected: Host not found +450 : Helo command rejected: Host not found >>> helo foo -./smtpd_check: reject: HELO from foo[123.123.123.123]: 450 : Host not found -450 : Host not found +./smtpd_check: : reject: HELO from foo[123.123.123.123]: 450 : Helo command rejected: Host not found +450 : 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: : reject: HELO from foo[123.123.123.123]: 554 : Helo command rejected: match bad.domain +554 : 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: : reject: MAIL from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17] +./smtpd_check: : reject: MAIL from unknown[131.155.210.17]: from= +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 : Domain not found -450 : Domain not found +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: 450 : Sender address rejected: Domain not found +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +450 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad-sender@ +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match reject@this.address +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match reject@this.address +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad.domain +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad.domain +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad.domain +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: RCPT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17] +./smtpd_check: : reject: RCPT from unknown[131.155.210.17]: from= to= +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 : Relay access denied -554 : Relay access denied +./smtpd_check: : reject: RCPT from foo[123.123.123.123]: 554 : Recipient address rejected: Relay access denied +./smtpd_check: : reject: RCPT from foo[123.123.123.123]: from= to= +554 : 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 : Relay access denied -554 : Relay access denied +./smtpd_check: : reject: RCPT from foo[123.123.123.123]: 554 : Recipient address rejected: Relay access denied +./smtpd_check: : reject: RCPT from foo[123.123.123.123]: from= to= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad-sender@ +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match reject@this.address +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad.domain +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad.domain +./smtpd_check: : reject: MAIL from foo[123.123.123.123]: from= +554 : 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: : reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com +./smtpd_check: : reject: CONNECT from foo[127.0.0.2]: from= 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 : Domain not found -554 : Domain not found +./smtpd_check: : reject: RCPT from foo[127.0.0.2]: 554 : Recipient address rejected: Domain not found +./smtpd_check: : reject: RCPT from foo[127.0.0.2]: from= to= +554 : 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 : Domain not found -554 : Domain not found +./smtpd_check: : reject: RCPT from foo[127.0.0.2]: 554 : Sender address rejected: Domain not found +./smtpd_check: : reject: RCPT from foo[127.0.0.2]: from= to= +554 : Sender address rejected: Domain not found diff --git a/postfix/smtpd/smtpd_state.c b/postfix/smtpd/smtpd_state.c index ef795d78c..a60ee4ca2 100644 --- a/postfix/smtpd/smtpd_state.c +++ b/postfix/smtpd/smtpd_state.c @@ -53,6 +53,7 @@ #include #include #include +#include /* 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); } diff --git a/postfix/smtpstone/smtp-source.c b/postfix/smtpstone/smtp-source.c index 6aae8f012..078e7f393 100644 --- a/postfix/smtpstone/smtp-source.c +++ b/postfix/smtpstone/smtp-source.c @@ -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.