diff --git a/postfix/HISTORY b/postfix/HISTORY index 8a8d3cf51..c57b542c8 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -28723,19 +28723,60 @@ Apologies for any names omitted. to use SMTPUTF8, and therefore can avoid incompatibility with sites that do not support SMTPUTF8. + The encoded result looks like "=?charset?Q?gibberish?=" for + quoted-printable encoding, or "=?charset?B?gibberish?=" for + base64 encoding. Postfix uses quoted-printable for a full + name that is short or mostly ASCII, and uses base64 otherwise. + The new parameter "full_name_encoding_charset" (default: "utf-8") specifies the character set of the full name in the Postfix sendmail "-F" option, in the Postfix sendmail "NAME" environment variable, or in the GECOS field of the - UNIX password database. - - The encoded result looks like "=?charset?Q?gibberish?= for - quoted-printable encoding, or "=?charset?B?gibberish?= for - base64 encoding. Postfix uses quoted-printable for a full - name that is short or mostly ASCII, and uses base64 otherwise. + UNIX password database. The parameter value is also part + of the encoded full name, and informs a Mail User Agent how + to display the decoded gibberish. Files: mantools/postlink, proto/postconf.proto, cleanup/cleanup.c, cleanup/cleanup_init.c, cleanup/cleanup_message.c, global/ascii_header_text.c, global/ascii_header_text.h, global/mail_params.h, global/rfc2047_code.c, global/rfc2047_code.h, util/clean_ascii_cntrl_space.c, util/clean_ascii_cntrl_space.h. + +20250106 + + Cleanup: the Postfix Milter implementation now logs the + reason for a quarantine request. If a quarantine action is + requested by a Milter application, Postfix will log the + reason given by the application. If the quarantine action + is requested with the "milter_default_action" parameter + setting or with a per-Milter "default_action" property, + Postfix will log "default_action". Files: smtpd/smtp_milter.c, + cleanup/cleanup_milter.c, milter/milter8.c, milter/test-milter.c. + + Cleanup: suppress repeated logging of a Milter "quarantine", + "discard", or "shutdown" request. Files: cleanup/cleanup_milter.c, + smtpd/smtpd.c. + + Documentation: cleanup_replace_stray_cr_lf is disabled + with "receive_override_options = no_header_body_checks". + File: proto/postconf.proto. + +20250107 + + Re-worded the documentation for RFC 2047 full name encoding. + Files: HISTORY, RELEASE_NOTES, proto/postconf.proto. + + Cleanup: eliminated a bogus warning "unexpected SMFIC_UNKNOWN + response" when a Milter default action is "quarantine", the + milter is unavailable, and a remote SMTP client sends a + command that is unknown or known-but-disabled. File: + smtpd/smtpd.c. + + Cleanup: the maximum netstring reply size is now configurable + with the socketmap_max_reply_size configuration parameter. + Code by Christian Roessner. Files: util/dict_sockmap.[hc], + global/mail_params.[hc], proto/postconf.proto, + proto/socketmap_table. + + Cleanup: the netstring client sets or clears errno to improve + error messages from its callers. File: util/netstring.c. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 0a09f458c..9316a4acf 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -26,6 +26,26 @@ now also distributed with the more recent Eclipse Public License license of their choice. Those who are more comfortable with the IPL can continue with that license. +[Incompat 20250106] + +The logging of the Milter 'quarantine' action has changed. Instead +of logging "milter triggers HOLD action", it logs the reason given +by a Milter application, or "default_action" if a Milter application +was unavailable and the milter_default_action parameter or Milter +"default_action" property specifies "quarantine". + +[Feature 20250106] + +The Postfix Milter implementation now logs the reason for a +'quarantine' action, instead of "milter triggers HOLD action". + +- If the quarantine action was requested by a Milter application, + Postfix will log the reason given by the application. + +- If the quarantine action was requested with the "milter_default_action" + parameter setting or with a Milter "default_action" property, + Postfix will log "default_action". + [Feature 20250105] Support for automatic RFC 2047 encoding of non-ASCII "full name" @@ -33,6 +53,11 @@ information in Postfix-generated From: message headers. Encoding non-ASCII full names can avoid the need to use SMTPUTF8, and therefore can avoid incompatibility with sites that do not support SMTPUTF8. +The encoded result looks like "=?charset?Q?gibberish?=: for +quoted-printable encoding, or "=?charset?B?gibberish?=" for base64 +encoding. Postfix uses quoted-printable for a full name that is +short or mostly ASCII, and uses base64 otherwise. + Background: when a message without a From: header is submitted with the Postfix sendmail(1) command, Postfix will add a From: header and will try to use the sender's full name specified with the Postfix sendmail(1) @@ -43,7 +68,8 @@ This introduces a new configuration parameter "full_name_encoding_charset" (default: utf8) which specifies the character set of the full name information in the Postfix sendmail(1) "-F" option or "NAME" environment variable, or in the GECOS field in the UNIX password -database. +database. The parameter value is also part of the encoded full name, +and informs a Mail User Agent how to display the decoded gibberish. [Incompat 20250105] diff --git a/postfix/WISHLIST b/postfix/WISHLIST index ec31c7bea..64e2ad51f 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -2,7 +2,8 @@ Wish list: Things to do before the stable release: - Make the spawn_command fix conditional on compatibility_level. + For the stable releases, make the spawn_command fix conditional + on compatibility_level. make pre-release-check, HTML validator check. @@ -18,7 +19,10 @@ Wish list: relay_recipient_maps empty should default to 'no valid recipients'. Subject to compatibility level. - Make a reason available for messages placed on 'hold'. + The Milter 'quarantine' action should be reported with a + call-back function, instead of setting the Milter default + reply. However, we still need the existing 'reply' based + channel to support "milter_default_action = quarantine". In pipe_command() and spawn_command(), the child process should call initgroups() to corrrectly the access rights diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 679f04df1..b673b46c4 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -1520,6 +1520,9 @@ signature validation by later mail system will not depend on how that mail system handles those stray characters in an implementation-dependent manner.

