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,
|
mantools/postlink, proto/postconf.proto, global/mail_params.h,
|
||||||
global/smtp_stream.c, global/smtp_stream.h, smtpd/smtpd.c.
|
global/smtp_stream.c, global/smtp_stream.h, smtpd/smtpd.c.
|
||||||
|
|
||||||
20231222
|
20231226
|
||||||
|
|
||||||
Workaround: smtpd_forbid_bare_newline broke the BDAT command.
|
Cleanup: a nicer implementation of smtpd_forbid_bare_newline
|
||||||
File: smtpd/smtpd.c.
|
that does not hang up the the middle of a BDAT or DATA
|
||||||
|
command, and that optionally includes the offending command
|
||||||
20231123
|
sequence in a postmaster 'protocol' notification. Files:
|
||||||
|
smtpd/smtpd.c, global/stp_stream.[hc], global/cleanup_user.h,
|
||||||
Bugfix: smtpd_forbid_bare_newline_exclusions should respect
|
global/cleanup_strerror.c.
|
||||||
XCLIENT overrides. File: smtpd/smtpd.c.
|
|
||||||
|
|
||||||
20231224
|
|
||||||
|
|
||||||
Reverted change 20231221 and adopted a fix by Viktor. File:
|
|
||||||
smtpd/smtpd.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_CONT, 550, "5.7.1", "message content rejected",
|
||||||
CLEANUP_STAT_WRITE, 451, "4.3.0", "queue file write error",
|
CLEANUP_STAT_WRITE, 451, "4.3.0", "queue file write error",
|
||||||
CLEANUP_STAT_NOPERM, 550, "5.7.1", "service denied",
|
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 = {
|
static CLEANUP_STAT_DETAIL cleanup_stat_success = {
|
||||||
|
@ -64,6 +64,12 @@
|
|||||||
#define CLEANUP_STAT_DEFER (1<<8) /* Temporary reject */
|
#define CLEANUP_STAT_DEFER (1<<8) /* Temporary reject */
|
||||||
#define CLEANUP_STAT_NOPERM (1<<9) /* Denied by non-content policy */
|
#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.
|
* 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
|
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||||
* patchlevel; they change the release date only.
|
* patchlevel; they change the release date only.
|
||||||
*/
|
*/
|
||||||
#define MAIL_RELEASE_DATE "20231224"
|
#define MAIL_RELEASE_DATE "20231226"
|
||||||
#define MAIL_VERSION_NUMBER "3.9"
|
#define MAIL_VERSION_NUMBER "3.9"
|
||||||
|
|
||||||
#ifdef SNAPSHOT
|
#ifdef SNAPSHOT
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
/* va_list ap;
|
/* va_list ap;
|
||||||
/*
|
/*
|
||||||
/* int smtp_forbid_bare_lf;
|
/* int smtp_forbid_bare_lf;
|
||||||
|
/* int smtp_seen_bare_lf;
|
||||||
/* AUXILIARY API
|
/* AUXILIARY API
|
||||||
/* int smtp_get_noexcept(vp, stream, maxlen, flags)
|
/* int smtp_get_noexcept(vp, stream, maxlen, flags)
|
||||||
/* VSTRING *vp;
|
/* VSTRING *vp;
|
||||||
@ -133,16 +134,17 @@
|
|||||||
/* smtp_vprintf() is the machine underneath smtp_printf().
|
/* smtp_vprintf() is the machine underneath smtp_printf().
|
||||||
/*
|
/*
|
||||||
/* smtp_get_noexcept() implements the subset of smtp_get()
|
/* 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.
|
/* query the stream status with vstream_feof() etc.
|
||||||
/* This function will make a VSTREAM long jump (error code
|
/* This function will set smtp_forbid_bare_lf when flagging
|
||||||
/* SMTP_ERR_LF) when rejecting input with a bare newline byte.
|
/* input with a bare newline byte.
|
||||||
/*
|
/*
|
||||||
/* smtp_timeout_setup() is a backwards-compatibility interface
|
/* smtp_timeout_setup() is a backwards-compatibility interface
|
||||||
/* for programs that don't require deadline or data-rate support.
|
/* for programs that don't require deadline or data-rate support.
|
||||||
/*
|
/*
|
||||||
/* smtp_forbid_bare_lf controls whether smtp_get_noexcept()
|
/* 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
|
/* DIAGNOSTICS
|
||||||
/* .fi
|
/* .fi
|
||||||
/* .ad
|
/* .ad
|
||||||
@ -222,6 +224,7 @@
|
|||||||
* body content one line at a time.
|
* body content one line at a time.
|
||||||
*/
|
*/
|
||||||
int smtp_forbid_bare_lf;
|
int smtp_forbid_bare_lf;
|
||||||
|
int smtp_seen_bare_lf;
|
||||||
|
|
||||||
/* smtp_timeout_reset - reset per-stream error flags */
|
/* 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 last_char;
|
||||||
int next_char;
|
int next_char;
|
||||||
|
|
||||||
|
smtp_seen_bare_lf = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It's painful to do I/O with records that may span multiple buffers.
|
* 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
|
* 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);
|
vstring_truncate(vp, VSTRING_LEN(vp) - 1);
|
||||||
if (smtp_forbid_bare_lf
|
if (smtp_forbid_bare_lf
|
||||||
&& (VSTRING_LEN(vp) == 0 || vstring_end(vp)[-1] != '\r'))
|
&& (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')
|
while (VSTRING_LEN(vp) > 0 && vstring_end(vp)[-1] == '\r')
|
||||||
vstring_truncate(vp, VSTRING_LEN(vp) - 1);
|
vstring_truncate(vp, VSTRING_LEN(vp) - 1);
|
||||||
VSTRING_TERMINATE(vp);
|
VSTRING_TERMINATE(vp);
|
||||||
|
@ -32,7 +32,6 @@
|
|||||||
#define SMTP_ERR_QUIET 3 /* silent cleanup (application) */
|
#define SMTP_ERR_QUIET 3 /* silent cleanup (application) */
|
||||||
#define SMTP_ERR_NONE 4 /* non-error case */
|
#define SMTP_ERR_NONE 4 /* non-error case */
|
||||||
#define SMTP_ERR_DATA 5 /* application data error */
|
#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 smtp_stream_setup(VSTREAM *, int, int, int);
|
||||||
extern void PRINTFLIKE(2, 3) smtp_printf(VSTREAM *, const char *,...);
|
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_fread_buf(VSTRING *, ssize_t len, VSTREAM *);
|
||||||
extern void smtp_fputc(int, VSTREAM *);
|
extern void smtp_fputc(int, VSTREAM *);
|
||||||
extern int smtp_forbid_bare_lf;
|
extern int smtp_forbid_bare_lf;
|
||||||
|
extern int smtp_seen_bare_lf;
|
||||||
|
|
||||||
extern void smtp_vprintf(VSTREAM *, const char *, va_list);
|
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_TIMEOUT "timeout"
|
||||||
#define REASON_LOST_CONNECTION "lost connection"
|
#define REASON_LOST_CONNECTION "lost connection"
|
||||||
#define REASON_ERROR_LIMIT "too many errors"
|
#define REASON_ERROR_LIMIT "too many errors"
|
||||||
#define REASON_BARE_LF "bare <LF> received"
|
|
||||||
|
|
||||||
#ifdef USE_TLS
|
#ifdef USE_TLS
|
||||||
|
|
||||||
@ -3625,6 +3624,8 @@ static void receive_data_message(SMTPD_STATE *state,
|
|||||||
curr_rec_type = REC_TYPE_NORM;
|
curr_rec_type = REC_TYPE_NORM;
|
||||||
else
|
else
|
||||||
curr_rec_type = REC_TYPE_CONT;
|
curr_rec_type = REC_TYPE_CONT;
|
||||||
|
if (smtp_seen_bare_lf)
|
||||||
|
state->err |= CLEANUP_STAT_BARE_LF;
|
||||||
start = vstring_str(state->buffer);
|
start = vstring_str(state->buffer);
|
||||||
len = VSTRING_LEN(state->buffer);
|
len = VSTRING_LEN(state->buffer);
|
||||||
if (first) {
|
if (first) {
|
||||||
@ -3792,6 +3793,12 @@ static int common_post_message_handling(SMTPD_STATE *state)
|
|||||||
else
|
else
|
||||||
smtpd_chat_reply(state,
|
smtpd_chat_reply(state,
|
||||||
"250 2.0.0 Ok: queued as %s", state->queue_id);
|
"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))) {
|
} else if (why && IS_SMTP_REJECT(STR(why))) {
|
||||||
state->error_mask |= MAIL_ERROR_POLICY;
|
state->error_mask |= MAIL_ERROR_POLICY;
|
||||||
smtpd_chat_reply(state, "%s", STR(why));
|
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;
|
done = 0;
|
||||||
do {
|
do {
|
||||||
int payload_err;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do not skip the smtp_fread_buf() call if read_len == 0. We still
|
* 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);
|
smtp_fread_buf(state->buffer, read_len, state->client);
|
||||||
state->bdat_get_stream = vstream_memreopen(
|
state->bdat_get_stream = vstream_memreopen(
|
||||||
state->bdat_get_stream, state->buffer, O_RDONLY);
|
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
|
* 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 {
|
do {
|
||||||
if (smtp_get_noexcept(state->bdat_get_buffer,
|
if (smtp_get_noexcept(state->bdat_get_buffer,
|
||||||
state->bdat_get_stream,
|
state->bdat_get_stream,
|
||||||
var_line_limit,
|
var_line_limit,
|
||||||
SMTP_GET_FLAG_APPEND) == '\n') {
|
SMTP_GET_FLAG_APPEND) == '\n') {
|
||||||
/* Stopped at end-of-line. */
|
/* Stopped at end-of-line. */
|
||||||
curr_rec_type = REC_TYPE_NORM;
|
curr_rec_type = REC_TYPE_NORM;
|
||||||
} else if (!vstream_feof(state->bdat_get_stream)) {
|
} 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. */
|
/* Skip the out_record() and VSTRING_RESET() calls below. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (smtp_seen_bare_lf)
|
||||||
|
state->err |= CLEANUP_STAT_BARE_LF;
|
||||||
start = vstring_str(state->bdat_get_buffer);
|
start = vstring_str(state->bdat_get_buffer);
|
||||||
len = VSTRING_LEN(state->bdat_get_buffer);
|
len = VSTRING_LEN(state->bdat_get_buffer);
|
||||||
if (state->err == CLEANUP_STAT_OK) {
|
if (state->err == CLEANUP_STAT_OK) {
|
||||||
@ -5597,13 +5601,6 @@ static void smtpd_proto(SMTPD_STATE *state)
|
|||||||
var_myhostname);
|
var_myhostname);
|
||||||
break;
|
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:
|
case 0:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5823,6 +5820,15 @@ static void smtpd_proto(SMTPD_STATE *state)
|
|||||||
}
|
}
|
||||||
watchdog_pat();
|
watchdog_pat();
|
||||||
smtpd_chat_query(state);
|
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. */
|
/* Safety: protect internal interfaces against malformed UTF-8. */
|
||||||
if (var_smtputf8_enable
|
if (var_smtputf8_enable
|
||||||
&& valid_utf8_stringz(STR(state->buffer)) == 0) {
|
&& valid_utf8_stringz(STR(state->buffer)) == 0) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user