2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-22 18:07:41 +00:00

postfix-3.9-20231226

This commit is contained in:
Wietse Venema 2023-12-26 00:00:00 -05:00 committed by Viktor Dukhovni
parent 27a36cbeed
commit 5395c4ff48
7 changed files with 48 additions and 36 deletions

View File

@ -27644,17 +27644,11 @@ Apologies for any names omitted.
mantools/postlink, proto/postconf.proto, global/mail_params.h,
global/smtp_stream.c, global/smtp_stream.h, smtpd/smtpd.c.
20231222
20231226
Workaround: smtpd_forbid_bare_newline broke the BDAT command.
File: smtpd/smtpd.c.
20231123
Bugfix: smtpd_forbid_bare_newline_exclusions should respect
XCLIENT overrides. File: smtpd/smtpd.c.
20231224
Reverted change 20231221 and adopted a fix by Viktor. File:
smtpd/smtpd.c.
Cleanup: a nicer implementation of smtpd_forbid_bare_newline
that does not hang up the the middle of a BDAT or DATA
command, and that optionally includes the offending command
sequence in a postmaster 'protocol' notification. Files:
smtpd/smtpd.c, global/stp_stream.[hc], global/cleanup_user.h,
global/cleanup_strerror.c.

View File

@ -73,6 +73,7 @@ static const CLEANUP_STAT_DETAIL cleanup_stat_map[] = {
CLEANUP_STAT_CONT, 550, "5.7.1", "message content rejected",
CLEANUP_STAT_WRITE, 451, "4.3.0", "queue file write error",
CLEANUP_STAT_NOPERM, 550, "5.7.1", "service denied",
CLEANUP_STAT_BARE_LF, 521, "5.5.2", "bare <LF> received",
};
static CLEANUP_STAT_DETAIL cleanup_stat_success = {

View File

@ -64,6 +64,12 @@
#define CLEANUP_STAT_DEFER (1<<8) /* Temporary reject */
#define CLEANUP_STAT_NOPERM (1<<9) /* Denied by non-content policy */
/*
* Non-cleanup errors that live in the same bitmask space, to centralize
* error handling.
*/
#define CLEANUP_STAT_BARE_LF (1<<16) /* Bare <LF> received */
/*
* These are set when we can't bounce even if we were asked to.
*/

View File

@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
#define MAIL_RELEASE_DATE "20231224"
#define MAIL_RELEASE_DATE "20231226"
#define MAIL_VERSION_NUMBER "3.9"
#ifdef SNAPSHOT

View File

@ -54,6 +54,7 @@
/* va_list ap;
/*
/* int smtp_forbid_bare_lf;
/* int smtp_seen_bare_lf;
/* AUXILIARY API
/* int smtp_get_noexcept(vp, stream, maxlen, flags)
/* VSTRING *vp;
@ -133,16 +134,17 @@
/* smtp_vprintf() is the machine underneath smtp_printf().
/*
/* smtp_get_noexcept() implements the subset of smtp_get()
/* without long jumps for timeout or EOF errors. Instead,
/* without timeouts and without making long jumps. Instead
/* query the stream status with vstream_feof() etc.
/* This function will make a VSTREAM long jump (error code
/* SMTP_ERR_LF) when rejecting input with a bare newline byte.
/* This function will set smtp_forbid_bare_lf when flagging
/* input with a bare newline byte.
/*
/* smtp_timeout_setup() is a backwards-compatibility interface
/* for programs that don't require deadline or data-rate support.
/*
/* smtp_forbid_bare_lf controls whether smtp_get_noexcept()
/* will reject input with a bare newline byte.
/* will set smtp_seen_bare_lf when the line that was read last
/* ended with a bare newline byte.
/* DIAGNOSTICS
/* .fi
/* .ad
@ -222,6 +224,7 @@
* body content one line at a time.
*/
int smtp_forbid_bare_lf;
int smtp_seen_bare_lf;
/* smtp_timeout_reset - reset per-stream error flags */
@ -384,6 +387,8 @@ int smtp_get_noexcept(VSTRING *vp, VSTREAM *stream, ssize_t bound, int flags
int last_char;
int next_char;
smtp_seen_bare_lf = 0;
/*
* It's painful to do I/O with records that may span multiple buffers.
* Allow for partial long lines (we will read the remainder later) and
@ -428,7 +433,7 @@ int smtp_get_noexcept(VSTRING *vp, VSTREAM *stream, ssize_t bound, int flags
vstring_truncate(vp, VSTRING_LEN(vp) - 1);
if (smtp_forbid_bare_lf
&& (VSTRING_LEN(vp) == 0 || vstring_end(vp)[-1] != '\r'))
vstream_longjmp(stream, SMTP_ERR_LF);
smtp_seen_bare_lf = 1;
while (VSTRING_LEN(vp) > 0 && vstring_end(vp)[-1] == '\r')
vstring_truncate(vp, VSTRING_LEN(vp) - 1);
VSTRING_TERMINATE(vp);

View File

@ -32,7 +32,6 @@
#define SMTP_ERR_QUIET 3 /* silent cleanup (application) */
#define SMTP_ERR_NONE 4 /* non-error case */
#define SMTP_ERR_DATA 5 /* application data error */
#define SMTP_ERR_LF 6 /* bare <LF> protocol error */
extern void smtp_stream_setup(VSTREAM *, int, int, int);
extern void PRINTFLIKE(2, 3) smtp_printf(VSTREAM *, const char *,...);
@ -45,6 +44,7 @@ extern void smtp_fwrite(const char *, ssize_t len, VSTREAM *);
extern void smtp_fread_buf(VSTRING *, ssize_t len, VSTREAM *);
extern void smtp_fputc(int, VSTREAM *);
extern int smtp_forbid_bare_lf;
extern int smtp_seen_bare_lf;
extern void smtp_vprintf(VSTREAM *, const char *, va_list);

View File

@ -1620,7 +1620,6 @@ static void tls_reset(SMTPD_STATE *);
#define REASON_TIMEOUT "timeout"
#define REASON_LOST_CONNECTION "lost connection"
#define REASON_ERROR_LIMIT "too many errors"
#define REASON_BARE_LF "bare <LF> received"
#ifdef USE_TLS
@ -3625,6 +3624,8 @@ static void receive_data_message(SMTPD_STATE *state,
curr_rec_type = REC_TYPE_NORM;
else
curr_rec_type = REC_TYPE_CONT;
if (smtp_seen_bare_lf)
state->err |= CLEANUP_STAT_BARE_LF;
start = vstring_str(state->buffer);
len = VSTRING_LEN(state->buffer);
if (first) {
@ -3792,6 +3793,12 @@ static int common_post_message_handling(SMTPD_STATE *state)
else
smtpd_chat_reply(state,
"250 2.0.0 Ok: queued as %s", state->queue_id);
} else if ((state->err & CLEANUP_STAT_BARE_LF) != 0) {
/* Disconnect immediately. */
state->error_mask |= MAIL_ERROR_PROTOCOL;
msg_info("disconnect: bare <LF> received from %s", state->namaddr);
smtpd_chat_reply(state, "521 5.5.2 %s Error: bare <LF> received",
var_myhostname);
} else if (why && IS_SMTP_REJECT(STR(why))) {
state->error_mask |= MAIL_ERROR_POLICY;
smtpd_chat_reply(state, "%s", STR(why));
@ -4079,7 +4086,6 @@ static int bdat_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
*/
done = 0;
do {
int payload_err;
/*
* Do not skip the smtp_fread_buf() call if read_len == 0. We still
@ -4093,10 +4099,6 @@ static int bdat_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
smtp_fread_buf(state->buffer, read_len, state->client);
state->bdat_get_stream = vstream_memreopen(
state->bdat_get_stream, state->buffer, O_RDONLY);
vstream_control(state->bdat_get_stream, CA_VSTREAM_CTL_EXCEPT,
CA_VSTREAM_CTL_END);
if ((payload_err = vstream_setjmp(state->bdat_get_stream)) != 0)
vstream_longjmp(state->client, payload_err);
/*
* Read lines from the fragment. The last line may continue in the
@ -4104,9 +4106,9 @@ static int bdat_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
*/
do {
if (smtp_get_noexcept(state->bdat_get_buffer,
state->bdat_get_stream,
var_line_limit,
SMTP_GET_FLAG_APPEND) == '\n') {
state->bdat_get_stream,
var_line_limit,
SMTP_GET_FLAG_APPEND) == '\n') {
/* Stopped at end-of-line. */
curr_rec_type = REC_TYPE_NORM;
} else if (!vstream_feof(state->bdat_get_stream)) {
@ -4121,6 +4123,8 @@ static int bdat_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
/* Skip the out_record() and VSTRING_RESET() calls below. */
break;
}
if (smtp_seen_bare_lf)
state->err |= CLEANUP_STAT_BARE_LF;
start = vstring_str(state->bdat_get_buffer);
len = VSTRING_LEN(state->bdat_get_buffer);
if (state->err == CLEANUP_STAT_OK) {
@ -5597,13 +5601,6 @@ static void smtpd_proto(SMTPD_STATE *state)
var_myhostname);
break;
case SMTP_ERR_LF:
state->reason = REASON_BARE_LF;
if (vstream_setjmp(state->client) == 0)
smtpd_chat_reply(state, "521 5.5.2 %s Error: bare <LF> received",
var_myhostname);
break;
case 0:
/*
@ -5823,6 +5820,15 @@ static void smtpd_proto(SMTPD_STATE *state)
}
watchdog_pat();
smtpd_chat_query(state);
if (smtp_seen_bare_lf) {
msg_info("disconnect: bare <LF> received from %s",
state->namaddr);
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state,
"521 5.5.2 %s Error: bare <LF> received",
var_myhostname);
break;
}
/* Safety: protect internal interfaces against malformed UTF-8. */
if (var_smtputf8_enable
&& valid_utf8_stringz(STR(state->buffer)) == 0) {