From: Wietse Venema Date: Wed, 19 Mar 2003 05:00:00 +0000 (-0500) Subject: postfix-2.0.7-20030319 X-Git-Tag: v2.1-RC1-20040331~72 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1c1296a56f213ead46c4171b3b80077ab9754b3d;p=thirdparty%2Fpostfix.git postfix-2.0.7-20030319 --- diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 7e8ce4ccf..132e9b83f 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -136,7 +136,6 @@ -TSINK_STATE -TSMTPD_CMD -TSMTPD_DEFER --TSMTPD_MSG_ACTION -TSMTPD_RBL_EXPAND_CONTEXT -TSMTPD_RBL_STATE -TSMTPD_STATE diff --git a/postfix/HISTORY b/postfix/HISTORY index 23f544606..f0b02952b 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -7895,12 +7895,12 @@ Apologies for any names omitted. systems against exploitation of the remote buffer overflow vulnerability described in CERT advisory CA-2003-07. -20030311-17 +20030311-19 Bugfix: the access map actions HOLD, DISCARD, FILTER and - REDIRECT were broken with smtpd_delay_reject=no. This - required re-architecting of the actions code. Files: - smtpd/smtpd.[hc], smtpd/smtpd_check.c, smtpd/smtpd_state.c. + REDIRECT were broken with smtpd_delay_reject=no and with + ETRN. This required re-architecting of the actions code. + Files: smtpd/smtpd.[hc], smtpd/smtpd_check.c, smtpd/smtpd_state.c. 20030315 @@ -7913,6 +7913,19 @@ Apologies for any names omitted. for non-existent addresses. This required re-architecting the recipient table lookup code. File: smtpd/smtpd_check.c. +20030319 + + Feature: configurable limit on virtual alias expansion size + and nesting depth, via the virtual_alias_expansion_limit + and virtual_alias_recursion_limit parameters. The default + limits are compatible with past Postfix versions. Victor + Duchovni, Morgan Stanley. Files: /sample-resource.cf, + html/resource.html, cleanup/cleanup.c, cleanup/cleanup_init.c, + cleanup/cleanup_map1n.c. + + Feature: the installation procedure records build information + (by default: in /etc/postfix/makedefs.out). + Open problems: Med: make qmgr recipient bounce/defer activity asynchronous diff --git a/postfix/Makefile.in b/postfix/Makefile.in index 62fb6d362..ddb60c483 100644 --- a/postfix/Makefile.in +++ b/postfix/Makefile.in @@ -18,6 +18,9 @@ makefiles Makefiles: $(MAKE) -f Makefile.in Makefile MAKELEVEL=) || exit 1; \ done; rm -f Makefile; (set -e; $(SHELL) makedefs && cat Makefile.in) >Makefile + (echo "# Do not edit -- this file documents how Postfix was built for your machine."; $(SHELL) makedefs) >makedefs.tmp + set +e; if cmp makedefs.tmp conf/makedefs.out; then rm makedefs.tmp; \ + else mv makedefs.tmp conf/makedefs.out; fi >/dev/null 2>/dev/null update printfck tests: set -e; for i in $(DIRS); do \ diff --git a/postfix/conf/postfix-files b/postfix/conf/postfix-files index cf30047b1..cb7ad74c3 100644 --- a/postfix/conf/postfix-files +++ b/postfix/conf/postfix-files @@ -94,6 +94,7 @@ $config_directory/aliases:f:root:-:644:p $config_directory/canonical:f:root:-:644:p $config_directory/main.cf:f:root:-:644:p $config_directory/main.cf.default:f:root:-:644 +$config_directory/makedefs.out:f:root:-:644 $config_directory/master.cf:f:root:-:644:p $config_directory/pcre_table:f:root:-:644:p $config_directory/postfix-files:f:root:-:644 diff --git a/postfix/conf/sample-resource.cf b/postfix/conf/sample-resource.cf index 7e24abd62..54ca3684f 100644 --- a/postfix/conf/sample-resource.cf +++ b/postfix/conf/sample-resource.cf @@ -47,6 +47,19 @@ deliver_lock_delay = 1s # duplicate_filter_limit = 1000 +# The virtual_alias_expansion_limit parameter limits the number of +# addresses that virtual expansion produces from each original recipient. +# +virtual_alias_expansion_limit = 1000 + +# The virtual_alias_recursion_limit parameter limits the nesting depth of +# virtual expansion. Currently the recursion limit is applied only to the +# left branch of the expansion graph, so the depth of the tree can in the +# worst case reach the sum of the expansion and recursion limits. +# This may change in the future. +# +virtual_alias_recursion_limit = 1000 + # The fork_attempts parameter limits the number of attempts to # fork() a process. # diff --git a/postfix/html/cleanup.8.html b/postfix/html/cleanup.8.html index 0e793b6a2..287181429 100644 --- a/postfix/html/cleanup.8.html +++ b/postfix/html/cleanup.8.html @@ -208,6 +208,15 @@ CLEANUP(8) CLEANUP(8) Limit the amount of recipients extracted from mes- sage headers. + virtual_alias_expansion_limit + Limit the number of actual recipients produced by + virtual alias expansion from each original recipi- + ent. + + virtual_alias_recursion_limit + Limit the recursion depth of virtual alias expan- + sion. + SEE ALSO canonical(5) canonical address lookup table format qmgr(8) queue manager daemon @@ -220,7 +229,7 @@ CLEANUP(8) CLEANUP(8) /etc/postfix/virtual*, virtual mapping table LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/html/resource.html b/postfix/html/resource.html index e37c78a0a..8255ad412 100644 --- a/postfix/html/resource.html +++ b/postfix/html/resource.html @@ -164,6 +164,21 @@ delivery agent and address cleanup daemon remember when delivering a message. A recipient address is ignored when it is found in the remembered list. +
virtual_alias_expansion_limit (default: 1000) + +
This limits the number of addresses that result from each original +recipient by virtual alias expansion in the +address cleanup daemon. By default each original recipient is rewritten +via $virtual_alias_maps to at most 1000 actual recipients. + +
virtual_alias_recursion_limit (default: 1000) + +
This limits the recursive nesting of virtual alias expansion performed +by the address cleanup daemon. Virtual +alias expansion is recursive, and stops only when an address is not +found in the table, when an address maps to itself, or when the +recursion limit is reached. +

