From: Wietse Venema Date: Wed, 19 Mar 2003 05:00:00 +0000 (-0500) Subject: postfix-2.0.7 X-Git-Tag: v2.0.7^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=42148a3746984bae66c9b42327329263cd73737e;p=thirdparty%2Fpostfix.git postfix-2.0.7 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index c882f46ad..283e48572 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -7682,6 +7682,24 @@ Apologies for any names omitted. systems against exploitation of the remote buffer overflow vulnerability described in CERT advisory CA-2003-07. +20030311-19 + + Bugfix: the access map actions HOLD, DISCARD and FILTER + were broken with smtpd_delay_reject=no and with ETRN. Fixing + this required re-architecting of the actions code. Files: + smtpd/smtpd.[hc], smtpd/smtpd_check.c, smtpd/smtpd_state.c. + +20030315 + + Bugfix: the postsuper manual page documented support for + the -c command line option, but it was not implemented. + File: postsuper/postsuper.c. + + Bugfix: the Postfix 2.0 recipient map checking code broke + the VRFY command, causing it to reply with status code 252 + for non-existent addresses. This required re-architecting + the recipient table lookup code. File: smtpd/smtpd_check.c. + Open problems: Low: after successful delivery, per-queue window += 1/window, diff --git a/postfix/conf/master.cf b/postfix/conf/master.cf index eb9960c2f..80857d088 100644 --- a/postfix/conf/master.cf +++ b/postfix/conf/master.cf @@ -26,6 +26,8 @@ # directory (pathname is controlled by the queue_directory configuration # variable in the main.cf file). Presently, all Postfix daemons can run # chrooted, except for the pipe, virtual and local delivery daemons. +# The proxymap server can run chrooted, but doing so defeats most of +# the purpose of having that service in the first place. # The files in the examples/chroot-setup subdirectory describe how # to set up a Postfix chroot environment for your type of machine. # diff --git a/postfix/html/proxymap.8.html b/postfix/html/proxymap.8.html index 4ea05c096..0cff6e6a6 100644 --- a/postfix/html/proxymap.8.html +++ b/postfix/html/proxymap.8.html @@ -88,7 +88,9 @@ PROXYMAP(8) PROXYMAP(8) The proxymap server opens only tables that are approved via the proxy_read_maps configuration parameter, does not talk to users, and can run at fixed low privilege, - chrooted or not. + chrooted or not. However, running the proxymap server + chrooted severely limits usability, because it can open + only chrooted tables. The proxymap server is not a trusted daemon process, and must not be used to look up sensitive information such as diff --git a/postfix/html/uce.html b/postfix/html/uce.html index 03055c963..9cc939967 100644 --- a/postfix/html/uce.html +++ b/postfix/html/uce.html @@ -856,7 +856,7 @@ and the address contains no sender-specified routing
  • Postfix is the final destination: any destination that matches $mydestination, $inet_interfaces, $virtual_alias_domains, or +href="virtual.5.html">$virtual_alias_domains, or $virtual_mailbox_domains. diff --git a/postfix/man/man8/proxymap.8 b/postfix/man/man8/proxymap.8 index a801de872..73efb7142 100644 --- a/postfix/man/man8/proxymap.8 +++ b/postfix/man/man8/proxymap.8 @@ -88,6 +88,8 @@ of idle time. The proxymap server opens only tables that are approved via the \fBproxy_read_maps\fR configuration parameter, does not talk to users, and can run at fixed low privilege, chrooted or not. +However, running the proxymap server chrooted severely limits +usability, because it can open only chrooted tables. The proxymap server is not a trusted daemon process, and must not be used to look up sensitive information such as user or diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index a981d06f9..8f48d059f 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -1210,6 +1210,7 @@ tok822_parse.o: ../../include/sys_defs.h tok822_parse.o: ../../include/vstring.h tok822_parse.o: ../../include/vbuf.h tok822_parse.o: ../../include/msg.h +tok822_parse.o: ../../include/stringops.h tok822_parse.o: lex_822.h tok822_parse.o: quote_822_local.h tok822_parse.o: quote_flags.h diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 05fb9d28b..d3ee7e8c2 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,10 +20,10 @@ * Patches change the patchlevel and the release date. Snapshots change the * release date only, unless they include the same bugfix as a patch release. */ -#define MAIL_RELEASE_DATE "20030305" +#define MAIL_RELEASE_DATE "20030319" #define VAR_MAIL_VERSION "mail_version" -#define DEF_MAIL_VERSION "2.0.6" +#define DEF_MAIL_VERSION "2.0.7" extern char *var_mail_version; /* diff --git a/postfix/src/global/maps.c b/postfix/src/global/maps.c index 82edbb0cc..6b0fa6269 100644 --- a/postfix/src/global/maps.c +++ b/postfix/src/global/maps.c @@ -184,14 +184,15 @@ const char *maps_find(MAPS *maps, const char *name, int flags) continue; if ((expansion = dict_get(dict, name)) != 0) { if (msg_verbose) - msg_info("%s: %s: %s = %s", myname, *map_name, name, expansion); + msg_info("%s: %s: %s: %s = %s", myname, maps->title, + *map_name, name, expansion); return (expansion); } else if (dict_errno != 0) { break; } } if (msg_verbose) - msg_info("%s: %s: %s", myname, name, dict_errno ? + msg_info("%s: %s: %s: %s", myname, maps->title, name, dict_errno ? "search aborted" : "not found"); return (0); } diff --git a/postfix/src/global/tok822_parse.c b/postfix/src/global/tok822_parse.c index fe554bf7a..4866ac5ad 100644 --- a/postfix/src/global/tok822_parse.c +++ b/postfix/src/global/tok822_parse.c @@ -126,6 +126,7 @@ #include #include +#include /* Global library. */ @@ -250,7 +251,7 @@ static void strip_address(VSTRING *vp, int start, TOK822 *addr) * Emit plain
    . Discard any comments or phrases. */ msg_warn("stripping too many comments from address: %.100s...", - vstring_str(vp) + start); + printable(vstring_str(vp) + start, '?')); vstring_truncate(vp, start); VSTRING_ADDCH(vp, '<'); if (addr) { @@ -263,7 +264,6 @@ static void strip_address(VSTRING *vp, int start, TOK822 *addr) VSTRING_ADDCH(vp, '>'); } - /* tok822_externalize - token tree to string, external form */ VSTRING *tok822_externalize(VSTRING *vp, TOK822 *tree, int flags) diff --git a/postfix/src/master/mail_flow.c b/postfix/src/master/mail_flow.c index efb598854..383ba5816 100644 --- a/postfix/src/master/mail_flow.c +++ b/postfix/src/master/mail_flow.c @@ -47,6 +47,7 @@ #include #include #include +#include /* Utility library. */ diff --git a/postfix/src/postsuper/postsuper.c b/postfix/src/postsuper/postsuper.c index 7c318f90b..d8831fc26 100644 --- a/postfix/src/postsuper/postsuper.c +++ b/postfix/src/postsuper/postsuper.c @@ -985,16 +985,13 @@ int main(int argc, char **argv) msg_fatal("open /dev/null: %m"); /* - * Process environment options as early as we can. We might be called - * from a set-uid (set-gid) program, so be careful with importing - * environment variables. + * Process this environment option as early as we can, to aid debugging. */ if (safe_getenv(CONF_ENV_VERB)) msg_verbose = 1; /* - * Initialize. Set up logging, read the global configuration file and - * extract configuration information. + * Initialize logging. */ if ((slash = strrchr(argv[0], '/')) != 0) argv[0] = slash + 1; @@ -1002,47 +999,37 @@ int main(int argc, char **argv) msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0])); - mail_conf_read(); - if (chdir(var_queue_dir)) - msg_fatal("chdir %s: %m", var_queue_dir); - /* - * Be sure to log a warning if we do not finish structural repair. Maybe - * we should have an fsck-style "clean" flag so Postfix will not start - * with a broken queue. - */ - signal(SIGHUP, interrupted); - signal(SIGINT, interrupted); - signal(SIGQUIT, interrupted); - signal(SIGTERM, interrupted); - msg_cleanup(fatal_exit); - - /* - * All file/directory updates must be done as the mail system owner. This - * is because Postfix daemons manipulate the queue with those same - * privileges, so directories must be created with the right ownership. - * - * Running as a non-root user is also required for security reasons. When - * the Postfix queue hierarchy is compromised, an attacker could trick us - * into entering other file hierarchies and afflicting damage. Running as - * a non-root user limits the damage to the already compromised mail - * owner. + * Disallow unsafe practices, and refuse to run set-uid (or as the child + * of a set-uid process). Whenever a privileged wrapper program is + * needed, it must properly sanitize the real/effective/saved UID/GID, + * the secondary groups, the process environment, and so on. Otherwise, + * accidents can happen. If not with Postfix, then with other software. */ + if (unsafe() != 0) + msg_fatal("this postfix command must not run as a set-uid process"); if (getuid()) msg_fatal("use of this command is reserved for the superuser"); - set_ugid(var_owner_uid, var_owner_gid); /* * Parse JCL. */ - while ((c = GETOPT(argc, argv, "d:h:H:pr:sv")) > 0) { + while ((c = GETOPT(argc, argv, "c:d:h:H:pr:sv")) > 0) { switch (c) { default: - msg_fatal("usage: %s [-d queue_id (delete)] " + msg_fatal("usage: %s " + "[-c config_dir] " + "[-d queue_id (delete)] " "[-h queue_id (hold)] [-H queue_id (un-hold)] " "[-p (purge temporary files)] [-r queue_id (requeue)] " "[-s (structure fix)] [-v (verbose)] " "[queue...]", argv[0]); + case 'c': + if (*optarg != '/') + msg_fatal("-c requires absolute pathname"); + if (setenv(CONF_ENV_PATH, optarg, 1) < 0) + msg_fatal("setenv: %m"); + break; case 'd': if (delete_names == 0) delete_names = argv_alloc(1); @@ -1083,6 +1070,42 @@ int main(int argc, char **argv) } } + /* + * Read the global configuration file and extract configuration + * information. The -c command option can override the default + * configuration directory location. + */ + mail_conf_read(); + if (chdir(var_queue_dir)) + msg_fatal("chdir %s: %m", var_queue_dir); + + /* + * All file/directory updates must be done as the mail system owner. This + * is because Postfix daemons manipulate the queue with those same + * privileges, so directories must be created with the right ownership. + * + * Running as a non-root user is also required for security reasons. When + * the Postfix queue hierarchy is compromised, an attacker could trick us + * into entering other file hierarchies and afflicting damage. Running as + * a non-root user limits the damage to the already compromised mail + * owner. + */ + set_ugid(var_owner_uid, var_owner_gid); + + /* + * Be sure to log a warning if we do not finish structural repair. Maybe + * we should have an fsck-style "clean" flag so Postfix will not start + * with a broken queue. + * + * Set up signal handlers after permanently dropping super-user privileges, + * so that signal handlers will always run with the correct privileges. + */ + signal(SIGHUP, interrupted); + signal(SIGINT, interrupted); + signal(SIGQUIT, interrupted); + signal(SIGTERM, interrupted); + msg_cleanup(fatal_exit); + /* * Sanity checks. */ diff --git a/postfix/src/proxymap/proxymap.c b/postfix/src/proxymap/proxymap.c index 362079da2..fd93a8275 100644 --- a/postfix/src/proxymap/proxymap.c +++ b/postfix/src/proxymap/proxymap.c @@ -78,6 +78,8 @@ /* The proxymap server opens only tables that are approved via the /* \fBproxy_read_maps\fR configuration parameter, does not talk to /* users, and can run at fixed low privilege, chrooted or not. +/* However, running the proxymap server chrooted severely limits +/* usability, because it can open only chrooted tables. /* /* The proxymap server is not a trusted daemon process, and must /* not be used to look up sensitive information such as user or diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 185ddd227..f4cd07788 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -893,6 +893,7 @@ static void mail_reset(SMTPD_STATE *state) if (var_smtpd_sasl_enable) smtpd_sasl_mail_reset(state); #endif + state->discard = 0; } /* rcpt_cmd - process RCPT TO command */ @@ -951,10 +952,6 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "%s", err); return (-1); } - if ((err = smtpd_check_rcptmap(state, argv[2].strval)) != 0) { - smtpd_chat_reply(state, "%s", err); - return (-1); - } } /* @@ -1259,7 +1256,7 @@ static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) return (-1); } if (SMTPD_STAND_ALONE(state) == 0 - && (err = smtpd_check_rcptmap(state, argv[1].strval)) != 0) { + && (err = smtpd_check_rcpt(state, argv[1].strval)) != 0) { smtpd_chat_reply(state, "%s", err); return (-1); } diff --git a/postfix/src/smtpd/smtpd.h b/postfix/src/smtpd/smtpd.h index 8be9efef1..a369b7e86 100644 --- a/postfix/src/smtpd/smtpd.h +++ b/postfix/src/smtpd/smtpd.h @@ -93,6 +93,7 @@ typedef struct SMTPD_STATE { int defer_if_permit_client; /* force permit into warning */ int defer_if_permit_helo; /* force permit into warning */ int defer_if_permit_sender; /* force permit into warning */ + int discard; /* discard message */ VSTRING *expand_buf; /* scratch space for $name expansion */ } SMTPD_STATE; diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 678a86f0b..b42333082 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -24,10 +24,6 @@ /* SMTPD_STATE *state; /* char *recipient; /* -/* char *smtpd_check_rcptmap(state, recipient) -/* SMTPD_STATE *state; -/* char *recipient; -/* /* char *smtpd_check_etrn(state, destination) /* SMTPD_STATE *state; /* char *destination; @@ -192,11 +188,7 @@ /* .IP smtpd_recipient_restrictions /* Restrictions on the recipient address that is sent with the RCPT /* TO command. -/* .PP -/* smtpd_check_rcptmap() validates the recipient address provided -/* with an RCPT TO request and sets the rcptmap_checked flag. -/* Relevant configuration parameters: -/* .IP local_recipients_map +/* .IP local_recipient_maps /* Tables of user names (not addresses) that exist in $mydestination. /* Mail for local users not in these tables is rejected. /* .PP @@ -1622,6 +1614,31 @@ static int reject_unknown_address(SMTPD_STATE *state, const char *addr, return (reject_unknown_mailhost(state, domain, reply_name, reply_class)); } +/* warn_skip_access_action - FILTER etc. action in unsupported context */ + +static void warn_skip_access_action(const char *table, const char *action, + const char *reply_class) +{ + + /* + * Warn only about FILTER/HOLD/etc. access table actions that appear in + * restrictions where they will always be ignored. + */ + if (strcmp(reply_class, SMTPD_NAME_CLIENT) == 0 + || strcmp(reply_class, SMTPD_NAME_HELO) == 0 + || strcmp(reply_class, SMTPD_NAME_SENDER) == 0) { + if (var_smtpd_delay_reject == 0) + msg_warn("access table %s: with %s=%s, " + "action %s is always skipped in %s restrictions", + table, VAR_SMTPD_DELAY_REJECT, CONFIG_BOOL_NO, + action, reply_class); + } else { + msg_warn("access table %s: action %s is always " + "skipped in %s restrictions", + table, action, reply_class); + } +} + /* check_table_result - translate table lookup result into pass/reject */ static int check_table_result(SMTPD_STATE *state, const char *table, @@ -1673,6 +1690,12 @@ static int check_table_result(SMTPD_STATE *state, const char *table, * mind, and reject/discard the message for other reasons. */ if (STREQUAL(value, "FILTER", cmd_len)) { +#ifndef TEST + if (state->dest == 0) { + warn_skip_access_action(table, "FILTER", reply_class); + return (SMTPD_CHECK_DUNNO); + } +#endif if (*cmd_text == 0) { msg_warn("access map %s entry \"%s\" has FILTER entry without value", table, datum); @@ -1697,6 +1720,12 @@ static int check_table_result(SMTPD_STATE *state, const char *table, * reject/discard the message for other reasons. */ if (STREQUAL(value, "HOLD", cmd_len)) { +#ifndef TEST + if (state->dest == 0) { + warn_skip_access_action(table, "HOLD", reply_class); + return (SMTPD_CHECK_DUNNO); + } +#endif vstring_sprintf(error_text, "<%s>: %s %s", reply_name, reply_class, *cmd_text ? cmd_text : "triggers HOLD action"); log_whatsup(state, "hold", STR(error_text)); @@ -1709,17 +1738,21 @@ static int check_table_result(SMTPD_STATE *state, const char *table, /* * DISCARD means silently discard and claim successful delivery. - * - * XXX Set some global flag that disables all further restrictions. - * Triggering a "reject" or "hold" action after "discard" is silly. */ if (STREQUAL(value, "DISCARD", cmd_len)) { +#ifndef TEST + if (state->dest == 0) { + warn_skip_access_action(table, "DISCARD", reply_class); + return (SMTPD_CHECK_DUNNO); + } +#endif vstring_sprintf(error_text, "<%s>: %s %s", reply_name, reply_class, *cmd_text ? cmd_text : "triggers DISCARD action"); log_whatsup(state, "discard", STR(error_text)); #ifndef TEST rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d", CLEANUP_FLAG_DISCARD); + state->discard = 1; #endif return (SMTPD_CHECK_OK); } @@ -2548,6 +2581,9 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, for (cpp = restrictions->argv; (name = *cpp) != 0; cpp++) { + if (state->discard != 0) + break; + if (msg_verbose) msg_info("%s: name=%s", myname, name); @@ -2998,10 +3034,7 @@ char *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient) /* * The "check_recipient_maps" restriction is relevant only when - * responding to RCPT TO. It's effectively disabled with DATA (recipient - * context is explicitly turned off) and not applicable with undelayed - * client/helo/sender restrictions (no recipient info) or with ETRN - * (command not allowed in the middle of an ongoing MAIL transaction). + * responding to RCPT TO or VRFY. */ state->rcptmap_checked = 0; @@ -3027,7 +3060,7 @@ char *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient) SMTPD_CHECK_RESET(); status = setjmp(smtpd_check_buf); if (status == 0 && rcpt_restrctions->argc) - status = generic_checks(state, rcpt_restrctions, + status = generic_checks(state, rcpt_restrctions, recipient, SMTPD_NAME_RECIPIENT, CHECK_RECIP_ACL); /* @@ -3038,6 +3071,14 @@ char *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient) status = smtpd_check_reject(state, state->defer_if_permit.class, "%s", STR(state->defer_if_permit.reason)); + /* + * If the "check_recipient_maps" restriction was not applied, and if mail + * is not being rejected or discarded, validate the recipient here. + */ + if (status != SMTPD_CHECK_REJECT && state->rcptmap_checked == 0 + && state->discard == 0) + status = check_rcpt_maps(state, recipient); + SMTPD_CHECK_RCPT_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); } @@ -3102,25 +3143,6 @@ char *smtpd_check_etrn(SMTPD_STATE *state, char *domain) SMTPD_CHECK_ETRN_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); } -/* smtpd_check_rcptmap - permit if recipient address matches lookup table */ - -char *smtpd_check_rcptmap(SMTPD_STATE *state, char *recipient) -{ - char *myname = "smtpd_check_rcptmap"; - int status; - - if (msg_verbose) - msg_info("%s: %s", myname, recipient); - - /* - * Return here in case of serious trouble. - */ - if ((status = setjmp(smtpd_check_buf)) == 0) - status = check_rcpt_maps(state, recipient); - - return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); -} - /* check_rcpt_maps - generic_checks() interface for recipient table check */ static int check_rcpt_maps(SMTPD_STATE *state, const char *recipient) @@ -3198,13 +3220,13 @@ static int check_rcpt_maps(SMTPD_STATE *state, const char *recipient) if ((reply->flags & RESOLVE_CLASS_LOCAL) && *var_local_rcpt_maps - /* Generated by bounce, absorbed by qmgr. */ + /* Generated by bounce, absorbed by qmgr. */ && !MATCH_LEFT(var_double_bounce_sender, CONST_STR(reply->recipient), strlen(var_double_bounce_sender)) - /* Absorbed by qmgr. */ + /* Absorbed by qmgr. */ && !MATCH_LEFT(MAIL_ADDR_POSTMASTER, CONST_STR(reply->recipient), strlen(MAIL_ADDR_POSTMASTER)) - /* Generated by bounce. */ + /* Generated by bounce. */ && !MATCH_LEFT(MAIL_ADDR_MAIL_DAEMON, CONST_STR(reply->recipient), strlen(MAIL_ADDR_MAIL_DAEMON)) && NOMATCH(local_rcpt_maps, CONST_STR(reply->recipient))) @@ -3486,6 +3508,7 @@ int var_local_rcpt_code; int var_relay_rcpt_code; int var_virt_mailbox_code; int var_virt_alias_code; +int var_show_unk_rcpt_table; static INT_TABLE int_table[] = { "msg_verbose", 0, &msg_verbose, @@ -3505,6 +3528,7 @@ static INT_TABLE int_table[] = { VAR_RELAY_RCPT_CODE, DEF_RELAY_RCPT_CODE, &var_relay_rcpt_code, VAR_VIRT_ALIAS_CODE, DEF_VIRT_ALIAS_CODE, &var_virt_alias_code, VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code, + VAR_SHOW_UNK_RCPT_TABLE, DEF_SHOW_UNK_RCPT_TABLE, &var_show_unk_rcpt_table, 0, }; @@ -3883,8 +3907,7 @@ int main(int argc, char **argv) } else if (strcasecmp(args->argv[0], "rcpt") == 0) { state.where = "RCPT"; TRIM_ADDR(args->argv[1], addr); - (resp = smtpd_check_rcpt(&state, addr)) - || (resp = smtpd_check_rcptmap(&state, addr)); + resp = smtpd_check_rcpt(&state, addr); } break; diff --git a/postfix/src/smtpd/smtpd_check.h b/postfix/src/smtpd/smtpd_check.h index 60348c40d..302e26903 100644 --- a/postfix/src/smtpd/smtpd_check.h +++ b/postfix/src/smtpd/smtpd_check.h @@ -16,7 +16,6 @@ extern void smtpd_check_init(void); extern char *smtpd_check_client(SMTPD_STATE *); extern char *smtpd_check_helo(SMTPD_STATE *, char *); extern char *smtpd_check_mail(SMTPD_STATE *, char *); -extern char *smtpd_check_rcptmap(SMTPD_STATE *, char *); extern char *smtpd_check_size(SMTPD_STATE *, off_t); extern char *smtpd_check_rcpt(SMTPD_STATE *, char *); extern char *smtpd_check_etrn(SMTPD_STATE *, char *); diff --git a/postfix/src/smtpd/smtpd_check.in4 b/postfix/src/smtpd/smtpd_check.in4 index 024bb77ff..abffa1ff0 100644 --- a/postfix/src/smtpd/smtpd_check.in4 +++ b/postfix/src/smtpd/smtpd_check.in4 @@ -11,6 +11,7 @@ sender_restrictions hash:./smtpd_check_access mail rejecttext@bad.domain mail filter@filter.domain mail filtertext@filter.domain +mail filtertexttext@filter.domain mail hold@hold.domain mail holdtext@hold.domain mail discard@hold.domain diff --git a/postfix/src/smtpd/smtpd_check.ref4 b/postfix/src/smtpd/smtpd_check.ref4 index e47600177..a73b5a1fc 100644 --- a/postfix/src/smtpd/smtpd_check.ref4 +++ b/postfix/src/smtpd/smtpd_check.ref4 @@ -14,10 +14,13 @@ OK ./smtpd_check: : reject: MAIL from localhost[127.0.0.1]: 554 : Sender address rejected: text; from= proto=SMTP 554 : Sender address rejected: text >>> mail filter@filter.domain -./smtpd_check: warning: access map hash:./smtpd_check_access entry filter@filter.domain has FILTER entry without value +./smtpd_check: warning: access map hash:./smtpd_check_access entry "filter@filter.domain" has FILTER entry without value OK >>> mail filtertext@filter.domain -./smtpd_check: : filter: MAIL from localhost[127.0.0.1]: : Sender address triggers FILTER text; from= proto=SMTP +./smtpd_check: warning: access map hash:./smtpd_check_access entry "filtertext@filter.domain" requires transport:destination +OK +>>> mail filtertexttext@filter.domain +./smtpd_check: : filter: MAIL from localhost[127.0.0.1]: : Sender address triggers FILTER text:text; from= proto=SMTP OK >>> mail hold@hold.domain ./smtpd_check: : hold: MAIL from localhost[127.0.0.1]: : Sender address triggers HOLD action; from= proto=SMTP diff --git a/postfix/src/smtpd/smtpd_check_access b/postfix/src/smtpd/smtpd_check_access index 41405ef4f..bfcb3d35f 100644 --- a/postfix/src/smtpd/smtpd_check_access +++ b/postfix/src/smtpd/smtpd_check_access @@ -50,6 +50,7 @@ dsn.rfc-ignorant.org $rbl_code client=$client rejecttext@bad.domain reject text filter@filter.domain filter filtertext@filter.domain filter text +filtertexttext@filter.domain filter text:text hold@hold.domain hold holdtext@hold.domain hold text discard@hold.domain discard diff --git a/postfix/src/smtpd/smtpd_state.c b/postfix/src/smtpd/smtpd_state.c index 53ef27580..6475ae49b 100644 --- a/postfix/src/smtpd/smtpd_state.c +++ b/postfix/src/smtpd/smtpd_state.c @@ -97,6 +97,7 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream) state->defer_if_permit_sender = 0; state->defer_if_reject.reason = 0; state->defer_if_permit.reason = 0; + state->discard = 0; state->expand_buf = 0; #ifdef USE_SASL_AUTH