+

Note: this feature is disabled with "receive_override_options = +no_header_body_checks".

+

This feature is available in Postfix ≥ 3.9, 3.8.5, 3.7.10, 3.6.14, and 3.5.24.

@@ -3963,10 +3966,13 @@ in the UNIX password database. In the latter case, Postfix will replace the "&" character with the login name, with a lowercase ASCII first character converted to uppercase.

-

NOTE: Postfix does not convert between character sets; it simply -encodes the raw bytes in a full name as printable ASCII gibberish. -The full_name_encoding_charset value specifies how a mail reader -program should display the decoded gibberish.

+

NOTE: Postfix does not convert between character sets. The +full_name_encoding_charset parameter specifies the character set +of the full name in the Postfix sendmail "-F" option, in the Postfix +sendmail "NAME" environment variable, or in the GECOS field of the +UNIX password database. The parameter value is also part of the +encoded full name, and informs a Mail User Agent how to display the +decoded gibberish.

Specify a valid character set name such as "utf-8" or "iso-8859-1 (specify the latter for full names that use the Latin1 encoding). @@ -19602,6 +19608,17 @@ built to support these protocols.

This feature is available in Postfix 3.0 and later.

+ + +
socketmap_max_reply_size +(default: 100000)
+ +

The maximum allowed reply size from a socketmap server, not +including the netstring encapsulation.

+ +

This feature is available in Postfix ≥ 3.10.

