diff options
| author | Ashish Sharma <asharma@mvista.com> | 2024-01-31 21:53:42 +0530 |
|---|---|---|
| committer | Armin Kuster <akuster808@gmail.com> | 2024-02-07 18:41:41 -0500 |
| commit | 667850f0860379fe643beccfb9bb2a7adb036de8 (patch) | |
| tree | 129e32349e961ea668a008f07cdc190159ca5df3 | |
| parent | f81b181933f33e477c3e81af7f238f0724c05d33 (diff) | |
| download | meta-openembedded-667850f0860379fe643beccfb9bb2a7adb036de8.tar.gz | |
postfix: Backport fix for CVE-2023-51764
Import patches from ubuntu launchpad fix CVE-2023-51764
Upstream-Status: Backport from [https://launchpad.net/ubuntu/+source/postfix/3.6.4-1ubuntu1.3]
Signed-off-by: Ashish Sharma <asharma@mvista.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
3 files changed, 1357 insertions, 0 deletions
diff --git a/meta-networking/recipes-daemons/postfix/files/CVE-2023-51764-1.patch b/meta-networking/recipes-daemons/postfix/files/CVE-2023-51764-1.patch new file mode 100644 index 0000000000..65436b704e --- /dev/null +++ b/meta-networking/recipes-daemons/postfix/files/CVE-2023-51764-1.patch | |||
| @@ -0,0 +1,377 @@ | |||
| 1 | From a6596ec37a4892e1d9c2498ecbfc4b8e6be5156a Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Wietse Venema <wietse@porcupine.org> | ||
| 3 | Date: Fri, 22 Dec 2023 00:00:00 -0500 | ||
| 4 | Subject: [PATCH] postfix-3.6.13 | ||
| 5 | --- | ||
| 6 | Upstream-Status: Backport from [https://launchpad.net/ubuntu/+source/postfix/3.6.4-1ubuntu1.3] | ||
| 7 | CVE: CVE-2023-51764 | ||
| 8 | Signed-off-by: Ashish Sharma <asharma@mvista.com> | ||
| 9 | |||
| 10 | man/man5/postconf.5 | 55 +++++++++++++++++++++++++++++++++++++++++++++++ | ||
| 11 | man/man8/smtpd.8 | 9 +++++++ | ||
| 12 | mantools/postlink | 2 + | ||
| 13 | proto/postconf.proto | 52 ++++++++++++++++++++++++++++++++++++++++++++ | ||
| 14 | src/global/mail_params.h | 11 ++++++++- | ||
| 15 | src/global/smtp_stream.c | 14 +++++++++++ | ||
| 16 | src/global/smtp_stream.h | 2 + | ||
| 17 | src/smtpd/smtpd.c | 42 +++++++++++++++++++++++++++++++++++ | ||
| 18 | 8 files changed, 185 insertions(+), 2 deletions(-) | ||
| 19 | |||
| 20 | --- a/man/man5/postconf.5 | ||
| 21 | +++ b/man/man5/postconf.5 | ||
| 22 | @@ -10412,6 +10412,61 @@ | ||
| 23 | parameter $name expansion. | ||
| 24 | .PP | ||
| 25 | This feature is available in Postfix 2.0 and later. | ||
| 26 | +.SH smtpd_forbid_bare_newline (default: Postfix < 3.9: no) | ||
| 27 | +Reply with "Error: bare <LF> received" and disconnect | ||
| 28 | +when a remote SMTP client sends a line ending in <LF>, violating | ||
| 29 | +the RFC 5321 requirement that lines must end in <CR><LF>. | ||
| 30 | +This feature is disbled by default with Postfix < 3.9. Use | ||
| 31 | +smtpd_forbid_bare_newline_exclusions to exclude non\-standard clients | ||
| 32 | +such as netcat. Specify "smtpd_forbid_bare_newline = no" to disable | ||
| 33 | +(not recommended for an Internet\-connected MTA). | ||
| 34 | +.PP | ||
| 35 | +See | ||
| 36 | +https://www.postfix.org/smtp\-smuggling.html for details. | ||
| 37 | +.PP | ||
| 38 | +Example: | ||
| 39 | +.sp | ||
| 40 | +.in +4 | ||
| 41 | +.nf | ||
| 42 | +.na | ||
| 43 | +.ft C | ||
| 44 | +# Disconnect remote SMTP clients that send bare newlines, but allow | ||
| 45 | +# local clients with non\-standard SMTP implementations such as netcat, | ||
| 46 | +# fax machines, or load balancer health checks. | ||
| 47 | +# | ||
| 48 | +smtpd_forbid_bare_newline = yes | ||
| 49 | +smtpd_forbid_bare_newline_exclusions = $mynetworks | ||
| 50 | +.fi | ||
| 51 | +.ad | ||
| 52 | +.ft R | ||
| 53 | +.in -4 | ||
| 54 | +.PP | ||
| 55 | +This feature is available in Postfix >= 3.9, 3.8.4, 3.7.9, | ||
| 56 | +3.6.13, and 3.5.23. | ||
| 57 | +.SH smtpd_forbid_bare_newline_exclusions (default: $mynetworks) | ||
| 58 | +Exclude the specified clients from smtpd_forbid_bare_newline | ||
| 59 | +enforcement. It uses the same syntax and parent\-domain matching | ||
| 60 | +behavior as mynetworks. | ||
| 61 | +.PP | ||
| 62 | +Example: | ||
| 63 | +.sp | ||
| 64 | +.in +4 | ||
| 65 | +.nf | ||
| 66 | +.na | ||
| 67 | +.ft C | ||
| 68 | +# Disconnect remote SMTP clients that send bare newlines, but allow | ||
| 69 | +# local clients with non\-standard SMTP implementations such as netcat, | ||
| 70 | +# fax machines, or load balancer health checks. | ||
| 71 | +# | ||
| 72 | +smtpd_forbid_bare_newline = yes | ||
| 73 | +smtpd_forbid_bare_newline_exclusions = $mynetworks | ||
| 74 | +.fi | ||
| 75 | +.ad | ||
| 76 | +.ft R | ||
| 77 | +.in -4 | ||
| 78 | +.PP | ||
| 79 | +This feature is available in Postfix >= 3.9, 3.8.4, 3.7.9, | ||
| 80 | +3.6.13, and 3.5.23. | ||
| 81 | .SH smtpd_forbidden_commands (default: CONNECT, GET, POST) | ||
| 82 | List of commands that cause the Postfix SMTP server to immediately | ||
| 83 | terminate the session with a 221 code. This can be used to disconnect | ||
| 84 | --- a/man/man8/smtpd.8 | ||
| 85 | +++ b/man/man8/smtpd.8 | ||
| 86 | @@ -808,6 +808,15 @@ | ||
| 87 | The maximal number of AUTH commands that any client is allowed to | ||
| 88 | send to this service per time unit, regardless of whether or not | ||
| 89 | Postfix actually accepts those commands. | ||
| 90 | +.PP | ||
| 91 | +Available in Postfix 3.9, 3.8.4, 3.7.9, 3.6.13, 3.5.23 and later: | ||
| 92 | +.IP "\fBsmtpd_forbid_bare_newline (Postfix < 3.9: no)\fR" | ||
| 93 | +Reply with "Error: bare <LF> received" and disconnect | ||
| 94 | +when a remote SMTP client sends a line ending in <LF>, violating | ||
| 95 | +the RFC 5321 requirement that lines must end in <CR><LF>. | ||
| 96 | +.IP "\fBsmtpd_forbid_bare_newline_exclusions ($mynetworks)\fR" | ||
| 97 | +Exclude the specified clients from smtpd_forbid_bare_newline | ||
| 98 | +enforcement. | ||
| 99 | .SH "TARPIT CONTROLS" | ||
| 100 | .na | ||
| 101 | .nf | ||
| 102 | --- a/mantools/postlink | ||
| 103 | +++ b/mantools/postlink | ||
| 104 | @@ -547,6 +547,8 @@ | ||
| 105 | s;\bsmtpd_error_sleep_time\b;<a href="postconf.5.html#smtpd_error_sleep_time">$&</a>;g; | ||
| 106 | s;\bsmtpd_etrn_restrictions\b;<a href="postconf.5.html#smtpd_etrn_restrictions">$&</a>;g; | ||
| 107 | s;\bsmtpd_expansion_filter\b;<a href="postconf.5.html#smtpd_expansion_filter">$&</a>;g; | ||
| 108 | + s;\bsmtpd_for[-</bB>]*\n*[ <bB>]*bid_bare_newline\b;<a href="postconf.5.html#smtpd_forbi d_bare_newline">$&</a>;g; | ||
| 109 | + s;\bsmtpd_for[-</bB>]*\n*[ <bB>]*bid_bare_newline_exclusions\b;<a href="postconf.5.html# smtpd_forbid_bare_newline_exclusions">$&</a>;g; | ||
| 110 | s;\bsmtpd_for[-</bB>]*\n*[ <bB>]*bidden_commands\b;<a href="postconf.5.html#smtpd_forbidden_commands">$&</a>;g; | ||
| 111 | s;\bsmtpd_hard_error_limit\b;<a href="postconf.5.html#smtpd_hard_error_limit">$&</a>;g; | ||
| 112 | s;\bsmtpd_helo_required\b;<a href="postconf.5.html#smtpd_helo_required">$&</a>;g; | ||
| 113 | --- a/proto/postconf.proto | ||
| 114 | +++ b/proto/postconf.proto | ||
| 115 | @@ -18058,3 +18058,55 @@ | ||
| 116 | name or port number. </p> | ||
| 117 | |||
| 118 | <p> This feature is available in Postfix 3.6 and later. </p> | ||
| 119 | + | ||
| 120 | +%PARAM smtpd_forbid_bare_newline Postfix < 3.9: no | ||
| 121 | + | ||
| 122 | +<p> Reply with "Error: bare <LF> received" and disconnect | ||
| 123 | +when a remote SMTP client sends a line ending in <LF>, violating | ||
| 124 | +the RFC 5321 requirement that lines must end in <CR><LF>. | ||
| 125 | +This feature is disbled by default with Postfix < 3.9. Use | ||
| 126 | +smtpd_forbid_bare_newline_exclusions to exclude non-standard clients | ||
| 127 | +such as netcat. Specify "smtpd_forbid_bare_newline = no" to disable | ||
| 128 | +(not recommended for an Internet-connected MTA). </p> | ||
| 129 | + | ||
| 130 | +<p> See <a href="https://www.postfix.org/smtp-smuggling.html"> | ||
| 131 | +https://www.postfix.org/smtp-smuggling.html</a> for details. | ||
| 132 | + | ||
| 133 | +<p> Example: </p> | ||
| 134 | + | ||
| 135 | +<blockquote> | ||
| 136 | +<pre> | ||
| 137 | +# Disconnect remote SMTP clients that send bare newlines, but allow | ||
| 138 | +# local clients with non-standard SMTP implementations such as netcat, | ||
| 139 | +# fax machines, or load balancer health checks. | ||
| 140 | +# | ||
| 141 | +smtpd_forbid_bare_newline = yes | ||
| 142 | +smtpd_forbid_bare_newline_exclusions = $mynetworks | ||
| 143 | +</pre> | ||
| 144 | +</blockquote> | ||
| 145 | + | ||
| 146 | +<p> This feature is available in Postfix ≥ 3.9, 3.8.4, 3.7.9, | ||
| 147 | +3.6.13, and 3.5.23. </p> | ||
| 148 | + | ||
| 149 | +%PARAM smtpd_forbid_bare_newline_exclusions $mynetworks | ||
| 150 | + | ||
| 151 | +<p> Exclude the specified clients from smtpd_forbid_bare_newline | ||
| 152 | +enforcement. It uses the same syntax and parent-domain matching | ||
| 153 | +behavior as mynetworks. </p> | ||
| 154 | + | ||
| 155 | +<p> Example: </p> | ||
| 156 | + | ||
| 157 | +<blockquote> | ||
| 158 | +<pre> | ||
| 159 | +# Disconnect remote SMTP clients that send bare newlines, but allow | ||
| 160 | +# local clients with non-standard SMTP implementations such as netcat, | ||
| 161 | +# fax machines, or load balancer health checks. | ||
| 162 | +# | ||
| 163 | +smtpd_forbid_bare_newline = yes | ||
| 164 | +smtpd_forbid_bare_newline_exclusions = $mynetworks | ||
| 165 | +</pre> | ||
| 166 | +</blockquote> | ||
| 167 | + | ||
| 168 | +<p> This feature is available in Postfix ≥ 3.9, 3.8.4, 3.7.9, | ||
| 169 | +3.6.13, and 3.5.23. </p> | ||
| 170 | + | ||
| 171 | --- a/src/global/mail_params.h | ||
| 172 | +++ b/src/global/mail_params.h | ||
| 173 | @@ -4170,7 +4170,16 @@ | ||
| 174 | extern char *var_smtpd_dns_re_filter; | ||
| 175 | |||
| 176 | /* | ||
| 177 | - * Share TLS sessions through tlproxy(8). | ||
| 178 | + * Backwards compatibility. | ||
| 179 | + */ | ||
| 180 | +#define VAR_SMTPD_FORBID_BARE_LF "smtpd_forbid_bare_newline" | ||
| 181 | +#define DEF_SMTPD_FORBID_BARE_LF 0 | ||
| 182 | + | ||
| 183 | +#define VAR_SMTPD_FORBID_BARE_LF_EXCL "smtpd_forbid_bare_newline_exclusions" | ||
| 184 | +#define DEF_SMTPD_FORBID_BARE_LF_EXCL "$" VAR_MYNETWORKS | ||
| 185 | + | ||
| 186 | + /* | ||
| 187 | + * Share TLS sessions through tlsproxy(8). | ||
| 188 | */ | ||
| 189 | #define VAR_SMTP_TLS_CONN_REUSE "smtp_tls_connection_reuse" | ||
| 190 | #define DEF_SMTP_TLS_CONN_REUSE 0 | ||
| 191 | --- a/src/global/smtp_stream.c | ||
| 192 | +++ b/src/global/smtp_stream.c | ||
| 193 | @@ -50,6 +50,8 @@ | ||
| 194 | /* VSTREAM *stream; | ||
| 195 | /* char *format; | ||
| 196 | /* va_list ap; | ||
| 197 | +/* | ||
| 198 | +/* int smtp_forbid_bare_lf; | ||
| 199 | /* AUXILIARY API | ||
| 200 | /* int smtp_get_noexcept(vp, stream, maxlen, flags) | ||
| 201 | /* VSTRING *vp; | ||
| 202 | @@ -124,11 +126,16 @@ | ||
| 203 | /* smtp_vprintf() is the machine underneath smtp_printf(). | ||
| 204 | /* | ||
| 205 | /* smtp_get_noexcept() implements the subset of smtp_get() | ||
| 206 | -/* without timeouts and without making long jumps. Instead, | ||
| 207 | +/* without long jumps for timeout or EOF errors. Instead, | ||
| 208 | /* query the stream status with vstream_feof() etc. | ||
| 209 | +/* This function will make a VSTREAM long jump (error code | ||
| 210 | +/* SMTP_ERR_LF) when rejecting input with a bare newline byte. | ||
| 211 | /* | ||
| 212 | /* smtp_timeout_setup() is a backwards-compatibility interface | ||
| 213 | /* for programs that don't require per-record deadline support. | ||
| 214 | +/* | ||
| 215 | +/* smtp_forbid_bare_lf controls whether smtp_get_noexcept() | ||
| 216 | +/* will reject input with a bare newline byte. | ||
| 217 | /* DIAGNOSTICS | ||
| 218 | /* .fi | ||
| 219 | /* .ad | ||
| 220 | @@ -201,6 +208,8 @@ | ||
| 221 | |||
| 222 | #include "smtp_stream.h" | ||
| 223 | |||
| 224 | +int smtp_forbid_bare_lf; | ||
| 225 | + | ||
| 226 | /* smtp_timeout_reset - reset per-stream error flags, restart deadline timer */ | ||
| 227 | |||
| 228 | static void smtp_timeout_reset(VSTREAM *stream) | ||
| 229 | @@ -404,6 +413,9 @@ | ||
| 230 | */ | ||
| 231 | case '\n': | ||
| 232 | vstring_truncate(vp, VSTRING_LEN(vp) - 1); | ||
| 233 | + if (smtp_forbid_bare_lf | ||
| 234 | + && (VSTRING_LEN(vp) == 0 || vstring_end(vp)[-1] != '\r')) | ||
| 235 | + vstream_longjmp(stream, SMTP_ERR_LF); | ||
| 236 | while (VSTRING_LEN(vp) > 0 && vstring_end(vp)[-1] == '\r') | ||
| 237 | vstring_truncate(vp, VSTRING_LEN(vp) - 1); | ||
| 238 | VSTRING_TERMINATE(vp); | ||
| 239 | --- a/src/global/smtp_stream.h | ||
| 240 | +++ b/src/global/smtp_stream.h | ||
| 241 | @@ -32,6 +32,7 @@ | ||
| 242 | #define SMTP_ERR_QUIET 3 /* silent cleanup (application) */ | ||
| 243 | #define SMTP_ERR_NONE 4 /* non-error case */ | ||
| 244 | #define SMTP_ERR_DATA 5 /* application data error */ | ||
| 245 | +#define SMTP_ERR_LF 6 /* bare <LF> protocol error */ | ||
| 246 | |||
| 247 | extern void smtp_stream_setup(VSTREAM *, int, int); | ||
| 248 | extern void PRINTFLIKE(2, 3) smtp_printf(VSTREAM *, const char *,...); | ||
| 249 | @@ -43,6 +44,7 @@ | ||
| 250 | extern void smtp_fwrite(const char *, ssize_t len, VSTREAM *); | ||
| 251 | extern void smtp_fread_buf(VSTRING *, ssize_t len, VSTREAM *); | ||
| 252 | extern void smtp_fputc(int, VSTREAM *); | ||
| 253 | +extern int smtp_forbid_bare_lf; | ||
| 254 | |||
| 255 | extern void smtp_vprintf(VSTREAM *, const char *, va_list); | ||
| 256 | |||
| 257 | --- a/src/smtpd/smtpd.c | ||
| 258 | +++ b/src/smtpd/smtpd.c | ||
| 259 | @@ -762,6 +762,15 @@ | ||
| 260 | /* The maximal number of AUTH commands that any client is allowed to | ||
| 261 | /* send to this service per time unit, regardless of whether or not | ||
| 262 | /* Postfix actually accepts those commands. | ||
| 263 | +/* .PP | ||
| 264 | +/* Available in Postfix 3.9, 3.8.4, 3.7.9, 3.6.13, 3.5.23 and later: | ||
| 265 | +/* .IP "\fBsmtpd_forbid_bare_newline (Postfix < 3.9: no)\fR" | ||
| 266 | +/* Reply with "Error: bare <LF> received" and disconnect | ||
| 267 | +/* when a remote SMTP client sends a line ending in <LF>, violating | ||
| 268 | +/* the RFC 5321 requirement that lines must end in <CR><LF>. | ||
| 269 | +/* .IP "\fBsmtpd_forbid_bare_newline_exclusions ($mynetworks)\fR" | ||
| 270 | +/* Exclude the specified clients from smtpd_forbid_bare_newline | ||
| 271 | +/* enforcement. | ||
| 272 | /* TARPIT CONTROLS | ||
| 273 | /* .ad | ||
| 274 | /* .fi | ||
| 275 | @@ -1467,6 +1476,10 @@ | ||
| 276 | int var_smtpd_uproxy_tmout; | ||
| 277 | bool var_relay_before_rcpt_checks; | ||
| 278 | |||
| 279 | +bool var_smtpd_forbid_bare_lf; | ||
| 280 | +char *var_smtpd_forbid_bare_lf_excl; | ||
| 281 | +static NAMADR_LIST *bare_lf_excl; | ||
| 282 | + | ||
| 283 | /* | ||
| 284 | * Silly little macros. | ||
| 285 | */ | ||
| 286 | @@ -1541,6 +1554,7 @@ | ||
| 287 | #define REASON_TIMEOUT "timeout" | ||
| 288 | #define REASON_LOST_CONNECTION "lost connection" | ||
| 289 | #define REASON_ERROR_LIMIT "too many errors" | ||
| 290 | +#define REASON_BARE_LF "bare <LF> received" | ||
| 291 | |||
| 292 | #ifdef USE_TLS | ||
| 293 | |||
| 294 | @@ -3967,6 +3981,7 @@ | ||
| 295 | */ | ||
| 296 | done = 0; | ||
| 297 | do { | ||
| 298 | + int payload_err; | ||
| 299 | |||
| 300 | /* | ||
| 301 | * Do not skip the smtp_fread_buf() call if read_len == 0. We still | ||
| 302 | @@ -3980,6 +3995,10 @@ | ||
| 303 | smtp_fread_buf(state->buffer, read_len, state->client); | ||
| 304 | state->bdat_get_stream = vstream_memreopen( | ||
| 305 | state->bdat_get_stream, state->buffer, O_RDONLY); | ||
| 306 | + vstream_control(state->bdat_get_stream, CA_VSTREAM_CTL_EXCEPT, | ||
| 307 | + CA_VSTREAM_CTL_END); | ||
| 308 | + if ((payload_err = vstream_setjmp(state->bdat_get_stream)) != 0) | ||
| 309 | + vstream_longjmp(state->client, payload_err); | ||
| 310 | |||
| 311 | /* | ||
| 312 | * Read lines from the fragment. The last line may continue in the | ||
| 313 | @@ -4655,6 +4674,9 @@ | ||
| 314 | */ | ||
| 315 | xclient_allowed = | ||
| 316 | namadr_list_match(xclient_hosts, state->name, state->addr); | ||
| 317 | + smtp_forbid_bare_lf = SMTPD_STAND_ALONE((state)) == 0 | ||
| 318 | + && var_smtpd_forbid_bare_lf | ||
| 319 | + && !namadr_list_match(bare_lf_excl, state->name, state->addr); | ||
| 320 | /* NOT: tls_reset() */ | ||
| 321 | if (got_helo == 0) | ||
| 322 | helo_reset(state); | ||
| 323 | @@ -5446,6 +5468,13 @@ | ||
| 324 | var_myhostname); | ||
| 325 | break; | ||
| 326 | |||
| 327 | + case SMTP_ERR_LF: | ||
| 328 | + state->reason = REASON_BARE_LF; | ||
| 329 | + if (vstream_setjmp(state->client) == 0) | ||
| 330 | + smtpd_chat_reply(state, "521 5.5.2 %s Error: bare <LF> received", | ||
| 331 | + var_myhostname); | ||
| 332 | + break; | ||
| 333 | + | ||
| 334 | case 0: | ||
| 335 | |||
| 336 | /* | ||
| 337 | @@ -5995,6 +6024,13 @@ | ||
| 338 | namadr_list_match(xforward_hosts, state.name, state.addr); | ||
| 339 | |||
| 340 | /* | ||
| 341 | + * Enforce strict SMTP line endings, with compatibility exclusions. | ||
| 342 | + */ | ||
| 343 | + smtp_forbid_bare_lf = SMTPD_STAND_ALONE((&state)) == 0 | ||
| 344 | + && var_smtpd_forbid_bare_lf | ||
| 345 | + && !namadr_list_match(bare_lf_excl, state.name, state.addr); | ||
| 346 | + | ||
| 347 | + /* | ||
| 348 | * See if we need to turn on verbose logging for this client. | ||
| 349 | */ | ||
| 350 | debug_peer_check(state.name, state.addr); | ||
| 351 | @@ -6055,6 +6091,10 @@ | ||
| 352 | hogger_list = namadr_list_init(VAR_SMTPD_HOGGERS, MATCH_FLAG_RETURN | ||
| 353 | | match_parent_style(VAR_SMTPD_HOGGERS), | ||
| 354 | var_smtpd_hoggers); | ||
| 355 | + bare_lf_excl = namadr_list_init(VAR_SMTPD_FORBID_BARE_LF_EXCL, | ||
| 356 | + MATCH_FLAG_RETURN | ||
| 357 | + | match_parent_style(VAR_MYNETWORKS), | ||
| 358 | + var_smtpd_forbid_bare_lf_excl); | ||
| 359 | |||
| 360 | /* | ||
| 361 | * Open maps before dropping privileges so we can read passwords etc. | ||
| 362 | @@ -6412,6 +6452,7 @@ | ||
| 363 | VAR_SMTPD_PEERNAME_LOOKUP, DEF_SMTPD_PEERNAME_LOOKUP, &var_smtpd_peername_lookup, | ||
| 364 | VAR_SMTPD_DELAY_OPEN, DEF_SMTPD_DELAY_OPEN, &var_smtpd_delay_open, | ||
| 365 | VAR_SMTPD_CLIENT_PORT_LOG, DEF_SMTPD_CLIENT_PORT_LOG, &var_smtpd_client_port_log, | ||
| 366 | + VAR_SMTPD_FORBID_BARE_LF, DEF_SMTPD_FORBID_BARE_LF, &var_smtpd_forbid_bare_lf, | ||
| 367 | 0, | ||
| 368 | }; | ||
| 369 | static const CONFIG_NBOOL_TABLE nbool_table[] = { | ||
| 370 | @@ -6527,6 +6568,7 @@ | ||
| 371 | VAR_SMTPD_POLICY_CONTEXT, DEF_SMTPD_POLICY_CONTEXT, &var_smtpd_policy_context, 0, 0, | ||
| 372 | VAR_SMTPD_DNS_RE_FILTER, DEF_SMTPD_DNS_RE_FILTER, &var_smtpd_dns_re_filter, 0, 0, | ||
| 373 | VAR_SMTPD_REJ_FTR_MAPS, DEF_SMTPD_REJ_FTR_MAPS, &var_smtpd_rej_ftr_maps, 0, 0, | ||
| 374 | + VAR_SMTPD_FORBID_BARE_LF_EXCL, DEF_SMTPD_FORBID_BARE_LF_EXCL, &var_smtpd_forbid_bare_lf_excl, 0, 0, | ||
| 375 | 0, | ||
| 376 | }; | ||
| 377 | static const CONFIG_RAW_TABLE raw_table[] = { | ||
diff --git a/meta-networking/recipes-daemons/postfix/files/CVE-2023-51764-2.patch b/meta-networking/recipes-daemons/postfix/files/CVE-2023-51764-2.patch new file mode 100644 index 0000000000..e97a088557 --- /dev/null +++ b/meta-networking/recipes-daemons/postfix/files/CVE-2023-51764-2.patch | |||
| @@ -0,0 +1,978 @@ | |||
| 1 | From cb3b1cbda3dec086a7f4541fe64751d9bb2988bd Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Wietse Venema <wietse@porcupine.org> | ||
| 3 | Date: Sun, 21 Jan 2024 00:00:00 -0500 | ||
| 4 | Subject: [PATCH] postfix-3.6.14 | ||
| 5 | |||
| 6 | --- | ||
| 7 | |||
| 8 | Upstream-Status: Backport from [https://launchpad.net/ubuntu/+source/postfix/3.6.4-1ubuntu1.3] | ||
| 9 | CVE: CVE-2023-51764 | ||
| 10 | Signed-off-by: Ashish Sharma <asharma@mvista.com> | ||
| 11 | |||
| 12 | man/man5/postconf.5 | 173 +++++++++++++++++++++++++++++++++++------- | ||
| 13 | man/man8/cleanup.8 | 8 + | ||
| 14 | man/man8/smtpd.8 | 11 +- | ||
| 15 | mantools/postlink | 6 - | ||
| 16 | proto/postconf.proto | 142 +++++++++++++++++++++++++++------- | ||
| 17 | src/cleanup/cleanup.c | 8 + | ||
| 18 | src/cleanup/cleanup_init.c | 2 | ||
| 19 | src/cleanup/cleanup_message.c | 17 ++++ | ||
| 20 | src/global/cleanup_strerror.c | 1 | ||
| 21 | src/global/cleanup_user.h | 6 + | ||
| 22 | src/global/mail_params.h | 9 +- | ||
| 23 | src/global/smtp_stream.c | 34 +++++--- | ||
| 24 | src/global/smtp_stream.h | 4 | ||
| 25 | src/smtpd/smtpd.c | 114 ++++++++++++++++++++------- | ||
| 26 | src/smtpd/smtpd_check.c | 14 ++- | ||
| 27 | src/smtpd/smtpd_check.h | 1 | ||
| 28 | 16 files changed, 443 insertions(+), 107 deletions(-) | ||
| 29 | |||
| 30 | --- a/man/man5/postconf.5 | ||
| 31 | +++ b/man/man5/postconf.5 | ||
| 32 | @@ -845,6 +845,32 @@ | ||
| 33 | .fi | ||
| 34 | .ad | ||
| 35 | .ft R | ||
| 36 | +.SH cleanup_replace_stray_cr_lf (default: yes) | ||
| 37 | +Replace each stray <CR> or <LF> character in message | ||
| 38 | +content with a space character, to prevent outbound SMTP smuggling, | ||
| 39 | +and to make the evaluation of Postfix\-added DKIM or other signatures | ||
| 40 | +independent from how a remote mail server handles such characters. | ||
| 41 | +.PP | ||
| 42 | +SMTP does not allow such characters unless they are part of a | ||
| 43 | +<CR><LF> sequence, and different mail systems handle | ||
| 44 | +such stray characters in an implementation\-dependent manner. Stray | ||
| 45 | +<CR> or <LF> characters could be used for outbound | ||
| 46 | +SMTP smuggling, where an attacker uses a Postfix server to send | ||
| 47 | +message content with a non\-standard End\-of\-DATA sequence that | ||
| 48 | +triggers inbound SMTP smuggling at a remote SMTP server. | ||
| 49 | +.PP | ||
| 50 | +The replacement happens before all other content management, | ||
| 51 | +and before Postfix may add a DKIM etc. signature; if the signature | ||
| 52 | +were created first, the replacement could invalidate the signature. | ||
| 53 | +.PP | ||
| 54 | +In addition to preventing SMTP smuggling, replacing stray | ||
| 55 | +<CR> or <LF> characters ensures that the result of | ||
| 56 | +signature validation by later mail system will not depend on how | ||
| 57 | +that mail system handles those stray characters in an | ||
| 58 | +implementation\-dependent manner. | ||
| 59 | +.PP | ||
| 60 | +This feature is available in Postfix >= 3.9, 3.8.5, 3.7.10, | ||
| 61 | +3.6.14, and 3.5.24. | ||
| 62 | .SH cleanup_service_name (default: cleanup) | ||
| 63 | The name of the \fBcleanup\fR(8) service. This service rewrites addresses | ||
| 64 | into the standard form, and performs \fBcanonical\fR(5) address mapping | ||
| 65 | @@ -10413,60 +10439,153 @@ | ||
| 66 | .PP | ||
| 67 | This feature is available in Postfix 2.0 and later. | ||
| 68 | .SH smtpd_forbid_bare_newline (default: Postfix < 3.9: no) | ||
| 69 | -Reply with "Error: bare <LF> received" and disconnect | ||
| 70 | -when a remote SMTP client sends a line ending in <LF>, violating | ||
| 71 | -the RFC 5321 requirement that lines must end in <CR><LF>. | ||
| 72 | -This feature is disbled by default with Postfix < 3.9. Use | ||
| 73 | -smtpd_forbid_bare_newline_exclusions to exclude non\-standard clients | ||
| 74 | -such as netcat. Specify "smtpd_forbid_bare_newline = no" to disable | ||
| 75 | -(not recommended for an Internet\-connected MTA). | ||
| 76 | -.PP | ||
| 77 | -See | ||
| 78 | -https://www.postfix.org/smtp\-smuggling.html for details. | ||
| 79 | +Reject or restrict input lines from an SMTP client that end in | ||
| 80 | +<LF> instead of the standard <CR><LF>. Such line | ||
| 81 | +endings are commonly allowed with UNIX\-based SMTP servers, but they | ||
| 82 | +violate RFC 5321, and allowing such line endings can make a server | ||
| 83 | +vulnerable to | ||
| 84 | +SMTP smuggling. | ||
| 85 | +.PP | ||
| 86 | +Specify one of the following values (case does not matter): | ||
| 87 | +.IP "\fBnormalize\fR" | ||
| 88 | +Require the standard | ||
| 89 | +End\-of\-DATA sequence <CR><LF>.<CR><LF>. | ||
| 90 | +Otherwise, allow command or message content lines ending in the | ||
| 91 | +non\-standard <LF>, and process them as if the client sent the | ||
| 92 | +standard <CR><LF>. | ||
| 93 | +.br | ||
| 94 | +.br | ||
| 95 | +This maintains compatibility | ||
| 96 | +with many legitimate SMTP client applications that send a mix of | ||
| 97 | +standard and non\-standard line endings, but will fail to receive | ||
| 98 | +email from client implementations that do not terminate DATA content | ||
| 99 | +with the standard End\-of\-DATA sequence | ||
| 100 | +<CR><LF>.<CR><LF>. | ||
| 101 | +.br | ||
| 102 | +.br | ||
| 103 | +Such clients | ||
| 104 | +can be excluded with smtpd_forbid_bare_newline_exclusions. | ||
| 105 | +.br | ||
| 106 | +.IP "\fByes\fR" | ||
| 107 | +Compatibility alias for \fBnormalize\fR. | ||
| 108 | +.br | ||
| 109 | +.IP "\fBreject\fR" | ||
| 110 | +Require the standard End\-of\-DATA | ||
| 111 | +sequence <CR><LF>.<CR><LF>. Reject a command | ||
| 112 | +or message content when a line contains bare <LF>, log a "bare | ||
| 113 | +<LF> received" error, and reply with the SMTP status code in | ||
| 114 | +$smtpd_forbid_bare_newline_reject_code. | ||
| 115 | +.br | ||
| 116 | +.br | ||
| 117 | +This will reject | ||
| 118 | +email from SMTP clients that send any non\-standard line endings | ||
| 119 | +such as web applications, netcat, or load balancer health checks. | ||
| 120 | +.br | ||
| 121 | +.br | ||
| 122 | +This will also reject email from services that use BDAT | ||
| 123 | +to send MIME text containing a bare newline (RFC 3030 Section 3 | ||
| 124 | +requires canonical MIME format for text message types, defined in | ||
| 125 | +RFC 2045 Sections 2.7 and 2.8). | ||
| 126 | +.br | ||
| 127 | +.br | ||
| 128 | +Such clients can be | ||
| 129 | +excluded with smtpd_forbid_bare_newline_exclusions (or, in the case | ||
| 130 | +of BDAT violations, BDAT can be selectively disabled with | ||
| 131 | +smtpd_discard_ehlo_keyword_address_maps, or globally disabled with | ||
| 132 | +smtpd_discard_ehlo_keywords). | ||
| 133 | +.br | ||
| 134 | +.IP "\fBno\fR (default)" | ||
| 135 | +Do not require the standard | ||
| 136 | +End\-of\-DATA | ||
| 137 | +sequence <CR><LF>.<CR><LF>. Always process | ||
| 138 | +a bare <LF> as if the client sent <CR><LF>. This | ||
| 139 | +option is fully backwards compatible, but is not recommended for | ||
| 140 | +an Internet\-facing SMTP server, because it is vulnerable to SMTP smuggling. | ||
| 141 | +.br | ||
| 142 | +.br | ||
| 143 | .PP | ||
| 144 | -Example: | ||
| 145 | +Recommended settings: | ||
| 146 | .sp | ||
| 147 | .in +4 | ||
| 148 | .nf | ||
| 149 | .na | ||
| 150 | .ft C | ||
| 151 | -# Disconnect remote SMTP clients that send bare newlines, but allow | ||
| 152 | -# local clients with non\-standard SMTP implementations such as netcat, | ||
| 153 | -# fax machines, or load balancer health checks. | ||
| 154 | +# Require the standard End\-of\-DATA sequence <CR><LF>.<CR><LF>. | ||
| 155 | +# Otherwise, allow bare <LF> and process it as if the client sent | ||
| 156 | +# <CR><LF>. | ||
| 157 | # | ||
| 158 | -smtpd_forbid_bare_newline = yes | ||
| 159 | +# This maintains compatibility with many legitimate SMTP client | ||
| 160 | +# applications that send a mix of standard and non\-standard line | ||
| 161 | +# endings, but will fail to receive email from client implementations | ||
| 162 | +# that do not terminate DATA content with the standard End\-of\-DATA | ||
| 163 | +# sequence <CR><LF>.<CR><LF>. | ||
| 164 | +# | ||
| 165 | +# Such clients can be allowlisted with smtpd_forbid_bare_newline_exclusions. | ||
| 166 | +# The example below allowlists SMTP clients in trusted networks. | ||
| 167 | +# | ||
| 168 | +smtpd_forbid_bare_newline = normalize | ||
| 169 | smtpd_forbid_bare_newline_exclusions = $mynetworks | ||
| 170 | .fi | ||
| 171 | .ad | ||
| 172 | .ft R | ||
| 173 | .in -4 | ||
| 174 | .PP | ||
| 175 | -This feature is available in Postfix >= 3.9, 3.8.4, 3.7.9, | ||
| 176 | -3.6.13, and 3.5.23. | ||
| 177 | -.SH smtpd_forbid_bare_newline_exclusions (default: $mynetworks) | ||
| 178 | -Exclude the specified clients from smtpd_forbid_bare_newline | ||
| 179 | -enforcement. It uses the same syntax and parent\-domain matching | ||
| 180 | -behavior as mynetworks. | ||
| 181 | -.PP | ||
| 182 | -Example: | ||
| 183 | +Alternative: | ||
| 184 | .sp | ||
| 185 | .in +4 | ||
| 186 | .nf | ||
| 187 | .na | ||
| 188 | .ft C | ||
| 189 | -# Disconnect remote SMTP clients that send bare newlines, but allow | ||
| 190 | -# local clients with non\-standard SMTP implementations such as netcat, | ||
| 191 | -# fax machines, or load balancer health checks. | ||
| 192 | +# Reject input lines that contain <LF> and log a "bare <LF> received" | ||
| 193 | +# error. Require that input lines end in <CR><LF>, and require the | ||
| 194 | +# standard End\-of\-DATA sequence <CR><LF>.<CR><LF>. | ||
| 195 | +# | ||
| 196 | +# This will reject email from SMTP clients that send any non\-standard | ||
| 197 | +# line endings such as web applications, netcat, or load balancer | ||
| 198 | +# health checks. | ||
| 199 | # | ||
| 200 | -smtpd_forbid_bare_newline = yes | ||
| 201 | +# This will also reject email from services that use BDAT to send | ||
| 202 | +# MIME text containing a bare newline (RFC 3030 Section 3 requires | ||
| 203 | +# canonical MIME format for text message types, defined in RFC 2045 | ||
| 204 | +# Sections 2.7 and 2.8). | ||
| 205 | +# | ||
| 206 | +# Such clients can be allowlisted with smtpd_forbid_bare_newline_exclusions. | ||
| 207 | +# The example below allowlists SMTP clients in trusted networks. | ||
| 208 | +# | ||
| 209 | +smtpd_forbid_bare_newline = reject | ||
| 210 | smtpd_forbid_bare_newline_exclusions = $mynetworks | ||
| 211 | +# | ||
| 212 | +# Alternatively, in the case of BDAT violations, BDAT can be selectively | ||
| 213 | +# disabled with smtpd_discard_ehlo_keyword_address_maps, or globally | ||
| 214 | +# disabled with smtpd_discard_ehlo_keywords. | ||
| 215 | +# | ||
| 216 | +# smtpd_discard_ehlo_keyword_address_maps = cidr:/path/to/file | ||
| 217 | +# /path/to/file: | ||
| 218 | +# 10.0.0.0/24 chunking, silent\-discard | ||
| 219 | +# smtpd_discard_ehlo_keywords = chunking, silent\-discard | ||
| 220 | .fi | ||
| 221 | .ad | ||
| 222 | .ft R | ||
| 223 | .in -4 | ||
| 224 | .PP | ||
| 225 | +This feature with settings \fByes\fR and \fBno\fR is available | ||
| 226 | +in Postfix 3.8.4, 3.7.9, 3.6.13, and 3.5.23. Additionally, the | ||
| 227 | +settings \fBreject\fR, and \fBnormalize\fR are available with | ||
| 228 | +Postfix >= 3.9, 3.8.5, 3.7.10, 3.6.14, and 3.5.24. | ||
| 229 | +.SH smtpd_forbid_bare_newline_exclusions (default: $mynetworks) | ||
| 230 | +Exclude the specified clients from smtpd_forbid_bare_newline | ||
| 231 | +enforcement. This setting uses the same syntax and parent\-domain | ||
| 232 | +matching behavior as mynetworks. | ||
| 233 | +.PP | ||
| 234 | This feature is available in Postfix >= 3.9, 3.8.4, 3.7.9, | ||
| 235 | 3.6.13, and 3.5.23. | ||
| 236 | +.SH smtpd_forbid_bare_newline_reject_code (default: 550) | ||
| 237 | +The numerical Postfix SMTP server response code when rejecting a | ||
| 238 | +request with "smtpd_forbid_bare_newline = reject". | ||
| 239 | +Specify a 5XX status code (521 to disconnect). | ||
| 240 | +.PP | ||
| 241 | +This feature is available in Postfix >= 3.9, 3.8.5, 3.7.10, | ||
| 242 | +3.6.14, and 3.5.24. | ||
| 243 | .SH smtpd_forbidden_commands (default: CONNECT, GET, POST) | ||
| 244 | List of commands that cause the Postfix SMTP server to immediately | ||
| 245 | terminate the session with a 221 code. This can be used to disconnect | ||
| 246 | --- a/man/man8/cleanup.8 | ||
| 247 | +++ b/man/man8/cleanup.8 | ||
| 248 | @@ -163,6 +163,14 @@ | ||
| 249 | .IP "\fBmessage_strip_characters (empty)\fR" | ||
| 250 | The set of characters that Postfix will remove from message | ||
| 251 | content. | ||
| 252 | +.PP | ||
| 253 | +Available in Postfix version 3.9, 3.8.5, 3.7.10, 3.6.14, | ||
| 254 | +3.5.24, and later: | ||
| 255 | +.IP "\fBcleanup_replace_stray_cr_lf (yes)\fR" | ||
| 256 | +Replace each stray <CR> or <LF> character in message | ||
| 257 | +content with a space character, to prevent outbound SMTP smuggling, | ||
| 258 | +and to make the evaluation of Postfix\-added DKIM or other signatures | ||
| 259 | +independent from how a remote mail server handles such characters. | ||
| 260 | .SH "BEFORE QUEUE MILTER CONTROLS" | ||
| 261 | .na | ||
| 262 | .nf | ||
| 263 | --- a/man/man8/smtpd.8 | ||
| 264 | +++ b/man/man8/smtpd.8 | ||
| 265 | @@ -811,12 +811,17 @@ | ||
| 266 | .PP | ||
| 267 | Available in Postfix 3.9, 3.8.4, 3.7.9, 3.6.13, 3.5.23 and later: | ||
| 268 | .IP "\fBsmtpd_forbid_bare_newline (Postfix < 3.9: no)\fR" | ||
| 269 | -Reply with "Error: bare <LF> received" and disconnect | ||
| 270 | -when a remote SMTP client sends a line ending in <LF>, violating | ||
| 271 | -the RFC 5321 requirement that lines must end in <CR><LF>. | ||
| 272 | +Reject or restrict input lines from an SMTP client that end in | ||
| 273 | +<LF> instead of the standard <CR><LF>. | ||
| 274 | .IP "\fBsmtpd_forbid_bare_newline_exclusions ($mynetworks)\fR" | ||
| 275 | Exclude the specified clients from smtpd_forbid_bare_newline | ||
| 276 | enforcement. | ||
| 277 | +.PP | ||
| 278 | +Available in Postfix 3.9, 3.8.5, 3.7.10, 3.6.14, 3.5.24 and | ||
| 279 | +later: | ||
| 280 | +.IP "\fBsmtpd_forbid_bare_newline_reject_code (550)\fR" | ||
| 281 | +The numerical Postfix SMTP server response code when rejecting a | ||
| 282 | +request with "smtpd_forbid_bare_newline = reject". | ||
| 283 | .SH "TARPIT CONTROLS" | ||
| 284 | .na | ||
| 285 | .nf | ||
| 286 | --- a/mantools/postlink | ||
| 287 | +++ b/mantools/postlink | ||
| 288 | @@ -547,8 +547,10 @@ | ||
| 289 | s;\bsmtpd_error_sleep_time\b;<a href="postconf.5.html#smtpd_error_sleep_time">$&</a>;g; | ||
| 290 | s;\bsmtpd_etrn_restrictions\b;<a href="postconf.5.html#smtpd_etrn_restrictions">$&</a>;g; | ||
| 291 | s;\bsmtpd_expansion_filter\b;<a href="postconf.5.html#smtpd_expansion_filter">$&</a>;g; | ||
| 292 | - s;\bsmtpd_for[-</bB>]*\n*[ <bB>]*bid_bare_newline\b;<a href="postconf.5.html#smtpd_forbi d_bare_newline">$&</a>;g; | ||
| 293 | - s;\bsmtpd_for[-</bB>]*\n*[ <bB>]*bid_bare_newline_exclusions\b;<a href="postconf.5.html# smtpd_forbid_bare_newline_exclusions">$&</a>;g; | ||
| 294 | + s;\bsmtpd_for[-</bB>]*\n*[ <bB>]*bid_bare_new[-</bB>]*\n*[ <bB>]*line\b;<a href="postconf.5.html#smtpd_forbid_bare_newline">$&</a>;g; | ||
| 295 | + s;\bsmtpd_for[-</bB>]*\n*[ <bB>]*bid_bare_new[-</bB>]*\n*[ <bB>]*line_reject_code\b;<a href="postconf.5.html#smtpd_forbid_bare_newline_reject_code">$&</a>;g; | ||
| 296 | + s;\bsmtpd_for[-</bB>]*\n*[ <bB>]*bid_bare_new[-</bB>]*\n*[ <bB>]*line_exclusions\b;<a href="postconf.5.html#smtpd_forbid_bare_newline_exclusions">$&</a>;g; | ||
| 297 | + s;\bcleanup_replace_stray_cr_lf\b;<a href="postconf.5.html#cleanup_replace_stray_cr_lf">$&</a>;g; | ||
| 298 | s;\bsmtpd_for[-</bB>]*\n*[ <bB>]*bidden_commands\b;<a href="postconf.5.html#smtpd_forbidden_commands">$&</a>;g; | ||
| 299 | s;\bsmtpd_hard_error_limit\b;<a href="postconf.5.html#smtpd_hard_error_limit">$&</a>;g; | ||
| 300 | s;\bsmtpd_helo_required\b;<a href="postconf.5.html#smtpd_helo_required">$&</a>;g; | ||
| 301 | --- a/proto/postconf.proto | ||
| 302 | +++ b/proto/postconf.proto | ||
| 303 | @@ -18061,52 +18061,138 @@ | ||
| 304 | |||
| 305 | %PARAM smtpd_forbid_bare_newline Postfix < 3.9: no | ||
| 306 | |||
| 307 | -<p> Reply with "Error: bare <LF> received" and disconnect | ||
| 308 | -when a remote SMTP client sends a line ending in <LF>, violating | ||
| 309 | -the RFC 5321 requirement that lines must end in <CR><LF>. | ||
| 310 | -This feature is disbled by default with Postfix < 3.9. Use | ||
| 311 | -smtpd_forbid_bare_newline_exclusions to exclude non-standard clients | ||
| 312 | -such as netcat. Specify "smtpd_forbid_bare_newline = no" to disable | ||
| 313 | -(not recommended for an Internet-connected MTA). </p> | ||
| 314 | +<p> Reject or restrict input lines from an SMTP client that end in | ||
| 315 | +<LF> instead of the standard <CR><LF>. Such line | ||
| 316 | +endings are commonly allowed with UNIX-based SMTP servers, but they | ||
| 317 | +violate RFC 5321, and allowing such line endings can make a server | ||
| 318 | +vulnerable to <a href="https://www.postfix.org/smtp-smuggling.html"> | ||
| 319 | +SMTP smuggling</a>. </p> | ||
| 320 | + | ||
| 321 | +<p> Specify one of the following values (case does not matter): </p> | ||
| 322 | + | ||
| 323 | +<dl compact> | ||
| 324 | + | ||
| 325 | +<dt> <b>normalize</b></dt> <dd> Require the standard | ||
| 326 | +End-of-DATA sequence <CR><LF>.<CR><LF>. | ||
| 327 | +Otherwise, allow command or message content lines ending in the | ||
| 328 | +non-standard <LF>, and process them as if the client sent the | ||
| 329 | +standard <CR><LF>. <br> <br> This maintains compatibility | ||
| 330 | +with many legitimate SMTP client applications that send a mix of | ||
| 331 | +standard and non-standard line endings, but will fail to receive | ||
| 332 | +email from client implementations that do not terminate DATA content | ||
| 333 | +with the standard End-of-DATA sequence | ||
| 334 | +<CR><LF>.<CR><LF>. <br> <br> Such clients | ||
| 335 | +can be excluded with smtpd_forbid_bare_newline_exclusions. </dd> | ||
| 336 | + | ||
| 337 | +<dt> <b>yes</b> </dt> <dd> Compatibility alias for <b>normalize</b>. </dd> | ||
| 338 | + | ||
| 339 | +<dt> <b>reject</b> </dt> <dd> Require the standard End-of-DATA | ||
| 340 | +sequence <CR><LF>.<CR><LF>. Reject a command | ||
| 341 | +or message content when a line contains bare <LF>, log a "bare | ||
| 342 | +<LF> received" error, and reply with the SMTP status code in | ||
| 343 | +$smtpd_forbid_bare_newline_reject_code. <br> <br> This will reject | ||
| 344 | +email from SMTP clients that send any non-standard line endings | ||
| 345 | +such as web applications, netcat, or load balancer health checks. | ||
| 346 | +<br> <br> This will also reject email from services that use BDAT | ||
| 347 | +to send MIME text containing a bare newline (RFC 3030 Section 3 | ||
| 348 | +requires canonical MIME format for text message types, defined in | ||
| 349 | +RFC 2045 Sections 2.7 and 2.8). <br> <br> Such clients can be | ||
| 350 | +excluded with smtpd_forbid_bare_newline_exclusions (or, in the case | ||
| 351 | +of BDAT violations, BDAT can be selectively disabled with | ||
| 352 | +smtpd_discard_ehlo_keyword_address_maps, or globally disabled with | ||
| 353 | +smtpd_discard_ehlo_keywords). </dd> | ||
| 354 | + | ||
| 355 | +<dt> <b>no</b> (default)</dt> <dd> Do not require the standard | ||
| 356 | +End-of-DATA | ||
| 357 | +sequence <CR><LF>.<CR><LF>. Always process | ||
| 358 | +a bare <LF> as if the client sent <CR><LF>. This | ||
| 359 | +option is fully backwards compatible, but is not recommended for | ||
| 360 | +an Internet-facing SMTP server, because it is vulnerable to <a | ||
| 361 | +href="https://www.postfix.org/smtp-smuggling.html"> SMTP smuggling</a>. | ||
| 362 | +</dd> | ||
| 363 | |||
| 364 | -<p> See <a href="https://www.postfix.org/smtp-smuggling.html"> | ||
| 365 | -https://www.postfix.org/smtp-smuggling.html</a> for details. | ||
| 366 | +</dl> | ||
| 367 | |||
| 368 | -<p> Example: </p> | ||
| 369 | +<p> Recommended settings: </p> | ||
| 370 | |||
| 371 | <blockquote> | ||
| 372 | <pre> | ||
| 373 | -# Disconnect remote SMTP clients that send bare newlines, but allow | ||
| 374 | -# local clients with non-standard SMTP implementations such as netcat, | ||
| 375 | -# fax machines, or load balancer health checks. | ||
| 376 | +# Require the standard End-of-DATA sequence <CR><LF>.<CR><LF>. | ||
| 377 | +# Otherwise, allow bare <LF> and process it as if the client sent | ||
| 378 | +# <CR><LF>. | ||
| 379 | # | ||
| 380 | -smtpd_forbid_bare_newline = yes | ||
| 381 | +# This maintains compatibility with many legitimate SMTP client | ||
| 382 | +# applications that send a mix of standard and non-standard line | ||
| 383 | +# endings, but will fail to receive email from client implementations | ||
| 384 | +# that do not terminate DATA content with the standard End-of-DATA | ||
| 385 | +# sequence <CR><LF>.<CR><LF>. | ||
| 386 | +# | ||
| 387 | +# Such clients can be allowlisted with smtpd_forbid_bare_newline_exclusions. | ||
| 388 | +# The example below allowlists SMTP clients in trusted networks. | ||
| 389 | +# | ||
| 390 | +smtpd_forbid_bare_newline = normalize | ||
| 391 | smtpd_forbid_bare_newline_exclusions = $mynetworks | ||
| 392 | </pre> | ||
| 393 | </blockquote> | ||
| 394 | |||
| 395 | -<p> This feature is available in Postfix ≥ 3.9, 3.8.4, 3.7.9, | ||
| 396 | -3.6.13, and 3.5.23. </p> | ||
| 397 | - | ||
| 398 | -%PARAM smtpd_forbid_bare_newline_exclusions $mynetworks | ||
| 399 | - | ||
| 400 | -<p> Exclude the specified clients from smtpd_forbid_bare_newline | ||
| 401 | -enforcement. It uses the same syntax and parent-domain matching | ||
| 402 | -behavior as mynetworks. </p> | ||
| 403 | - | ||
| 404 | -<p> Example: </p> | ||
| 405 | +<p> Alternative: </p> | ||
| 406 | |||
| 407 | <blockquote> | ||
| 408 | <pre> | ||
| 409 | -# Disconnect remote SMTP clients that send bare newlines, but allow | ||
| 410 | -# local clients with non-standard SMTP implementations such as netcat, | ||
| 411 | -# fax machines, or load balancer health checks. | ||
| 412 | +# Reject input lines that contain <LF> and log a "bare <LF> received" | ||
| 413 | +# error. Require that input lines end in <CR><LF>, and require the | ||
| 414 | +# standard End-of-DATA sequence <CR><LF>.<CR><LF>. | ||
| 415 | +# | ||
| 416 | +# This will reject email from SMTP clients that send any non-standard | ||
| 417 | +# line endings such as web applications, netcat, or load balancer | ||
| 418 | +# health checks. | ||
| 419 | +# | ||
| 420 | +# This will also reject email from services that use BDAT to send | ||
| 421 | +# MIME text containing a bare newline (RFC 3030 Section 3 requires | ||
| 422 | +# canonical MIME format for text message types, defined in RFC 2045 | ||
| 423 | +# Sections 2.7 and 2.8). | ||
| 424 | +# | ||
| 425 | +# Such clients can be allowlisted with smtpd_forbid_bare_newline_exclusions. | ||
| 426 | +# The example below allowlists SMTP clients in trusted networks. | ||
| 427 | # | ||
| 428 | -smtpd_forbid_bare_newline = yes | ||
| 429 | +smtpd_forbid_bare_newline = reject | ||
| 430 | smtpd_forbid_bare_newline_exclusions = $mynetworks | ||
| 431 | +# | ||
| 432 | +# Alternatively, in the case of BDAT violations, BDAT can be selectively | ||
| 433 | +# disabled with smtpd_discard_ehlo_keyword_address_maps, or globally | ||
| 434 | +# disabled with smtpd_discard_ehlo_keywords. | ||
| 435 | +# | ||
| 436 | +# smtpd_discard_ehlo_keyword_address_maps = cidr:/path/to/file | ||
| 437 | +# /path/to/file: | ||
| 438 | +# 10.0.0.0/24 chunking, silent-discard | ||
| 439 | +# smtpd_discard_ehlo_keywords = chunking, silent-discard | ||
| 440 | </pre> | ||
| 441 | </blockquote> | ||
| 442 | |||
| 443 | +<p> This feature with settings <b>yes</b> and <b>no</b> is available | ||
| 444 | +in Postfix 3.8.4, 3.7.9, 3.6.13, and 3.5.23. Additionally, the | ||
| 445 | +settings <b>reject</b>, and <b>normalize</b> are available with | ||
| 446 | +Postfix ≥ 3.9, 3.8.5, 3.7.10, 3.6.14, and 3.5.24. </p> | ||
| 447 | + | ||
| 448 | +%PARAM smtpd_forbid_bare_newline_exclusions $mynetworks | ||
| 449 | + | ||
| 450 | +<p> Exclude the specified clients from smtpd_forbid_bare_newline | ||
| 451 | +enforcement. This setting uses the same syntax and parent-domain | ||
| 452 | +matching behavior as mynetworks. </p> | ||
| 453 | + | ||
| 454 | <p> This feature is available in Postfix ≥ 3.9, 3.8.4, 3.7.9, | ||
| 455 | 3.6.13, and 3.5.23. </p> | ||
| 456 | |||
| 457 | +%PARAM smtpd_forbid_bare_newline_reject_code 550 | ||
| 458 | + | ||
| 459 | +<p> | ||
| 460 | +The numerical Postfix SMTP server response code when rejecting a | ||
| 461 | +request with "smtpd_forbid_bare_newline = reject". | ||
| 462 | +Specify a 5XX status code (521 to disconnect). | ||
| 463 | +</p> | ||
| 464 | + | ||
| 465 | +<p> This feature is available in Postfix ≥ 3.9, 3.8.5, 3.7.10, | ||
| 466 | +3.6.14, and 3.5.24. </p> | ||
| 467 | + | ||
| 468 | +%PARAM cleanup_replace_stray_cr_lf yes | ||
| 469 | + | ||
| 470 | --- a/src/cleanup/cleanup.c | ||
| 471 | +++ b/src/cleanup/cleanup.c | ||
| 472 | @@ -145,6 +145,14 @@ | ||
| 473 | /* .IP "\fBmessage_strip_characters (empty)\fR" | ||
| 474 | /* The set of characters that Postfix will remove from message | ||
| 475 | /* content. | ||
| 476 | +/* .PP | ||
| 477 | +/* Available in Postfix version 3.9, 3.8.5, 3.7.10, 3.6.14, | ||
| 478 | +/* 3.5.24, and later: | ||
| 479 | +/* .IP "\fBcleanup_replace_stray_cr_lf (yes)\fR" | ||
| 480 | +/* Replace each stray <CR> or <LF> character in message | ||
| 481 | +/* content with a space character, to prevent outbound SMTP smuggling, | ||
| 482 | +/* and to make the evaluation of Postfix-added DKIM or other signatures | ||
| 483 | +/* independent from how a remote mail server handles such characters. | ||
| 484 | /* BEFORE QUEUE MILTER CONTROLS | ||
| 485 | /* .ad | ||
| 486 | /* .fi | ||
| 487 | --- a/src/cleanup/cleanup_init.c | ||
| 488 | +++ b/src/cleanup/cleanup_init.c | ||
| 489 | @@ -173,6 +173,7 @@ | ||
| 490 | int var_always_add_hdrs; /* always add missing headers */ | ||
| 491 | int var_virt_addrlen_limit; /* stop exponential growth */ | ||
| 492 | char *var_hfrom_format; /* header_from_format */ | ||
| 493 | +int var_cleanup_mask_stray_cr_lf; /* replace stray CR or LF with space */ | ||
| 494 | |||
| 495 | const CONFIG_INT_TABLE cleanup_int_table[] = { | ||
| 496 | VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0, | ||
| 497 | @@ -189,6 +190,7 @@ | ||
| 498 | VAR_VERP_BOUNCE_OFF, DEF_VERP_BOUNCE_OFF, &var_verp_bounce_off, | ||
| 499 | VAR_AUTO_8BIT_ENC_HDR, DEF_AUTO_8BIT_ENC_HDR, &var_auto_8bit_enc_hdr, | ||
| 500 | VAR_ALWAYS_ADD_HDRS, DEF_ALWAYS_ADD_HDRS, &var_always_add_hdrs, | ||
| 501 | + VAR_CLEANUP_MASK_STRAY_CR_LF, DEF_CLEANUP_MASK_STRAY_CR_LF, &var_cleanup_mask_stray_cr_lf, | ||
| 502 | 0, | ||
| 503 | }; | ||
| 504 | |||
| 505 | --- a/src/cleanup/cleanup_message.c | ||
| 506 | +++ b/src/cleanup/cleanup_message.c | ||
| 507 | @@ -930,6 +930,23 @@ | ||
| 508 | char *dst; | ||
| 509 | |||
| 510 | /* | ||
| 511 | + * Replace each stray CR or LF with one space. These are not allowed in | ||
| 512 | + * SMTP, and can be used to enable outbound (remote) SMTP smuggling. | ||
| 513 | + * Replacing these early ensures that our later DKIM etc. signature will | ||
| 514 | + * not be invalidated. Besides preventing SMTP smuggling, replacing stray | ||
| 515 | + * <CR> or <LF> ensures that the result of signature validation by a | ||
| 516 | + * later mail system will not depend on how that mail system handles | ||
| 517 | + * those stray characters in an implementation-dependent manner. | ||
| 518 | + * | ||
| 519 | + * The input length is not changed, therefore it is safe to overwrite the | ||
| 520 | + * input. | ||
| 521 | + */ | ||
| 522 | + if (var_cleanup_mask_stray_cr_lf) | ||
| 523 | + for (dst = (char *) buf; dst < buf + len; dst++) | ||
| 524 | + if (*dst == '\r' || *dst == '\n') | ||
| 525 | + *dst = ' '; | ||
| 526 | + | ||
| 527 | + /* | ||
| 528 | * Reject unwanted characters. | ||
| 529 | * | ||
| 530 | * XXX Possible optimization: simplify the loop when the "reject" set | ||
| 531 | --- a/src/global/cleanup_strerror.c | ||
| 532 | +++ b/src/global/cleanup_strerror.c | ||
| 533 | @@ -73,6 +73,7 @@ | ||
| 534 | CLEANUP_STAT_CONT, 550, "5.7.1", "message content rejected", | ||
| 535 | CLEANUP_STAT_WRITE, 451, "4.3.0", "queue file write error", | ||
| 536 | CLEANUP_STAT_NOPERM, 550, "5.7.1", "service denied", | ||
| 537 | + CLEANUP_STAT_BARE_LF, 521, "5.5.2", "bare <LF> received", | ||
| 538 | }; | ||
| 539 | |||
| 540 | static CLEANUP_STAT_DETAIL cleanup_stat_success = { | ||
| 541 | --- a/src/global/cleanup_user.h | ||
| 542 | +++ b/src/global/cleanup_user.h | ||
| 543 | @@ -65,6 +65,12 @@ | ||
| 544 | #define CLEANUP_STAT_NOPERM (1<<9) /* Denied by non-content policy */ | ||
| 545 | |||
| 546 | /* | ||
| 547 | + * Non-cleanup errors that live in the same bitmask space, to centralize | ||
| 548 | + * error handling. | ||
| 549 | + */ | ||
| 550 | +#define CLEANUP_STAT_BARE_LF (1<<16) /* Bare <LF> received */ | ||
| 551 | + | ||
| 552 | + /* | ||
| 553 | * These are set when we can't bounce even if we were asked to. | ||
| 554 | */ | ||
| 555 | #define CLEANUP_STAT_MASK_CANT_BOUNCE \ | ||
| 556 | --- a/src/global/mail_params.h | ||
| 557 | +++ b/src/global/mail_params.h | ||
| 558 | @@ -4173,11 +4173,18 @@ | ||
| 559 | * Backwards compatibility. | ||
| 560 | */ | ||
| 561 | #define VAR_SMTPD_FORBID_BARE_LF "smtpd_forbid_bare_newline" | ||
| 562 | -#define DEF_SMTPD_FORBID_BARE_LF 0 | ||
| 563 | +#define DEF_SMTPD_FORBID_BARE_LF "no" | ||
| 564 | |||
| 565 | #define VAR_SMTPD_FORBID_BARE_LF_EXCL "smtpd_forbid_bare_newline_exclusions" | ||
| 566 | #define DEF_SMTPD_FORBID_BARE_LF_EXCL "$" VAR_MYNETWORKS | ||
| 567 | |||
| 568 | +#define VAR_SMTPD_FORBID_BARE_LF_CODE "smtpd_forbid_bare_newline_reject_code" | ||
| 569 | +#define DEF_SMTPD_FORBID_BARE_LF_CODE 550 | ||
| 570 | + | ||
| 571 | +#define VAR_CLEANUP_MASK_STRAY_CR_LF "cleanup_replace_stray_cr_lf" | ||
| 572 | +#define DEF_CLEANUP_MASK_STRAY_CR_LF 1 | ||
| 573 | +extern int var_cleanup_mask_stray_cr_lf; | ||
| 574 | + | ||
| 575 | /* | ||
| 576 | * Share TLS sessions through tlsproxy(8). | ||
| 577 | */ | ||
| 578 | --- a/src/global/smtp_stream.c | ||
| 579 | +++ b/src/global/smtp_stream.c | ||
| 580 | @@ -51,7 +51,8 @@ | ||
| 581 | /* char *format; | ||
| 582 | /* va_list ap; | ||
| 583 | /* | ||
| 584 | -/* int smtp_forbid_bare_lf; | ||
| 585 | +/* int smtp_detect_bare_lf; | ||
| 586 | +/* int smtp_got_bare_lf; | ||
| 587 | /* AUXILIARY API | ||
| 588 | /* int smtp_get_noexcept(vp, stream, maxlen, flags) | ||
| 589 | /* VSTRING *vp; | ||
| 590 | @@ -126,16 +127,16 @@ | ||
| 591 | /* smtp_vprintf() is the machine underneath smtp_printf(). | ||
| 592 | /* | ||
| 593 | /* smtp_get_noexcept() implements the subset of smtp_get() | ||
| 594 | -/* without long jumps for timeout or EOF errors. Instead, | ||
| 595 | +/* without timeouts and without making long jumps. Instead, | ||
| 596 | /* query the stream status with vstream_feof() etc. | ||
| 597 | -/* This function will make a VSTREAM long jump (error code | ||
| 598 | -/* SMTP_ERR_LF) when rejecting input with a bare newline byte. | ||
| 599 | +/* | ||
| 600 | +/* This function assigns smtp_got_bare_lf = smtp_detect_bare_lf, | ||
| 601 | +/* if smtp_detect_bare_lf is non-zero and the last read line | ||
| 602 | +/* was terminated with a bare newline. Otherwise, this function | ||
| 603 | +/* sets smtp_got_bare_lf to zero. | ||
| 604 | /* | ||
| 605 | /* smtp_timeout_setup() is a backwards-compatibility interface | ||
| 606 | /* for programs that don't require per-record deadline support. | ||
| 607 | -/* | ||
| 608 | -/* smtp_forbid_bare_lf controls whether smtp_get_noexcept() | ||
| 609 | -/* will reject input with a bare newline byte. | ||
| 610 | /* DIAGNOSTICS | ||
| 611 | /* .fi | ||
| 612 | /* .ad | ||
| 613 | @@ -208,7 +209,8 @@ | ||
| 614 | |||
| 615 | #include "smtp_stream.h" | ||
| 616 | |||
| 617 | -int smtp_forbid_bare_lf; | ||
| 618 | +int smtp_detect_bare_lf; | ||
| 619 | +int smtp_got_bare_lf; | ||
| 620 | |||
| 621 | /* smtp_timeout_reset - reset per-stream error flags, restart deadline timer */ | ||
| 622 | |||
| 623 | @@ -371,6 +373,8 @@ | ||
| 624 | int last_char; | ||
| 625 | int next_char; | ||
| 626 | |||
| 627 | + smtp_got_bare_lf = 0; | ||
| 628 | + | ||
| 629 | /* | ||
| 630 | * It's painful to do I/O with records that may span multiple buffers. | ||
| 631 | * Allow for partial long lines (we will read the remainder later) and | ||
| 632 | @@ -413,11 +417,15 @@ | ||
| 633 | */ | ||
| 634 | case '\n': | ||
| 635 | vstring_truncate(vp, VSTRING_LEN(vp) - 1); | ||
| 636 | - if (smtp_forbid_bare_lf | ||
| 637 | - && (VSTRING_LEN(vp) == 0 || vstring_end(vp)[-1] != '\r')) | ||
| 638 | - vstream_longjmp(stream, SMTP_ERR_LF); | ||
| 639 | - while (VSTRING_LEN(vp) > 0 && vstring_end(vp)[-1] == '\r') | ||
| 640 | - vstring_truncate(vp, VSTRING_LEN(vp) - 1); | ||
| 641 | + if (smtp_detect_bare_lf) { | ||
| 642 | + if (VSTRING_LEN(vp) == 0 || vstring_end(vp)[-1] != '\r') | ||
| 643 | + smtp_got_bare_lf = smtp_detect_bare_lf; | ||
| 644 | + else | ||
| 645 | + vstring_truncate(vp, VSTRING_LEN(vp) - 1); | ||
| 646 | + } else { | ||
| 647 | + while (VSTRING_LEN(vp) > 0 && vstring_end(vp)[-1] == '\r') | ||
| 648 | + vstring_truncate(vp, VSTRING_LEN(vp) - 1); | ||
| 649 | + } | ||
| 650 | VSTRING_TERMINATE(vp); | ||
| 651 | /* FALLTRHOUGH */ | ||
| 652 | |||
| 653 | --- a/src/global/smtp_stream.h | ||
| 654 | +++ b/src/global/smtp_stream.h | ||
| 655 | @@ -32,7 +32,6 @@ | ||
| 656 | #define SMTP_ERR_QUIET 3 /* silent cleanup (application) */ | ||
| 657 | #define SMTP_ERR_NONE 4 /* non-error case */ | ||
| 658 | #define SMTP_ERR_DATA 5 /* application data error */ | ||
| 659 | -#define SMTP_ERR_LF 6 /* bare <LF> protocol error */ | ||
| 660 | |||
| 661 | extern void smtp_stream_setup(VSTREAM *, int, int); | ||
| 662 | extern void PRINTFLIKE(2, 3) smtp_printf(VSTREAM *, const char *,...); | ||
| 663 | @@ -44,7 +43,8 @@ | ||
| 664 | extern void smtp_fwrite(const char *, ssize_t len, VSTREAM *); | ||
| 665 | extern void smtp_fread_buf(VSTRING *, ssize_t len, VSTREAM *); | ||
| 666 | extern void smtp_fputc(int, VSTREAM *); | ||
| 667 | -extern int smtp_forbid_bare_lf; | ||
| 668 | +extern int smtp_detect_bare_lf; | ||
| 669 | +extern int smtp_got_bare_lf; | ||
| 670 | |||
| 671 | extern void smtp_vprintf(VSTREAM *, const char *, va_list); | ||
| 672 | |||
| 673 | --- a/src/smtpd/smtpd.c | ||
| 674 | +++ b/src/smtpd/smtpd.c | ||
| 675 | @@ -765,12 +765,17 @@ | ||
| 676 | /* .PP | ||
| 677 | /* Available in Postfix 3.9, 3.8.4, 3.7.9, 3.6.13, 3.5.23 and later: | ||
| 678 | /* .IP "\fBsmtpd_forbid_bare_newline (Postfix < 3.9: no)\fR" | ||
| 679 | -/* Reply with "Error: bare <LF> received" and disconnect | ||
| 680 | -/* when a remote SMTP client sends a line ending in <LF>, violating | ||
| 681 | -/* the RFC 5321 requirement that lines must end in <CR><LF>. | ||
| 682 | +/* Reject or restrict input lines from an SMTP client that end in | ||
| 683 | +/* <LF> instead of the standard <CR><LF>. | ||
| 684 | /* .IP "\fBsmtpd_forbid_bare_newline_exclusions ($mynetworks)\fR" | ||
| 685 | /* Exclude the specified clients from smtpd_forbid_bare_newline | ||
| 686 | /* enforcement. | ||
| 687 | +/* .PP | ||
| 688 | +/* Available in Postfix 3.9, 3.8.5, 3.7.10, 3.6.14, 3.5.24 and | ||
| 689 | +/* later: | ||
| 690 | +/* .IP "\fBsmtpd_forbid_bare_newline_reject_code (550)\fR" | ||
| 691 | +/* The numerical Postfix SMTP server response code when rejecting a | ||
| 692 | +/* request with "smtpd_forbid_bare_newline = reject". | ||
| 693 | /* TARPIT CONTROLS | ||
| 694 | /* .ad | ||
| 695 | /* .fi | ||
| 696 | @@ -1476,8 +1481,10 @@ | ||
| 697 | int var_smtpd_uproxy_tmout; | ||
| 698 | bool var_relay_before_rcpt_checks; | ||
| 699 | |||
| 700 | -bool var_smtpd_forbid_bare_lf; | ||
| 701 | +char *var_smtpd_forbid_bare_lf; | ||
| 702 | char *var_smtpd_forbid_bare_lf_excl; | ||
| 703 | +int var_smtpd_forbid_bare_lf_code; | ||
| 704 | +static int bare_lf_mask; | ||
| 705 | static NAMADR_LIST *bare_lf_excl; | ||
| 706 | |||
| 707 | /* | ||
| 708 | @@ -1554,7 +1561,6 @@ | ||
| 709 | #define REASON_TIMEOUT "timeout" | ||
| 710 | #define REASON_LOST_CONNECTION "lost connection" | ||
| 711 | #define REASON_ERROR_LIMIT "too many errors" | ||
| 712 | -#define REASON_BARE_LF "bare <LF> received" | ||
| 713 | |||
| 714 | #ifdef USE_TLS | ||
| 715 | |||
| 716 | @@ -1573,6 +1579,40 @@ | ||
| 717 | */ | ||
| 718 | static DICT *smtpd_cmd_filter; | ||
| 719 | |||
| 720 | + /* | ||
| 721 | + * Bare LF and End-of-DATA controls (bare CR is handled elsewhere). | ||
| 722 | + * | ||
| 723 | + * At the smtp_get*() line reader level, setting any of these flags in the | ||
| 724 | + * smtp_detect_bare_lf variable enables the detection of bare newlines. The | ||
| 725 | + * line reader will set the same flags in the smtp_got_bare_lf variable | ||
| 726 | + * after it detects a bare newline, otherwise it clears smtp_got_bare_lf. | ||
| 727 | + * | ||
| 728 | + * At the SMTP command level, the flags in smtp_got_bare_lf control whether | ||
| 729 | + * commands ending in a bare newline are rejected. | ||
| 730 | + * | ||
| 731 | + * At the DATA and BDAT content level, the flags in smtp_got_bare_lf control | ||
| 732 | + * whether the standard End-of-DATA sequence CRLF.CRLF is required, and | ||
| 733 | + * whether lines ending in bare newlines are rejected. | ||
| 734 | + * | ||
| 735 | + * Postfix implements "delayed reject" after detecting a bare newline in BDAT | ||
| 736 | + * or DATA content. The SMTP server delays a REJECT response until the | ||
| 737 | + * command is finished, instead of replying and hanging up immediately. The | ||
| 738 | + * End-of-DATA detection is secured with BARE_LF_FLAG_WANT_STD_EOD. | ||
| 739 | + */ | ||
| 740 | +#define BARE_LF_FLAG_WANT_STD_EOD (1<<0) /* Require CRLF.CRLF */ | ||
| 741 | +#define BARE_LF_FLAG_REPLY_REJECT (1<<1) /* Reject bare newline */ | ||
| 742 | + | ||
| 743 | +#define IS_BARE_LF_WANT_STD_EOD(m) ((m) & BARE_LF_FLAG_WANT_STD_EOD) | ||
| 744 | +#define IS_BARE_LF_REPLY_REJECT(m) ((m) & BARE_LF_FLAG_REPLY_REJECT) | ||
| 745 | + | ||
| 746 | +static const NAME_CODE bare_lf_mask_table[] = { | ||
| 747 | + "normalize", BARE_LF_FLAG_WANT_STD_EOD, /* Default */ | ||
| 748 | + "yes", BARE_LF_FLAG_WANT_STD_EOD, /* Migration aid */ | ||
| 749 | + "reject", BARE_LF_FLAG_WANT_STD_EOD | BARE_LF_FLAG_REPLY_REJECT, | ||
| 750 | + "no", 0, | ||
| 751 | + 0, -1, /* error */ | ||
| 752 | +}; | ||
| 753 | + | ||
| 754 | #ifdef USE_SASL_AUTH | ||
| 755 | |||
| 756 | /* | ||
| 757 | @@ -3515,6 +3555,7 @@ | ||
| 758 | int curr_rec_type; | ||
| 759 | int prev_rec_type; | ||
| 760 | int first = 1; | ||
| 761 | + int prev_got_bare_lf = 0; | ||
| 762 | |||
| 763 | /* | ||
| 764 | * Copy the message content. If the cleanup process has a problem, keep | ||
| 765 | @@ -3528,12 +3569,15 @@ | ||
| 766 | * XXX Deal with UNIX-style From_ lines at the start of message content | ||
| 767 | * because sendmail permits it. | ||
| 768 | */ | ||
| 769 | - for (prev_rec_type = 0; /* void */ ; prev_rec_type = curr_rec_type) { | ||
| 770 | + for (prev_rec_type = 0; /* void */ ; prev_rec_type = curr_rec_type, | ||
| 771 | + prev_got_bare_lf = smtp_got_bare_lf) { | ||
| 772 | if (smtp_get(state->buffer, state->client, var_line_limit, | ||
| 773 | SMTP_GET_FLAG_NONE) == '\n') | ||
| 774 | curr_rec_type = REC_TYPE_NORM; | ||
| 775 | else | ||
| 776 | curr_rec_type = REC_TYPE_CONT; | ||
| 777 | + if (IS_BARE_LF_REPLY_REJECT(smtp_got_bare_lf)) | ||
| 778 | + state->err |= CLEANUP_STAT_BARE_LF; | ||
| 779 | start = vstring_str(state->buffer); | ||
| 780 | len = VSTRING_LEN(state->buffer); | ||
| 781 | if (first) { | ||
| 782 | @@ -3546,9 +3590,14 @@ | ||
| 783 | if (len > 0 && IS_SPACE_TAB(start[0])) | ||
| 784 | out_record(out_stream, REC_TYPE_NORM, "", 0); | ||
| 785 | } | ||
| 786 | - if (prev_rec_type != REC_TYPE_CONT && *start == '.' | ||
| 787 | - && (proxy == 0 ? (++start, --len) == 0 : len == 1)) | ||
| 788 | - break; | ||
| 789 | + if (prev_rec_type != REC_TYPE_CONT && *start == '.') { | ||
| 790 | + if (len == 1 && IS_BARE_LF_WANT_STD_EOD(smtp_detect_bare_lf) | ||
| 791 | + && (smtp_got_bare_lf || prev_got_bare_lf)) | ||
| 792 | + /* Do not store or send to proxy filter. */ | ||
| 793 | + continue; | ||
| 794 | + if (proxy == 0 ? (++start, --len) == 0 : len == 1) | ||
| 795 | + break; | ||
| 796 | + } | ||
| 797 | if (state->err == CLEANUP_STAT_OK) { | ||
| 798 | if (ENFORCING_SIZE_LIMIT(var_message_limit) | ||
| 799 | && var_message_limit - state->act_size < len + 2) { | ||
| 800 | @@ -3701,6 +3750,11 @@ | ||
| 801 | else | ||
| 802 | smtpd_chat_reply(state, | ||
| 803 | "250 2.0.0 Ok: queued as %s", state->queue_id); | ||
| 804 | + } else if ((state->err & CLEANUP_STAT_BARE_LF) != 0) { | ||
| 805 | + state->error_mask |= MAIL_ERROR_PROTOCOL; | ||
| 806 | + log_whatsup(state, "reject", "bare <LF> received"); | ||
| 807 | + smtpd_chat_reply(state, "%d 5.5.2 %s Error: bare <LF> received", | ||
| 808 | + var_smtpd_forbid_bare_lf_code, var_myhostname); | ||
| 809 | } else if (why && IS_SMTP_REJECT(STR(why))) { | ||
| 810 | state->error_mask |= MAIL_ERROR_POLICY; | ||
| 811 | smtpd_chat_reply(state, "%s", STR(why)); | ||
| 812 | @@ -3981,7 +4035,6 @@ | ||
| 813 | */ | ||
| 814 | done = 0; | ||
| 815 | do { | ||
| 816 | - int payload_err; | ||
| 817 | |||
| 818 | /* | ||
| 819 | * Do not skip the smtp_fread_buf() call if read_len == 0. We still | ||
| 820 | @@ -3995,10 +4048,6 @@ | ||
| 821 | smtp_fread_buf(state->buffer, read_len, state->client); | ||
| 822 | state->bdat_get_stream = vstream_memreopen( | ||
| 823 | state->bdat_get_stream, state->buffer, O_RDONLY); | ||
| 824 | - vstream_control(state->bdat_get_stream, CA_VSTREAM_CTL_EXCEPT, | ||
| 825 | - CA_VSTREAM_CTL_END); | ||
| 826 | - if ((payload_err = vstream_setjmp(state->bdat_get_stream)) != 0) | ||
| 827 | - vstream_longjmp(state->client, payload_err); | ||
| 828 | |||
| 829 | /* | ||
| 830 | * Read lines from the fragment. The last line may continue in the | ||
| 831 | @@ -4023,6 +4072,8 @@ | ||
| 832 | /* Skip the out_record() and VSTRING_RESET() calls below. */ | ||
| 833 | break; | ||
| 834 | } | ||
| 835 | + if (IS_BARE_LF_REPLY_REJECT(smtp_got_bare_lf)) | ||
| 836 | + state->err |= CLEANUP_STAT_BARE_LF; | ||
| 837 | start = vstring_str(state->bdat_get_buffer); | ||
| 838 | len = VSTRING_LEN(state->bdat_get_buffer); | ||
| 839 | if (state->err == CLEANUP_STAT_OK) { | ||
| 840 | @@ -4674,9 +4725,9 @@ | ||
| 841 | */ | ||
| 842 | xclient_allowed = | ||
| 843 | namadr_list_match(xclient_hosts, state->name, state->addr); | ||
| 844 | - smtp_forbid_bare_lf = SMTPD_STAND_ALONE((state)) == 0 | ||
| 845 | - && var_smtpd_forbid_bare_lf | ||
| 846 | - && !namadr_list_match(bare_lf_excl, state->name, state->addr); | ||
| 847 | + smtp_detect_bare_lf = (SMTPD_STAND_ALONE((state)) == 0 && bare_lf_mask | ||
| 848 | + && !namadr_list_match(bare_lf_excl, state->name, state->addr)) ? | ||
| 849 | + bare_lf_mask : 0; | ||
| 850 | /* NOT: tls_reset() */ | ||
| 851 | if (got_helo == 0) | ||
| 852 | helo_reset(state); | ||
| 853 | @@ -5468,13 +5519,6 @@ | ||
| 854 | var_myhostname); | ||
| 855 | break; | ||
| 856 | |||
| 857 | - case SMTP_ERR_LF: | ||
| 858 | - state->reason = REASON_BARE_LF; | ||
| 859 | - if (vstream_setjmp(state->client) == 0) | ||
| 860 | - smtpd_chat_reply(state, "521 5.5.2 %s Error: bare <LF> received", | ||
| 861 | - var_myhostname); | ||
| 862 | - break; | ||
| 863 | - | ||
| 864 | case 0: | ||
| 865 | |||
| 866 | /* | ||
| 867 | @@ -5676,6 +5720,13 @@ | ||
| 868 | } | ||
| 869 | watchdog_pat(); | ||
| 870 | smtpd_chat_query(state); | ||
| 871 | + if (IS_BARE_LF_REPLY_REJECT(smtp_got_bare_lf)) { | ||
| 872 | + log_whatsup(state, "reject", "bare <LF> received"); | ||
| 873 | + state->error_mask |= MAIL_ERROR_PROTOCOL; | ||
| 874 | + smtpd_chat_reply(state, "%d 5.5.2 %s Error: bare <LF> received", | ||
| 875 | + var_smtpd_forbid_bare_lf_code, var_myhostname); | ||
| 876 | + break; | ||
| 877 | + } | ||
| 878 | /* Safety: protect internal interfaces against malformed UTF-8. */ | ||
| 879 | if (var_smtputf8_enable && valid_utf8_string(STR(state->buffer), | ||
| 880 | LEN(state->buffer)) == 0) { | ||
| 881 | @@ -6024,11 +6075,11 @@ | ||
| 882 | namadr_list_match(xforward_hosts, state.name, state.addr); | ||
| 883 | |||
| 884 | /* | ||
| 885 | - * Enforce strict SMTP line endings, with compatibility exclusions. | ||
| 886 | + * Reject or normalize bare LF, with compatibility exclusions. | ||
| 887 | */ | ||
| 888 | - smtp_forbid_bare_lf = SMTPD_STAND_ALONE((&state)) == 0 | ||
| 889 | - && var_smtpd_forbid_bare_lf | ||
| 890 | - && !namadr_list_match(bare_lf_excl, state.name, state.addr); | ||
| 891 | + smtp_detect_bare_lf = (SMTPD_STAND_ALONE((&state)) == 0 && bare_lf_mask | ||
| 892 | + && !namadr_list_match(bare_lf_excl, state.name, state.addr)) ? | ||
| 893 | + bare_lf_mask : 0; | ||
| 894 | |||
| 895 | /* | ||
| 896 | * See if we need to turn on verbose logging for this client. | ||
| 897 | @@ -6095,6 +6146,10 @@ | ||
| 898 | MATCH_FLAG_RETURN | ||
| 899 | | match_parent_style(VAR_MYNETWORKS), | ||
| 900 | var_smtpd_forbid_bare_lf_excl); | ||
| 901 | + if ((bare_lf_mask = name_code(bare_lf_mask_table, NAME_CODE_FLAG_NONE, | ||
| 902 | + var_smtpd_forbid_bare_lf)) < 0) | ||
| 903 | + msg_fatal("bad parameter value: '%s = %s'", | ||
| 904 | + VAR_SMTPD_FORBID_BARE_LF, var_smtpd_forbid_bare_lf); | ||
| 905 | |||
| 906 | /* | ||
| 907 | * Open maps before dropping privileges so we can read passwords etc. | ||
| 908 | @@ -6390,6 +6445,7 @@ | ||
| 909 | VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code, 0, 0, | ||
| 910 | VAR_RELAY_RCPT_CODE, DEF_RELAY_RCPT_CODE, &var_relay_rcpt_code, 0, 0, | ||
| 911 | VAR_PLAINTEXT_CODE, DEF_PLAINTEXT_CODE, &var_plaintext_code, 0, 0, | ||
| 912 | + VAR_SMTPD_FORBID_BARE_LF_CODE, DEF_SMTPD_FORBID_BARE_LF_CODE, &var_smtpd_forbid_bare_lf_code, 500, 599, | ||
| 913 | VAR_SMTPD_CRATE_LIMIT, DEF_SMTPD_CRATE_LIMIT, &var_smtpd_crate_limit, 0, 0, | ||
| 914 | VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0, | ||
| 915 | VAR_SMTPD_CMAIL_LIMIT, DEF_SMTPD_CMAIL_LIMIT, &var_smtpd_cmail_limit, 0, 0, | ||
| 916 | @@ -6452,7 +6508,6 @@ | ||
| 917 | VAR_SMTPD_PEERNAME_LOOKUP, DEF_SMTPD_PEERNAME_LOOKUP, &var_smtpd_peername_lookup, | ||
| 918 | VAR_SMTPD_DELAY_OPEN, DEF_SMTPD_DELAY_OPEN, &var_smtpd_delay_open, | ||
| 919 | VAR_SMTPD_CLIENT_PORT_LOG, DEF_SMTPD_CLIENT_PORT_LOG, &var_smtpd_client_port_log, | ||
| 920 | - VAR_SMTPD_FORBID_BARE_LF, DEF_SMTPD_FORBID_BARE_LF, &var_smtpd_forbid_bare_lf, | ||
| 921 | 0, | ||
| 922 | }; | ||
| 923 | static const CONFIG_NBOOL_TABLE nbool_table[] = { | ||
| 924 | @@ -6569,6 +6624,7 @@ | ||
| 925 | VAR_SMTPD_DNS_RE_FILTER, DEF_SMTPD_DNS_RE_FILTER, &var_smtpd_dns_re_filter, 0, 0, | ||
| 926 | VAR_SMTPD_REJ_FTR_MAPS, DEF_SMTPD_REJ_FTR_MAPS, &var_smtpd_rej_ftr_maps, 0, 0, | ||
| 927 | VAR_SMTPD_FORBID_BARE_LF_EXCL, DEF_SMTPD_FORBID_BARE_LF_EXCL, &var_smtpd_forbid_bare_lf_excl, 0, 0, | ||
| 928 | + VAR_SMTPD_FORBID_BARE_LF, DEF_SMTPD_FORBID_BARE_LF, &var_smtpd_forbid_bare_lf, 1, 0, | ||
| 929 | 0, | ||
| 930 | }; | ||
| 931 | static const CONFIG_RAW_TABLE raw_table[] = { | ||
| 932 | --- a/src/smtpd/smtpd_check.c | ||
| 933 | +++ b/src/smtpd/smtpd_check.c | ||
| 934 | @@ -48,6 +48,11 @@ | ||
| 935 | /* | ||
| 936 | /* char *smtpd_check_queue(state) | ||
| 937 | /* SMTPD_STATE *state; | ||
| 938 | +/* AUXILIARY FUNCTIONS | ||
| 939 | +/* void log_whatsup(state, action, text) | ||
| 940 | +/* SMTPD_STATE *state; | ||
| 941 | +/* const char *action; | ||
| 942 | +/* const char *text; | ||
| 943 | /* DESCRIPTION | ||
| 944 | /* This module implements additional checks on SMTP client requests. | ||
| 945 | /* A client request is validated in the context of the session state. | ||
| 946 | @@ -146,6 +151,11 @@ | ||
| 947 | /* The recipient address given with the RCPT TO or VRFY command. | ||
| 948 | /* .IP size | ||
| 949 | /* The message size given with the MAIL FROM command (zero if unknown). | ||
| 950 | +/* .PP | ||
| 951 | +/* log_whatsup() logs "<queueid>: <action>: <protocol state> | ||
| 952 | +/* from: <client-name[client-addr]>: <text>" plus the protocol | ||
| 953 | +/* (SMTP or ESMTP), and if available, EHLO, MAIL FROM, or RCPT | ||
| 954 | +/* TO. | ||
| 955 | /* BUGS | ||
| 956 | /* Policies like these should not be hard-coded in C, but should | ||
| 957 | /* be user-programmable instead. | ||
| 958 | @@ -987,8 +997,8 @@ | ||
| 959 | |||
| 960 | /* log_whatsup - log as much context as we have */ | ||
| 961 | |||
| 962 | -static void log_whatsup(SMTPD_STATE *state, const char *whatsup, | ||
| 963 | - const char *text) | ||
| 964 | +void log_whatsup(SMTPD_STATE *state, const char *whatsup, | ||
| 965 | + const char *text) | ||
| 966 | { | ||
| 967 | VSTRING *buf = vstring_alloc(100); | ||
| 968 | |||
| 969 | --- a/src/smtpd/smtpd_check.h | ||
| 970 | +++ b/src/smtpd/smtpd_check.h | ||
| 971 | @@ -25,6 +25,7 @@ | ||
| 972 | extern char *smtpd_check_data(SMTPD_STATE *); | ||
| 973 | extern char *smtpd_check_eod(SMTPD_STATE *); | ||
| 974 | extern char *smtpd_check_policy(SMTPD_STATE *, char *); | ||
| 975 | +extern void log_whatsup(SMTPD_STATE *, const char *, const char *); | ||
| 976 | |||
| 977 | /* LICENSE | ||
| 978 | /* .ad | ||
diff --git a/meta-networking/recipes-daemons/postfix/postfix_3.6.7.bb b/meta-networking/recipes-daemons/postfix/postfix_3.6.7.bb index 17864b8915..fdda2e749e 100644 --- a/meta-networking/recipes-daemons/postfix/postfix_3.6.7.bb +++ b/meta-networking/recipes-daemons/postfix/postfix_3.6.7.bb | |||
| @@ -13,6 +13,8 @@ SRC_URI += "ftp://ftp.porcupine.org/mirrors/postfix-release/official/postfix-${P | |||
| 13 | file://0004-Fix-icu-config.patch \ | 13 | file://0004-Fix-icu-config.patch \ |
| 14 | file://0005-makedefs-add-lnsl-and-lresolv-to-SYSLIBS-by-default.patch \ | 14 | file://0005-makedefs-add-lnsl-and-lresolv-to-SYSLIBS-by-default.patch \ |
| 15 | file://0006-makedefs-Account-for-linux-6.x-version.patch \ | 15 | file://0006-makedefs-Account-for-linux-6.x-version.patch \ |
| 16 | file://CVE-2023-51764-1.patch \ | ||
| 17 | file://CVE-2023-51764-2.patch \ | ||
| 16 | " | 18 | " |
| 17 | SRC_URI[sha256sum] = "e471df7e0eb11c4a1e574b6d7298f635386e2843b6b3584c25a04543d587e07f" | 19 | SRC_URI[sha256sum] = "e471df7e0eb11c4a1e574b6d7298f635386e2843b6b3584c25a04543d587e07f" |
| 18 | UPSTREAM_CHECK_REGEX = "postfix\-(?P<pver>3\.6(\.\d+)+).tar.gz" | 20 | UPSTREAM_CHECK_REGEX = "postfix\-(?P<pver>3\.6(\.\d+)+).tar.gz" |
