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:
parent
27a36cbeed
commit
5395c4ff48
@ -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.
|
||||
|
@ -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 = {
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user