+ +
soft_bounce diff --git a/postfix/html/socketmap_table.5.html b/postfix/html/socketmap_table.5.html index ef5115d2b..ecc1156e9 100644 --- a/postfix/html/socketmap_table.5.html +++ b/postfix/html/socketmap_table.5.html @@ -45,9 +45,7 @@ SOCKETMAP_TABLE(5) SOCKETMAP_TABLE(5) cidr:, pcre:, and regexp: tables. REPLY FORMAT - The Postfix socketmap client requires that replies are not longer than - 100000 characters (not including the netstring encapsulation). Replies - must have the following form: + Replies must have the following form: OK <space> data The requested data was found. @@ -63,9 +61,25 @@ SOCKETMAP_TABLE(5) SOCKETMAP_TABLE(5) The request failed. The reason, if non-empty, is descriptive text. +PROTOCOL LIMITS + The Postfix socketmap client requires that replies are no longer than + 100000 bytes (not including the netstring encapsulation). This limit + can be changed with the socketmap_max_reply_size configuration parame- + ter (Postfix 3.10 and later). + + The Postfix socketmap client enforces a 100s time limit to connect to a + socketmap server, to send a request, and to receive a reply. It closes + an idle connection after 10s, and closes an active connection after + 100s. These limits are not (yet) configurable. + SECURITY - This map cannot be used for security-sensitive information, - because neither the connection nor the server are authenticated. + This map cannot be used for security-sensitive information, because + neither the connection nor the server are authenticated. + +CONFIGURATION PARAMETERS + socketmap_max_reply_size (100000) + The maximum allowed reply size from a socketmap server, not + including the netstring encapsulation. SEE ALSO https://cr.yp.to/proto/netstrings.txt, netstring definition @@ -79,7 +93,7 @@ SOCKETMAP_TABLE(5) SOCKETMAP_TABLE(5) DATABASE_README, Postfix lookup table overview BUGS - The protocol limits are not yet configurable. + The protocol time limits are not yet configurable. LICENSE The Secure Mailer license must be distributed with this software. @@ -87,6 +101,8 @@ SOCKETMAP_TABLE(5) SOCKETMAP_TABLE(5) HISTORY Socketmap support was introduced with Postfix version 2.10. + The socketmap protocol was published with Sendmail v8.13. + AUTHOR(S) Wietse Venema IBM T.J. Watson Research @@ -98,5 +114,8 @@ SOCKETMAP_TABLE(5) SOCKETMAP_TABLE(5) 111 8th Avenue New York, NY 10011, USA + Wietse Venema + porcupine.org + SOCKETMAP_TABLE(5) diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index b2a4618f6..46d3c24ef 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -893,6 +893,9 @@ signature validation by later mail system will not depend on how that mail system handles those stray characters in an implementation\-dependent manner. .PP +Note: this feature is disabled with "receive_override_options = +no_header_body_checks". +.PP This feature is available in Postfix >= 3.9, 3.8.5, 3.7.10, 3.6.14, and 3.5.24. .SH cleanup_service_name (default: cleanup) @@ -2477,10 +2480,13 @@ in the UNIX password database. In the latter case, Postfix will replace the "&" character with the login name, with a lowercase ASCII first character converted to uppercase. .PP -NOTE: Postfix does not convert between character sets; it simply -encodes the raw bytes in a full name as printable ASCII gibberish. -The full_name_encoding_charset value specifies how a mail reader -program should display the decoded gibberish. +NOTE: Postfix does not convert between character sets. The +full_name_encoding_charset parameter specifies the character set +of the full name in the Postfix sendmail "\-F" option, in the Postfix +sendmail "NAME" environment variable, or in the GECOS field of the +UNIX password database. The parameter value is also part of the +encoded full name, and informs a Mail User Agent how to display the +decoded gibberish. .PP Specify a valid character set name such as "utf\-8" or "iso\-8859\-1 (specify the latter for full names that use the Latin1 encoding). @@ -13621,6 +13627,11 @@ in RFC 6531, RFC 6532, and RFC 6533. This requires that Postfix is built to support these protocols. .PP This feature is available in Postfix 3.0 and later. +.SH socketmap_max_reply_size (default: 100000) +The maximum allowed reply size from a socketmap server, not +including the netstring encapsulation. +.PP +This feature is available in Postfix >= 3.10. .SH soft_bounce (default: no) Safety net to keep mail queued that would otherwise be returned to the sender. This parameter disables locally\-generated bounces, diff --git a/postfix/man/man5/socketmap_table.5 b/postfix/man/man5/socketmap_table.5 index e4ec27e67..693bb60ea 100644 --- a/postfix/man/man5/socketmap_table.5 +++ b/postfix/man/man5/socketmap_table.5 @@ -56,9 +56,7 @@ regexp: tables. .nf .ad .fi -The Postfix socketmap client requires that replies are not -longer than 100000 characters (not including the netstring -encapsulation). Replies must have the following form: +Replies must have the following form: .IP "\fBOK \fIdata\fR" The requested data was found. .IP "\fBNOTFOUND " @@ -68,11 +66,37 @@ The requested data was not found. .IP "\fBPERM \fIreason\fR" The request failed. The reason, if non\-empty, is descriptive text. +.SH "PROTOCOL LIMITS" +.na +.nf +.ad +.fi +The Postfix socketmap client requires that replies are no +longer than 100000 bytes (not including the netstring +encapsulation). This limit can be changed with the +socketmap_max_reply_size configuration parameter (Postfix 3.10 +and later). + +The Postfix socketmap client enforces a 100s time limit to +connect to a socketmap server, to send a request, and to receive +a reply. It closes an idle connection after 10s, and closes +an active connection after 100s. These limits are not (yet) +configurable. .SH "SECURITY" .na .nf +.ad +.fi This map cannot be used for security\-sensitive information, because neither the connection nor the server are authenticated. +.SH "CONFIGURATION PARAMETERS" +.na +.nf +.ad +.fi +.IP "\fBsocketmap_max_reply_size (100000)\fR" +The maximum allowed reply size from a socketmap server, not +including the netstring encapsulation. .SH "SEE ALSO" .na .nf @@ -95,7 +119,7 @@ DATABASE_README, Postfix lookup table overview .SH BUGS .ad .fi -The protocol limits are not yet configurable. +The protocol time limits are not yet configurable. .SH "LICENSE" .na .nf @@ -106,6 +130,8 @@ The Secure Mailer license must be distributed with this software. .ad .fi Socketmap support was introduced with Postfix version 2.10. + +The socketmap protocol was published with Sendmail v8.13. .SH "AUTHOR(S)" .na .nf @@ -118,3 +144,6 @@ Wietse Venema Google, Inc. 111 8th Avenue New York, NY 10011, USA + +Wietse Venema +porcupine.org diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink index b753d0871..5c59da4ee 100755 --- a/postfix/mantools/postlink +++ b/postfix/mantools/postlink @@ -405,6 +405,7 @@ while (<>) { s;\bqmqpd_authorized_clients\b;$&;g; s;\bservice_name\b;$&;g; + s;\bsocket[-]*\n* *[]*map_max_reply_size\b;$&;g; s;\bdefault_desti[-]*\n* *[]*na[-]*\n* *[]*tion_con[-]*\n* *[]*cur[-]*\n* *[]*rency_negative_feedback\b;$&;g; s;\bdefault_desti[-]*\n* *[]*na[-]*\n* *[]*tion_con[-]*\n* *[]*cur[-]*\n* *[]*rency_positive_feedback\b;$&;g; s;\bdefault_desti[-]*\n* *[]*na[-]*\n* *[]*tion_con[-]*\n* *[]*cur[-]*\n* *[]*rency_failed_cohort_limit\b;$&;g; diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index d147b6403..5a06d3fb5 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -19365,6 +19365,9 @@ signature validation by later mail system will not depend on how that mail system handles those stray characters in an implementation-dependent manner.

