summaryrefslogtreecommitdiff
path: root/gnu/dist/postfix/src/smtpd
diff options
context:
space:
mode:
authorheas <heas@NetBSD.org>2004-03-27 16:31:19 +0000
committerheas <heas@NetBSD.org>2004-03-27 16:31:19 +0000
commitf32166d8a91a2c82316a00a40ee4842e27ec245d (patch)
tree23fa8e0342da03f7dc80d4e582d0351d2a2f3724 /gnu/dist/postfix/src/smtpd
parent5f1ffa71fcd47bffcc5eb3f23221d6570b558e8f (diff)
merge from 2.0.19 import
Diffstat (limited to 'gnu/dist/postfix/src/smtpd')
-rw-r--r--gnu/dist/postfix/src/smtpd/smtpd.c49
-rw-r--r--gnu/dist/postfix/src/smtpd/smtpd_check.c112
2 files changed, 101 insertions, 60 deletions
diff --git a/gnu/dist/postfix/src/smtpd/smtpd.c b/gnu/dist/postfix/src/smtpd/smtpd.c
index 185ddd22777..4fd11947101 100644
--- a/gnu/dist/postfix/src/smtpd/smtpd.c
+++ b/gnu/dist/postfix/src/smtpd/smtpd.c
@@ -59,7 +59,7 @@
/* Disallow non-RFC 821 style addresses in SMTP commands. For example,
/* the RFC822-style address forms with comments that Sendmail allows.
/* .IP \fBbroken_sasl_auth_clients\fR
-/* Support older Microsoft clients that mis-implement the AUTH
+/* Support Microsoft clients that implement an older version of the AUTH
/* protocol, and that expect an EHLO response of "250 AUTH=list"
/* instead of "250 AUTH list".
/* .IP \fBsmtpd_noop_commands\fR
@@ -73,7 +73,7 @@
/* This parameter uses the same syntax as the right-hand side of
/* a Postfix transport table.
/* .SH "Authentication controls"
-/* .IP \fBenable_sasl_authentication\fR
+/* .IP \fBsmtpd_sasl_auth_enable\fR
/* Enable per-session authentication as per RFC 2554 (SASL).
/* This functionality is available only when explicitly selected
/* at program build time and explicitly enabled at runtime.
@@ -629,7 +629,9 @@ static char *extract_addr(SMTPD_STATE *state, SMTPD_TOKEN *arg,
int naddr;
int non_addr;
char *err = 0;
- char *junk;
+ char *junk = 0;
+ char *text;
+ char *colon;
/*
* Special case.
@@ -653,11 +655,19 @@ static char *extract_addr(SMTPD_STATE *state, SMTPD_TOKEN *arg,
msg_info("%s: input: %s", myname, STR(arg->vstrval));
if (STR(arg->vstrval)[0] == '<'
&& STR(arg->vstrval)[LEN(arg->vstrval) - 1] == '>') {
- junk = mystrndup(STR(arg->vstrval) + 1, LEN(arg->vstrval) - 2);
- tree = tok822_parse(junk);
- myfree(junk);
+ junk = text = mystrndup(STR(arg->vstrval) + 1, LEN(arg->vstrval) - 2);
} else
- tree = tok822_parse(STR(arg->vstrval));
+ text = STR(arg->vstrval);
+
+ /*
+ * Truncate deprecated route address form.
+ */
+ if (*text == '@' && (colon = strchr(text, ':')) != 0)
+ text = colon + 1;
+ tree = tok822_parse(text);
+
+ if (junk)
+ myfree(junk);
/*
* Find trouble.
@@ -796,7 +806,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
verp_delims = arg + VERP_CMD_LEN + 1;
if (verp_delims_verify(verp_delims) != 0) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
- smtpd_chat_reply(state, "501 %s needs two characters from %s",
+ smtpd_chat_reply(state, "501 Error: %s needs two characters from %s",
VERP_CMD, var_verp_filter);
return (-1);
}
@@ -808,7 +818,8 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
}
}
if (verp_delims && argv[2].strval[0] == 0) {
- smtpd_chat_reply(state, "503 Error: XVERP requires non-null sender");
+ smtpd_chat_reply(state, "503 Error: %s requires non-null sender",
+ VERP_CMD);
return (-1);
}
state->time = time((time_t *) 0);
@@ -837,10 +848,12 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
/*
* Record the time of arrival and the sender envelope address.
*/
- rec_fprintf(state->cleanup, REC_TYPE_TIME, "%ld",
- (long) time((time_t *) 0));
- if (*var_filter_xport)
- rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport);
+ if (SMTPD_STAND_ALONE(state) == 0) {
+ rec_fprintf(state->cleanup, REC_TYPE_TIME, "%ld",
+ (long) time((time_t *) 0));
+ if (*var_filter_xport)
+ rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport);
+ }
rec_fputs(state->cleanup, REC_TYPE_FROM, argv[2].strval);
if (encoding != 0)
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
@@ -893,6 +906,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 +965,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 +1269,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);
}
@@ -1463,7 +1473,8 @@ static void smtpd_proto(SMTPD_STATE *state)
break;
case 0:
- if (var_smtpd_delay_reject == 0
+ if (SMTPD_STAND_ALONE(state) == 0
+ && var_smtpd_delay_reject == 0
&& (state->access_denied = smtpd_check_client(state)) != 0) {
smtpd_chat_reply(state, "%s", state->access_denied);
} else {
diff --git a/gnu/dist/postfix/src/smtpd/smtpd_check.c b/gnu/dist/postfix/src/smtpd/smtpd_check.c
index 678a86f0b04..755e551a7ae 100644
--- a/gnu/dist/postfix/src/smtpd/smtpd_check.c
+++ b/gnu/dist/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
@@ -795,6 +787,13 @@ static int smtpd_check_reject(SMTPD_STATE *state, int error_class,
va_end(ap);
/*
+ * Ensure RFC compliance. We could do this inside smtpd_chat_reply() and
+ * switch to multi-line for long replies.
+ */
+ vstring_truncate(error_text, 510);
+ VSTRING_TERMINATE(error_text);
+
+ /*
* Validate the response, that is, the response must begin with a
* three-digit status code, and the first digit must be 4 or 5. If the
* response is bad, log a warning and send a generic response instead.
@@ -1622,6 +1621,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 +1697,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 +1727,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 +1745,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 +2588,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 +3041,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 +3067,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 +3078,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 +3150,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 +3227,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 +3515,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 +3535,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 +3914,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;