Time limits

diff --git a/postfix/man/man8/cleanup.8 b/postfix/man/man8/cleanup.8 index 19a0106f5..fe4360d18 100644 --- a/postfix/man/man8/cleanup.8 +++ b/postfix/man/man8/cleanup.8 @@ -174,6 +174,11 @@ Amount of time to pause before accepting a message, when the message arrival rate exceeds the message delivery rate. .IP \fBextract_recipient_limit\fR Limit the amount of recipients extracted from message headers. +.IP \fBvirtual_alias_expansion_limit\fR +Limit the number of actual recipients produced by virtual alias +expansion from each original recipient. +.IP \fBvirtual_alias_recursion_limit\fR +Limit the recursion depth of virtual alias expansion. .SH SEE ALSO .na .nf diff --git a/postfix/src/cleanup/cleanup.c b/postfix/src/cleanup/cleanup.c index 78baa9b05..9ec0896fe 100644 --- a/postfix/src/cleanup/cleanup.c +++ b/postfix/src/cleanup/cleanup.c @@ -160,6 +160,11 @@ /* message arrival rate exceeds the message delivery rate. /* .IP \fBextract_recipient_limit\fR /* Limit the amount of recipients extracted from message headers. +/* .IP \fBvirtual_alias_expansion_limit\fR +/* Limit the number of actual recipients produced by virtual alias +/* expansion from each original recipient. +/* .IP \fBvirtual_alias_recursion_limit\fR +/* Limit the recursion depth of virtual alias expansion. /* SEE ALSO /* canonical(5) canonical address lookup table format /* qmgr(8) queue manager daemon diff --git a/postfix/src/cleanup/cleanup_init.c b/postfix/src/cleanup/cleanup_init.c index 296c88c75..5c8a57658 100644 --- a/postfix/src/cleanup/cleanup_init.c +++ b/postfix/src/cleanup/cleanup_init.c @@ -110,6 +110,8 @@ int var_extra_rcpt_limit; /* recipient extract limit */ char *var_rcpt_witheld; /* recipients not disclosed */ char *var_masq_classes; /* what to masquerade */ int var_qattr_count_limit; /* named attribute limit */ +int var_virt_recur_limit; /* maximum virtual alias recursion */ +int var_virt_expan_limit; /* maximum virtual alias expansion */ int var_body_check_len; /* when to stop body scan */ CONFIG_INT_TABLE cleanup_int_table[] = { @@ -117,6 +119,8 @@ CONFIG_INT_TABLE cleanup_int_table[] = { VAR_DUP_FILTER_LIMIT, DEF_DUP_FILTER_LIMIT, &var_dup_filter_limit, 0, 0, VAR_EXTRA_RCPT_LIMIT, DEF_EXTRA_RCPT_LIMIT, &var_extra_rcpt_limit, 0, 0, VAR_QATTR_COUNT_LIMIT, DEF_QATTR_COUNT_LIMIT, &var_qattr_count_limit, 1, 0, + VAR_VIRT_RECUR_LIMIT, DEF_VIRT_RECUR_LIMIT, &var_virt_recur_limit, 1, 0, + VAR_VIRT_EXPAN_LIMIT, DEF_VIRT_EXPAN_LIMIT, &var_virt_expan_limit, 1, 0, VAR_BODY_CHECK_LEN, DEF_BODY_CHECK_LEN, &var_body_check_len, 0, 0, 0, }; diff --git a/postfix/src/cleanup/cleanup_map1n.c b/postfix/src/cleanup/cleanup_map1n.c index e83f4fb62..e69ec190f 100644 --- a/postfix/src/cleanup/cleanup_map1n.c +++ b/postfix/src/cleanup/cleanup_map1n.c @@ -55,6 +55,7 @@ /* Global library. */ +#include #include #include #include @@ -93,13 +94,11 @@ ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr, * pointer. */ #define UPDATE(ptr,new) { myfree(ptr); ptr = mystrdup(new); } -#define MAX_RECURSION 1000 -#define MAX_EXPANSION 1000 #define STR vstring_str #define RETURN(x) { been_here_free(been_here); return (x); } for (arg = 0; arg < argv->argc; arg++) { - if (argv->argc > MAX_EXPANSION) { + if (argv->argc > var_virt_expan_limit) { msg_warn("%s: unreasonable %s map expansion size for %s", state->queue_id, maps->title, addr); break; @@ -111,7 +110,7 @@ ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr, */ if (been_here_check_fixed(been_here, argv->argv[arg]) != 0) break; - if (count >= MAX_RECURSION) { + if (count >= var_virt_recur_limit) { msg_warn("%s: unreasonable %s map nesting for %s", state->queue_id, maps->title, addr); break; diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 5fda0d9de..e4cb9ce1b 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -1019,6 +1019,14 @@ extern int var_token_limit; #define DEF_EXTRA_RCPT_LIMIT 10240 extern int var_extra_rcpt_limit; +#define VAR_VIRT_RECUR_LIMIT "virtual_alias_recursion_limit" +#define DEF_VIRT_RECUR_LIMIT 1000 +extern int var_virt_recur_limit; + +#define VAR_VIRT_EXPAN_LIMIT "virtual_alias_expansion_limit" +#define DEF_VIRT_EXPAN_LIMIT 1000 +extern int var_virt_expan_limit; + /* * Message/queue size limits. */ diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 4dc8dae25..0b847dec6 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * 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 "20030317" +#define MAIL_RELEASE_DATE "20030319" #define VAR_MAIL_VERSION "mail_version" #define DEF_MAIL_VERSION "2.0.7-" MAIL_RELEASE_DATE diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index e75bb0d47..7cf3ed70b 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -495,8 +495,6 @@ static int helo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "501 Syntax: HELO hostname"); return (-1); } - if (state->helo_name != 0) - helo_reset(state); if (argc > 2) collapse_args(argc - 1, argv + 1); if (SMTPD_STAND_ALONE(state) == 0 @@ -505,6 +503,8 @@ static int helo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "%s", err); return (-1); } + if (state->helo_name != 0) + helo_reset(state); chat_reset(state, var_smtpd_hist_thrsh); mail_reset(state); rcpt_reset(state); @@ -531,8 +531,6 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "501 Syntax: EHLO hostname"); return (-1); } - if (state->helo_name != 0) - helo_reset(state); if (argc > 2) collapse_args(argc - 1, argv + 1); if (SMTPD_STAND_ALONE(state) == 0 @@ -541,6 +539,8 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "%s", err); return (-1); } + if (state->helo_name != 0) + helo_reset(state); chat_reset(state, var_smtpd_hist_thrsh); mail_reset(state); rcpt_reset(state); @@ -576,26 +576,6 @@ static void helo_reset(SMTPD_STATE *state) if (state->helo_name) myfree(state->helo_name); state->helo_name = 0; - - /* - * With smtpd_delay_reject=yes, smtpd_helo_restrictions is evaluated at - * RCPT TO time, and may be evaluated multiple times per message. - * Per-message smtpd_helo_restrictions side effects (HOLD, DISCARD, etc.) - * accumulate from one evaluation to the next, and may also depend on - * client, sender or recipient information. Therefore, any per-message - * helo restriction side effects need to be reset at the end of a mail - * delivery transaction. - * - * With smtpd_delay_reject=no, smtpd_helo_restrictions is evaluated when - * HELO/EHLO is issued, and its per-message side effects change only when - * another HELO/EHLO command is issued. Therefore, any per-message helo - * restriction side effects must be reset before smtpd_helo_restrictions - * is evaluated. - */ - if (var_smtpd_delay_reject == 0) { - SMTPD_MSG_ACT_FREE(state->action_helo); - SMTPD_MSG_ACT_ZERO(state->action_helo); - } } /* mail_open_stream - open mail destination */ @@ -923,20 +903,7 @@ static void mail_reset(SMTPD_STATE *state) if (var_smtpd_sasl_enable) smtpd_sasl_mail_reset(state); #endif - - /* - * With smtpd_delay_reject=yes, smtpd_sender_restrictions is evaluated at - * RCPT TO time, and may be evaluated multiple times per message. - * Per-message smtpd_sender_restrictions side effects (HOLD, DISCARD, - * etc.) accumulate from one evaluation to the next, and may also depend - * on client, helo or recipient information. - * - * The action_mailrcpt member accumulates both sender and recipient side - * effects. It needs to be reset after each mail delivery, whether or not - * it is actually completed. - */ - SMTPD_MSG_ACT_FREE(state->action_mailrcpt); - SMTPD_MSG_ACT_ZERO(state->action_mailrcpt); + state->discard = 0; } /* rcpt_cmd - process RCPT TO command */ @@ -1017,26 +984,6 @@ static void rcpt_reset(SMTPD_STATE *state) state->recipient = 0; } state->rcpt_count = 0; - - /* - * With smtpd_delay_reject=yes, smtpd_{client,helo}_restrictions are - * evaluated at RCPT TO time. They may be evaluated multiple times per - * message delivery. Per-message {client,helo} restriction side effects - * (HOLD, DISCARD, etc.) accumulate from one evaluation to the next, and - * the result may also depend on sender or recipient information. - * Therefore, per-message {client,helo} restriction side effects need to - * be reset between deliveries. - * - * With smtpd_delay_reject=no, smtpd_{client,helo}_restrictions are - * evaluated once and take effect over multiple deliveries. Therefore, - * their per-message side effects must not be reset between deliveries. - */ - if (var_smtpd_delay_reject) { - SMTPD_MSG_ACT_FREE(state->action_client); - SMTPD_MSG_ACT_ZERO(state->action_client); - SMTPD_MSG_ACT_FREE(state->action_helo); - SMTPD_MSG_ACT_ZERO(state->action_helo); - } } /* data_cmd - process DATA command */ @@ -1051,7 +998,6 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) int first = 1; VSTRING *why = 0; int saved_err; - char *act_value; /* * Sanity checks. With ESMTP command pipelining the client can send DATA @@ -1084,18 +1030,6 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) */ if (*var_always_bcc) rec_fputs(state->cleanup, REC_TYPE_RCPT, var_always_bcc); - if (SMTPD_MSG_ACT_FLAGS(state) & SMTPD_MSG_ACT_DISCARD) { - rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d", - CLEANUP_FLAG_DISCARD); - } else { - if (SMTPD_MSG_ACT_FLAGS(state) & SMTPD_MSG_ACT_HOLD) - rec_fprintf(state->cleanup, REC_TYPE_FLGS, "%d", - CLEANUP_FLAG_HOLD); - if ((act_value = SMTPD_MSG_ACT_VALUE(state, filter)) != 0) - rec_fprintf(state->dest->stream, REC_TYPE_FILT, "%s", act_value); - if ((act_value = SMTPD_MSG_ACT_VALUE(state, redirect)) != 0) - rec_fprintf(state->dest->stream, REC_TYPE_RDR, "%s", act_value); - } rec_fputs(state->cleanup, REC_TYPE_MESG, ""); rec_fprintf(state->cleanup, REC_TYPE_NORM, "Received: from %s (%s [%s])", @@ -1332,7 +1266,7 @@ static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) return (-1); } if (SMTPD_STAND_ALONE(state) == 0 - && (err = smtpd_check_vrfy(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 be0ad3421..a369b7e86 100644 --- a/postfix/src/smtpd/smtpd.h +++ b/postfix/src/smtpd/smtpd.h @@ -45,43 +45,6 @@ typedef struct SMTPD_DEFER { int class; /* error notification class */ } SMTPD_DEFER; - /* - * Actions that affect all recipients of a given message. That is, we don't - * "undo" results from one recipient when evaluating the next recipient. - */ -typedef struct SMTPD_MSG_ACTION { - int flags; /* see below */ - char *filter; /* filter destination */ - char *redirect; /* redirect destination */ -} SMTPD_MSG_ACTION; - -#define SMTPD_MSG_ACT_HOLD (1<<0) /* place message on hold */ -#define SMTPD_MSG_ACT_DISCARD (1<<1) /* discard message */ -#define SMTPD_MSG_ACT_FILTER (1<<2) /* filter message */ -#define SMTPD_MSG_ACT_REDIRECT (1<<3) /* redirect message */ - - /* - * Short-hand for when to stop searching restriction lists. - */ -#define SMTPD_MSG_ACT_FINAL (SMTPD_MSG_ACT_DISCARD) - -#define SMTPD_MSG_ACT_ZERO(a) do { \ - (a).flags = 0; \ - (a).filter = 0; \ - (a).redirect = 0; \ - } while (0) - -#define SMTPD_MSG_ACT_FREE(a) do { \ - if ((a).filter) myfree((a).filter); \ - if ((a).redirect) myfree((a).redirect); \ - } while (0) - -#define SMTPD_MSG_ACT_COPY(d, s) do { \ - SMTPD_MSG_ACT_FREE(d); \ - (d).filter = ((s).filter ? mystrdup((s).filter) : 0); \ - (d).redirect = ((s).redirect ? mystrdup((s).redirect) : 0); \ - } while (0) - typedef struct SMTPD_STATE { int err; VSTREAM *client; @@ -123,10 +86,6 @@ typedef struct SMTPD_STATE { VSTRING *sasl_encoded; VSTRING *sasl_decoded; #endif - SMTPD_MSG_ACTION *action; /* action from access map */ - SMTPD_MSG_ACTION action_client; /* action after connect */ - SMTPD_MSG_ACTION action_helo; /* action after helo/ehlo */ - SMTPD_MSG_ACTION action_mailrcpt; /* action after mail from/rcpt to */ int rcptmap_checked; int warn_if_reject; /* force reject into warning */ SMTPD_DEFER defer_if_reject; /* force reject into deferral */ @@ -134,18 +93,10 @@ 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; -#define SMTPD_MSG_ACT_FLAGS(s) \ - ((s)->action_client.flags | (s)->action_helo.flags \ - | (s)->action_mailrcpt.flags) - -#define SMTPD_MSG_ACT_VALUE(s,m) \ - ((s)->action_mailrcpt.m ? (s)->action_mailrcpt.m : \ - (s)->action_helo.m ? (s)->action_helo.m : \ - (s)->action_client.m) - extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *); extern void smtpd_state_reset(SMTPD_STATE *); diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 4b030da86..a7da2a25e 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_vrfy(state, recipient) -/* SMTPD_STATE *state; -/* char *recipient; -/* /* char *smtpd_check_etrn(state, destination) /* SMTPD_STATE *state; /* char *destination; @@ -206,12 +202,6 @@ /* Tables of user names (not addresses) that exist in $mydestination. /* Mail for local users not in these tables is rejected. /* .PP -/* smtpd_check_vrfy() validates the recipient address provided -/* with a VRFY request. Relevant configuration parameters: -/* .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 /* smtpd_check_etrn() validates the domain name provided with the /* ETRN command, and other client-provided information. Relevant /* configuration parameters: @@ -1702,6 +1692,31 @@ static int reject_unverified_address(SMTPD_STATE *state, const char *addr, return (rqst_status); } +/* 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, @@ -1753,8 +1768,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)) { - if (state->action == 0) +#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); @@ -1767,10 +1786,9 @@ static int check_table_result(SMTPD_STATE *state, const char *table, vstring_sprintf(error_text, "<%s>: %s triggers FILTER %s", reply_name, reply_class, cmd_text); log_whatsup(state, "filter", STR(error_text)); - state->action->flags |= SMTPD_MSG_ACT_FILTER; - if (state->action->filter) - myfree(state->action->filter); - state->action->filter = mystrdup(cmd_text); +#ifndef TEST + rec_fprintf(state->dest->stream, REC_TYPE_FILT, "%s", cmd_text); +#endif return (SMTPD_CHECK_DUNNO); } } @@ -1780,12 +1798,19 @@ static int check_table_result(SMTPD_STATE *state, const char *table, * reject/discard the message for other reasons. */ if (STREQUAL(value, "HOLD", cmd_len)) { - if (state->action == 0) +#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)); - state->action->flags |= SMTPD_MSG_ACT_HOLD; +#ifndef TEST + rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d", + CLEANUP_FLAG_HOLD); +#endif return (SMTPD_CHECK_DUNNO); } @@ -1793,12 +1818,20 @@ static int check_table_result(SMTPD_STATE *state, const char *table, * DISCARD means silently discard and claim successful delivery. */ if (STREQUAL(value, "DISCARD", cmd_len)) { - if (state->action == 0) +#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)); - state->action->flags |= SMTPD_MSG_ACT_DISCARD; +#ifndef TEST + rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d", + CLEANUP_FLAG_DISCARD); + state->discard = 1; +#endif return (SMTPD_CHECK_OK); } @@ -1807,8 +1840,12 @@ static int check_table_result(SMTPD_STATE *state, const char *table, * change our mind, and reject/discard the message for other reasons. */ if (STREQUAL(value, "REDIRECT", cmd_len)) { - if (state->action == 0) +#ifndef TEST + if (state->dest == 0) { + warn_skip_access_action(table, "REDIRECT", reply_class); return (SMTPD_CHECK_DUNNO); + } +#endif if (strchr(cmd_text, '@') == 0) { msg_warn("access map %s entry \"%s\" requires user@domain target", table, datum); @@ -1817,10 +1854,9 @@ static int check_table_result(SMTPD_STATE *state, const char *table, vstring_sprintf(error_text, "<%s>: %s triggers REDIRECT %s", reply_name, reply_class, cmd_text); log_whatsup(state, "redirect", STR(error_text)); - state->action->flags |= SMTPD_MSG_ACT_REDIRECT; - if (state->action->redirect) - myfree(state->action->redirect); - state->action->redirect = mystrdup(cmd_text); +#ifndef TEST + rec_fprintf(state->dest->stream, REC_TYPE_RDR, "%s", cmd_text); +#endif return (SMTPD_CHECK_DUNNO); } } @@ -2649,7 +2685,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, for (cpp = restrictions->argv; (name = *cpp) != 0; cpp++) { - if (state->action && SMTPD_MSG_ACT_FLAGS(state) & SMTPD_MSG_ACT_FINAL) + if (state->discard != 0) break; if (msg_verbose) @@ -2972,20 +3008,6 @@ char *smtpd_check_client(SMTPD_STATE *state) */ state->defer_if_permit.active = 0; - /* - * With smtpd_delay_reject=yes, smtpd_client_restrictions is evaluated at - * RCPT TO time, and may be evaluated multiple times. Per-message side - * effects (HOLD, DISCARD, etc.) accumulate from one evaluation to the - * next, and may also depend on helo, sender or recipient information. - * - * With smtpd_delay_reject=no, smtpd_{client,helo}_restrictions are - * evaluated immediately, and HELO may be given multiple times. The same - * {client,helo} per-message side effects (HOLD, DISCARD, etc.) apply to - * multiple deliveries. Therefore, we need separate per-message side - * effect storage for client, helo, and for sender+recipients. - */ - state->action = &state->action_client; - /* * Apply restrictions in the order as specified. */ @@ -3040,20 +3062,6 @@ char *smtpd_check_helo(SMTPD_STATE *state, char *helohost) */ state->defer_if_permit.active = state->defer_if_permit_client; - /* - * With smtpd_delay_reject=yes, smtpd_helo_restrictions is evaluated at - * RCPT TO time, and may be evaluated multiple times. Per-message side - * effects (HOLD, DISCARD, etc.) accumulate from one evaluation to the - * next, and may also depend on sender or recipient information. - * - * With smtpd_delay_reject=no, smtpd_{client,helo}_restrictions are - * evaluated immediately, and HELO may be given multiple times. The same - * {client,helo} per-message side effects (HOLD, DISCARD, etc.) apply to - * multiple deliveries. Therefore, we need separate per-message side - * effect storage for client, helo, and for sender+recipients. - */ - state->action = &state->action_helo; - /* * Apply restrictions in the order as specified. */ @@ -3099,14 +3107,6 @@ char *smtpd_check_mail(SMTPD_STATE *state, char *sender) state->defer_if_permit.active = state->defer_if_permit_client | state->defer_if_permit_helo; - /* - * With smtpd_delay_reject=yes, smtpd_sender_restrictions is evaluated at - * RCPT TO time, and may be evaluated multiple times. Per-message side - * effects (HOLD, DISCARD, etc.) accumulate from one evaluation to the - * next, and may also depend on client, helo or recipient information. - */ - state->action = &state->action_mailrcpt; - /* * Apply restrictions in the order as specified. */ @@ -3171,10 +3171,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; @@ -3194,13 +3191,6 @@ char *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient) */ state->defer_if_permit.active = state->defer_if_permit_sender; - /* - * Per-message side effects (HOLD, DISCARD, etc.) accumulate from one - * recipient to the next, and may also depend on client, helo or sender - * information. - */ - state->action = &state->action_mailrcpt; - /* * Apply restrictions in the order as specified. */ @@ -3222,8 +3212,8 @@ char *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient) * If the "check_recipient_maps" restriction was not applied, and if mail * is not being rejected or discarded, validate the recipient here. */ - if (status == 0 && state->rcptmap_checked == 0 - && (SMTPD_MSG_ACT_FLAGS(state) & SMTPD_MSG_ACT_FINAL) == 0) + 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); @@ -3270,11 +3260,6 @@ char *smtpd_check_etrn(SMTPD_STATE *state, char *domain) state->defer_if_permit.active = state->defer_if_permit_client | state->defer_if_permit_helo; - /* - * HOLD, DISCARD, FILTER, etc. are meaningless. - */ - state->action = 0; - /* * Apply restrictions in the order as specified. */ @@ -3295,32 +3280,20 @@ char *smtpd_check_etrn(SMTPD_STATE *state, char *domain) SMTPD_CHECK_ETRN_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); } -/* smtpd_check_vrfy - permit if recipient address matches lookup table */ - -char *smtpd_check_vrfy(SMTPD_STATE *state, char *recipient) -{ - char *myname = "smtpd_check_vrfy"; - int status; - - if (msg_verbose) - msg_info("%s: %s", myname, recipient); - - /* - * Return here in case of serious trouble. - */ - SMTPD_CHECK_RESET(); - 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) { const RESOLVE_REPLY *reply; + /* + * Duplicate suppression. There's an implicit check_recipient_maps + * restriction at the end of all recipient restrictions. + */ + if (state->rcptmap_checked == 1) + return (0); + state->rcptmap_checked = 1; + /* * Resolve the address. */ @@ -3959,8 +3932,6 @@ int main(int argc, char **argv) state.namaddr = concatenate(state.name, "[", state.addr, "]", (char *) 0); resp = smtpd_check_client(&state); - SMTPD_MSG_ACT_FREE(state.action_client); - SMTPD_MSG_ACT_ZERO(state.action_client); } break; @@ -4072,22 +4043,16 @@ int main(int argc, char **argv) if (strcasecmp(args->argv[0], "helo") == 0) { state.where = "HELO"; resp = smtpd_check_helo(&state, args->argv[1]); - SMTPD_MSG_ACT_FREE(state.action_helo); - SMTPD_MSG_ACT_ZERO(state.action_helo); UPDATE_STRING(state.helo_name, args->argv[1]); } else if (strcasecmp(args->argv[0], "mail") == 0) { state.where = "MAIL"; TRIM_ADDR(args->argv[1], addr); UPDATE_STRING(state.sender, addr); resp = smtpd_check_mail(&state, addr); - SMTPD_MSG_ACT_FREE(state.action_mailrcpt); - SMTPD_MSG_ACT_ZERO(state.action_mailrcpt); } else if (strcasecmp(args->argv[0], "rcpt") == 0) { state.where = "RCPT"; TRIM_ADDR(args->argv[1], addr); resp = smtpd_check_rcpt(&state, addr); - SMTPD_MSG_ACT_FREE(state.action_mailrcpt); - SMTPD_MSG_ACT_ZERO(state.action_mailrcpt); } break; diff --git a/postfix/src/smtpd/smtpd_check.h b/postfix/src/smtpd/smtpd_check.h index e05b80a7d..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_vrfy(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_state.c b/postfix/src/smtpd/smtpd_state.c index d3694839f..6475ae49b 100644 --- a/postfix/src/smtpd/smtpd_state.c +++ b/postfix/src/smtpd/smtpd_state.c @@ -92,14 +92,12 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream) state->recursion = 0; state->msg_size = 0; state->junk_cmds = 0; - SMTPD_MSG_ACT_ZERO(state->action_client); - SMTPD_MSG_ACT_ZERO(state->action_helo); - SMTPD_MSG_ACT_ZERO(state->action_mailrcpt); state->defer_if_permit_client = 0; state->defer_if_permit_helo = 0; 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 @@ -139,9 +137,6 @@ void smtpd_state_reset(SMTPD_STATE *state) vstring_free(state->defer_if_reject.reason); if (state->expand_buf) vstring_free(state->expand_buf); - SMTPD_MSG_ACT_FREE(state->action_client); - SMTPD_MSG_ACT_FREE(state->action_helo); - SMTPD_MSG_ACT_FREE(state->action_mailrcpt); #ifdef USE_SASL_AUTH if (var_smtpd_sasl_enable)