+

Note: this feature is disabled with "receive_override_options = +no_header_body_checks".

+

This feature is available in Postfix ≥ 3.9, 3.8.5, 3.7.10, 3.6.14, and 3.5.24.

@@ -19448,10 +19451,13 @@ in the UNIX password database. In the latter case, Postfix will replace the "&" character with the login name, with a lowercase ASCII first character converted to uppercase.

-

NOTE: Postfix does not convert between character sets; it simply -encodes the raw bytes in a full name as printable ASCII gibberish. -The full_name_encoding_charset value specifies how a mail reader -program should display the decoded gibberish.

+

NOTE: Postfix does not convert between character sets. The +full_name_encoding_charset parameter specifies the character set +of the full name in the Postfix sendmail "-F" option, in the Postfix +sendmail "NAME" environment variable, or in the GECOS field of the +UNIX password database. The parameter value is also part of the +encoded full name, and informs a Mail User Agent how to display the +decoded gibberish.

Specify a valid character set name such as "utf-8" or "iso-8859-1 (specify the latter for full names that use the Latin1 encoding). @@ -19460,3 +19466,10 @@ name violates RFC 2047 syntax, Postfix will log a warning and will skip the full name.

This feature is available in Postfix ≥ 3.10.

+ +%PARAM socketmap_max_reply_size 100000 + +

The maximum allowed reply size from a socketmap server, not +including the netstring encapsulation.

+ +

This feature is available in Postfix ≥ 3.10.

diff --git a/postfix/proto/socketmap_table b/postfix/proto/socketmap_table index 305afb1ee..47205b735 100644 --- a/postfix/proto/socketmap_table +++ b/postfix/proto/socketmap_table @@ -44,9 +44,7 @@ # REPLY FORMAT # .ad # .fi -# The Postfix socketmap client requires that replies are not -# longer than 100000 characters (not including the netstring -# encapsulation). Replies must have the following form: +# Replies must have the following form: # .IP "\fBOK \fIdata\fR" # The requested data was found. # .IP "\fBNOTFOUND " @@ -56,9 +54,31 @@ # .IP "\fBPERM \fIreason\fR" # The request failed. The reason, if non-empty, is descriptive # text. +# PROTOCOL LIMITS +# .ad +# .fi +# The Postfix socketmap client requires that replies are no +# longer than 100000 bytes (not including the netstring +# encapsulation). This limit can be changed with the +# socketmap_max_reply_size configuration parameter (Postfix 3.10 +# and later). +# +# The Postfix socketmap client enforces a 100s time limit to +# connect to a socketmap server, to send a request, and to receive +# a reply. It closes an idle connection after 10s, and closes +# an active connection after 100s. These limits are not (yet) +# configurable. # SECURITY +# .ad +# .fi # This map cannot be used for security-sensitive information, # because neither the connection nor the server are authenticated. +# CONFIGURATION PARAMETERS +# .ad +# .fi +# .IP "\fBsocketmap_max_reply_size (100000)\fR" +# The maximum allowed reply size from a socketmap server, not +# including the netstring encapsulation. # SEE ALSO # https://cr.yp.to/proto/netstrings.txt, netstring definition # postconf(1), Postfix supported lookup tables @@ -75,13 +95,15 @@ # .nf # DATABASE_README, Postfix lookup table overview # BUGS -# The protocol limits are not yet configurable. +# The protocol time limits are not yet configurable. # LICENSE # .ad # .fi # The Secure Mailer license must be distributed with this software. # HISTORY # Socketmap support was introduced with Postfix version 2.10. +# +# The socketmap protocol was published with Sendmail v8.13. # AUTHOR(S) # Wietse Venema # IBM T.J. Watson Research @@ -92,5 +114,8 @@ # Google, Inc. # 111 8th Avenue # New York, NY 10011, USA +# +# Wietse Venema +# porcupine.org #-- diff --git a/postfix/proto/stop.double-history b/postfix/proto/stop.double-history index ff1c0f338..ebc38fcc2 100644 --- a/postfix/proto/stop.double-history +++ b/postfix/proto/stop.double-history @@ -150,3 +150,5 @@ proto proto socketmap_table qmqpd qmqpd c tls tls_misc c logging to the standard error stream File postlog postlog c Files mantools postlink proto postconf proto cleanup cleanup c many errors I O timeout lost connection File smtpd smtpd c + that is unknown or known but disabled File smtpd smtpd c +proto proto socketmap_table diff --git a/postfix/proto/stop.spell-history b/postfix/proto/stop.spell-history index 9a892a1d5..29ba11fe1 100644 --- a/postfix/proto/stop.spell-history +++ b/postfix/proto/stop.spell-history @@ -96,3 +96,4 @@ v'expr roff diffs CLOSEFROM +Roessner diff --git a/postfix/src/cleanup/cleanup_milter.c b/postfix/src/cleanup/cleanup_milter.c index a35344c93..9fe7aa132 100644 --- a/postfix/src/cleanup/cleanup_milter.c +++ b/postfix/src/cleanup/cleanup_milter.c @@ -2063,19 +2063,22 @@ static const char *cleanup_milter_apply(CLEANUP_STATE *state, const char *event, return (0); switch (resp[0]) { case 'H': - /* XXX Should log the reason here. */ if (state->flags & CLEANUP_FLAG_HOLD) return (0); state->flags |= CLEANUP_FLAG_HOLD; action = "milter-hold"; - text = "milter triggers HOLD action"; + text = resp[1] ? resp + 1 : "milter triggers HOLD action"; break; case 'D': + if (state->flags & CLEANUP_FLAG_DISCARD) + return (0); state->flags |= CLEANUP_FLAG_DISCARD; action = "milter-discard"; text = "milter triggers DISCARD action"; break; case 'S': + if (state->flags & CLEANUP_STAT_CONT) + return (0); /* XXX Can this happen after end-of-message? */ state->flags |= CLEANUP_STAT_CONT; action = "milter-reject"; diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 27e1ab961..47c291ffa 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -1943,6 +1943,7 @@ mail_params.o: ../../include/check_arg.h mail_params.o: ../../include/dict.h mail_params.o: ../../include/dict_db.h mail_params.o: ../../include/dict_lmdb.h +mail_params.o: ../../include/dict_sockmap.h mail_params.o: ../../include/get_hostname.h mail_params.o: ../../include/htable.h mail_params.o: ../../include/inet_addr_list.h diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c index 17fe040f6..5147c0915 100644 --- a/postfix/src/global/mail_params.c +++ b/postfix/src/global/mail_params.c @@ -223,6 +223,7 @@ #include #include #include +#include #include #include #include @@ -352,6 +353,7 @@ int var_strict_encoding; int var_verify_neg_cache; int var_oldlog_compat; int var_delay_max_res; +int var_sockmap_max_reply; char *var_int_filt_classes; int var_cyrus_sasl_authzid; @@ -838,6 +840,7 @@ void mail_params_init() VAR_MIME_BOUND_LEN, DEF_MIME_BOUND_LEN, &var_mime_bound_len, 1, 0, VAR_DELAY_MAX_RES, DEF_DELAY_MAX_RES, &var_delay_max_res, MIN_DELAY_MAX_RES, MAX_DELAY_MAX_RES, VAR_INET_WINDOW, DEF_INET_WINDOW, &var_inet_windowsize, 0, 0, + VAR_SOCKMAP_MAX_REPLY, DEF_SOCKMAP_MAX_REPLY, &var_sockmap_max_reply, 1, 0, 0, }; static const CONFIG_LONG_TABLE long_defaults[] = { @@ -986,6 +989,7 @@ void mail_params_init() check_overlap(); dict_db_cache_size = var_db_read_buf; dict_lmdb_map_size = var_lmdb_map_size; + dict_sockmap_max_reply = var_sockmap_max_reply; inet_windowsize = var_inet_windowsize; if (set_logwriter_create_perms(var_maillog_file_perms) < 0) msg_warn("ignoring bad permissions: %s = %s", diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 316688903..253929319 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -4488,6 +4488,13 @@ extern int var_smtp_tlsrpt_skip_reused_hs; #define DEF_FULL_NAME_ENCODING_CHARSET "utf-8" extern char *var_full_name_encoding_charset; + /* + * Limit for the sockmap reply size + */ +#define VAR_SOCKMAP_MAX_REPLY "socketmap_max_reply_size" +#define DEF_SOCKMAP_MAX_REPLY 100000 /* reply size limit */ +extern int var_sockmap_max_reply; + /* LICENSE /* .ad /* .fi diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index b028754b0..dbd0f0afd 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -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 "20250105" +#define MAIL_RELEASE_DATE "20250107" #define MAIL_VERSION_NUMBER "3.10" #ifdef SNAPSHOT diff --git a/postfix/src/milter/milter8.c b/postfix/src/milter/milter8.c index c6f9bdf88..a280134d9 100644 --- a/postfix/src/milter/milter8.c +++ b/postfix/src/milter/milter8.c @@ -524,7 +524,7 @@ static int milter8_conf_error(MILTER8 *milter) if (strcasecmp(milter->def_action, "accept") == 0) { reply = 0; } else if (strcasecmp(milter->def_action, "quarantine") == 0) { - reply = "H"; + reply = "Hdefault_action"; } else { reply = "451 4.3.5 Server configuration problem - try again later"; } @@ -558,7 +558,7 @@ static int milter8_comm_error(MILTER8 *milter) } else if (strcasecmp(milter->def_action, "tempfail") == 0) { reply = "451 4.7.1 Service unavailable - try again later"; } else if (strcasecmp(milter->def_action, "quarantine") == 0) { - reply = "H"; + reply = "Hdefault_action"; } else { msg_warn("milter %s: unrecognized default action: %s", milter->m.name, milter->def_action); @@ -1332,14 +1332,24 @@ static const char *milter8_event(MILTER8 *milter, int event, * accept, discard). We should not transition, either, otherwise * we get out of sync. */ - case SMFIR_QUARANTINE: - /* XXX What to do with the "reason" text? */ - if (milter8_read_data(milter, &data_size, - MILTER8_DATA_BUFFER, milter->buf, - MILTER8_DATA_END) != 0) - MILTER8_EVENT_BREAK(milter->def_reply); - milter8_def_reply(milter, "H"); - continue; + case SMFIR_QUARANTINE:{ + VSTRING *reply; + ssize_t saved_size = data_size; + + if (milter8_read_data(milter, &data_size, + MILTER8_DATA_BUFFER, milter->buf, + MILTER8_DATA_END) != 0) + MILTER8_EVENT_BREAK(milter->def_reply); + /* XXX This should be reported with a call-back. */ + reply = vstring_alloc(100); + if (saved_size > 100) + saved_size=100; + vstring_sprintf(reply, "H%.*s", (int) saved_size, + STR(milter->buf)); + milter8_def_reply(milter, STR(reply)); + vstring_free(reply); + continue; + } /* * Decision: skip further events of this type. diff --git a/postfix/src/milter/test-milter.c b/postfix/src/milter/test-milter.c index e0fb94503..90c644387 100644 --- a/postfix/src/milter/test-milter.c +++ b/postfix/src/milter/test-milter.c @@ -16,7 +16,7 @@ /* to maintain compatibility between successive versions. /* /* Arguments (multiple alternatives are separated by "\fB|\fR"): -/* .IP "\fB-a accept|tempfail|reject|discard|skip|\fIddd x.y.z text\fR" +/* .IP "\fB-a accept|tempfail|reject|discard|skip|quarantine \fItext\fR|\fIddd x.y.z text\fR" /* Specifies a non-default reply for the MTA command specified /* with \fB-c\fR. The default is \fBtempfail\fR. The \fItext\fR /* is repeated once, to produce multi-line reply text. @@ -139,6 +139,8 @@ static const struct command_map command_map[] = { 0, 0, }; +static char *quarantine_reason; + static char *reply_code; static char *reply_dsn; static char *reply_message; @@ -385,6 +387,11 @@ static sfsistat test_eom(SMFICTX *ctx) if (smfi_delrcpt(ctx, del_rcpt[count]) == MI_FAILURE) fprintf(stderr, "smfi_delrcpt `%s' failed\n", del_rcpt[count]); } + if (quarantine_reason) { + if (smfi_quarantine(ctx, quarantine_reason) == MI_FAILURE) + fprintf(stderr, "smfi_quarantine failed\n"); + printf("quarantine '%s'\n", quarantine_reason); + } return (test_reply(ctx, test_eom_reply)); } @@ -445,7 +452,7 @@ static struct smfiDesc smfilter = { "test-milter", SMFI_VERSION, - SMFIF_ADDRCPT | SMFIF_DELRCPT | SMFIF_ADDHDRS | SMFIF_CHGHDRS | SMFIF_CHGBODY | SMFIF_CHGFROM, + SMFIF_ADDRCPT | SMFIF_DELRCPT | SMFIF_ADDHDRS | SMFIF_CHGHDRS | SMFIF_CHGBODY | SMFIF_CHGFROM | SMFIF_QUARANTINE, test_connect, test_helo, test_mail, @@ -570,7 +577,10 @@ int main(int argc, char **argv) while ((ch = getopt(argc, argv, "a:A:b:c:C:d:D:f:h:i:lm:M:n:N:p:rv")) > 0) { switch (ch) { case 'a': - action = optarg; + if (action != 0) + fprintf(stderr, "ignoring extra -a option\n"); + else + action = optarg; break; case 'A': if (add_rcpt_count >= MAX_RCPT) { @@ -758,6 +768,13 @@ int main(int argc, char **argv) cp->reply[0] = SMFIS_ACCEPT; } else if (strcmp(action, "discard") == 0) { cp->reply[0] = SMFIS_DISCARD; + } else if (strncmp(action, "quarantine ", 11) == 0) { + if (strcmp(command, "eom") != 0) { + fprintf(stderr, "quarantine action requires '-c eom'\n"); + exit(1); + } + quarantine_reason = action + 11; + quarantine_reason += strspn(quarantine_reason, " "); #ifdef SMFIS_SKIP } else if (strcmp(action, "skip") == 0) { cp->reply[0] = SMFIS_SKIP; @@ -793,6 +810,8 @@ int main(int argc, char **argv) printf("reply code %s dsn %s message %s\n", reply_code, reply_dsn ? reply_dsn : "(null)", reply_message ? reply_message : "(null)"); + if (quarantine_reason) + printf("quarantine reason %s\n", quarantine_reason); } } #if SMFI_VERSION > 5 diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 42a82893f..968bac458 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -1787,12 +1787,16 @@ static const char *check_milter_reply(SMTPD_STATE *state, const char *reply) switch (reply[0]) { case 'H': + if (state->saved_flags & CLEANUP_FLAG_HOLD) + return (0); state->saved_flags |= CLEANUP_FLAG_HOLD; action = "milter-hold"; + text = reply[1] ? reply + 1 : "milter triggers HOLD action"; reply = 0; - text = "milter triggers HOLD action"; break; case 'D': + if (state->saved_flags & CLEANUP_FLAG_DISCARD) + return (0); state->saved_flags |= CLEANUP_FLAG_DISCARD; action = "milter-discard"; reply = 0; @@ -5524,6 +5528,9 @@ static int milter_unknown_reply_override(SMTPD_STATE *state) * * As a compromise, we will not override the Postfix SMTP server's specific * "5XX Unknown command" etc. reply. + * + * We're not calling check_milter_reply() because that has unwanted side + * effects including logging and replying with 421. */ if (state->milters != 0 && (err = milter_unknown_event(state->milters, @@ -5531,7 +5538,7 @@ static int milter_unknown_reply_override(SMTPD_STATE *state) if (err[0] == '4') { smtpd_chat_reply(state, "%s", err); return (1); - } else if (err[0] != '5') { + } else if (strchr("HDS5", err[0]) == 0) { msg_warn("unexpected SMFIC_UNKNOWN response: %s", err); } } diff --git a/postfix/src/util/dict_sockmap.c b/postfix/src/util/dict_sockmap.c index becad1ae8..8c0d4e014 100644 --- a/postfix/src/util/dict_sockmap.c +++ b/postfix/src/util/dict_sockmap.c @@ -119,7 +119,7 @@ typedef struct { * Class variables. */ static int dict_sockmap_timeout = DICT_SOCKMAP_DEF_TIMEOUT; -static int dict_sockmap_max_reply = DICT_SOCKMAP_DEF_MAX_REPLY; +int dict_sockmap_max_reply = DICT_SOCKMAP_DEF_MAX_REPLY; static int dict_sockmap_max_idle = DICT_SOCKMAP_DEF_MAX_IDLE; static int dict_sockmap_max_ttl = DICT_SOCKMAP_DEF_MAX_TTL; diff --git a/postfix/src/util/dict_sockmap.h b/postfix/src/util/dict_sockmap.h index b81212aa4..160dfca10 100644 --- a/postfix/src/util/dict_sockmap.h +++ b/postfix/src/util/dict_sockmap.h @@ -22,6 +22,7 @@ #define DICT_TYPE_SOCKMAP "socketmap" extern DICT *dict_sockmap_open(const char *, int, int); +extern int dict_sockmap_max_reply; /* LICENSE /* .ad diff --git a/postfix/src/util/netstring.c b/postfix/src/util/netstring.c index eccd1ba62..ea68ccd34 100644 --- a/postfix/src/util/netstring.c +++ b/postfix/src/util/netstring.c @@ -156,6 +156,9 @@ /* Google, Inc. /* 111 8th Avenue /* New York, NY 10011, USA +/* +/* Wietse Venema +/* porcupine.org /*--*/ /* System library. */ @@ -163,6 +166,7 @@ #include #include #include +#include /* Utility library. */ @@ -367,12 +371,18 @@ const char *netstring_strerror(int err) case NETSTRING_ERR_EOF: return ("unexpected disconnect"); case NETSTRING_ERR_TIME: + errno = ETIMEDOUT; return ("time limit exceeded"); case NETSTRING_ERR_FORMAT: + errno = 0; return ("input format error"); case NETSTRING_ERR_SIZE: +#ifdef EMSGSIZE + errno = EMSGSIZE; +#endif return ("input exceeds size limit"); default: + errno = 0; return ("unknown netstring error"); } }