]*dom_bytes\b;$&;g;
@@ -954,6 +954,9 @@ while (<>) {
s;\bpostscreen_use_tls\b;$&;g;
s;\bpostscreen_discard_ehlo_keyword_address_maps\b;$&;g;
s;\bpostscreen_discard_ehlo_keywords\b;$&;g;
+ s;\bpostscreen_expansion_filter\b;$&;g;
+ s;\bpostscreen_reject_footer\b;$&;g;
+ s;\bpostscreen_command_filter\b;$&;g;
s;\btlsproxy_watchdog_timeout\b;$&;g;
s;\btlsproxy_enforce_tls\b;$&;g;
diff --git a/postfix/proto/POSTSCREEN_README.html b/postfix/proto/POSTSCREEN_README.html
index e744ef554..5adef7580 100644
--- a/postfix/proto/POSTSCREEN_README.html
+++ b/postfix/proto/POSTSCREEN_README.html
@@ -269,7 +269,8 @@ postscreen_greet_wait time has elapsed, postscreen(8) logs this as:
bytes before its turn to speak. This happened time seconds
after the postscreen_greet_wait timer was started. The text
is what the client sent (truncated to 100 bytes, and with non-printable
-characters replaced with "?").
+characters replaced with C-style escapes such as \r for carriage-return
+and \n for newline).
The postscreen_greet_action parameter specifies the action that
is taken next. See "When tests fail
diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto
index c39a711cc..2885e9807 100644
--- a/postfix/proto/postconf.proto
+++ b/postfix/proto/postconf.proto
@@ -13822,62 +13822,99 @@ for further details.
This feature is available in Postfix 2.8 and later.
-%PARAM smtpd_reject_contact_information
+%PARAM smtpd_reject_footer
- Optional contact information that is appended after each SMTP
-server 4XX or 5XX response.
+ Optional information that is appended after each SMTP server
+4XX or 5XX response.
Example:
/etc/postfix/main.cf:
- smtpd_reject_contact_information = For assistance, call 800-555-0101.
+ smtpd_reject_footer = For assistance, call 800-555-0101.
Please provide the following information in your problem report:
- time ($localtime) and client address ($client_address).
+ time ($localtime), client ($client_address) and server
+ ($server_name).
Server response:
-550-5.5.1 <user@example> Recipient address rejected: User unknown
-550 5.5.1 For assistance, call 800-555-0101. Please provide the
-following information in your problem report: time (Jan 4 15:42:00)
-and client address (192.168.1.248).
+ 550-5.5.1 <user@example> Recipient address rejected: User unknown
+ 550 5.5.1 For assistance, call 800-555-0101. Please provide the
+ following information in your problem report: time (Jan 4 15:42:00),
+ client (192.168.1.248) and server (mail1.example.com).
- Note: this text is meant to make it easier to find the Postfix
-logfile records for a failed SMTP session. The text itself is not
-logged to the Postfix server's maillog file.
+ Note: the above text is meant to make it easier to find the
+Postfix logfile records for a failed SMTP session. The text itself
+is not logged to the Postfix SMTP server's maillog file.
Be sure to keep the text as short as possible. Long text may
-be truncated before it is logged in the senders maillog file, or
-before it is returned to the sender in a delivery status notification.
-
+be truncated before it is logged in the Postfix SMTP server's maillog
+file, or before it is returned to the sender in a delivery status
+notification.
This feature supports a limited number of $name attributes in
-the contact text. These are replaced by their current value for the
+the footer text. These are replaced by their current value for the
SMTP session:
-- client_address
- Client IP address
+- client_address
- The Client IP address that
+is logged in the maillog file.
-- client_port
- Client TCP port
+- client_port
- The client TCP port that is
+logged in the maillog file.
-- localtime
- Server local time (Mmm dd hh:mm:ss)
+- localtime
- The server local time (Mmm dd
+hh:mm:ss) that is logged in the maillog file.
-- recipient
- The address in the RCPT TO command
-
-- sender
- The address in the MAIL FROM command
+- server_name
- The server's myhostname value.
+This attribute is made available for sites with multiple MTAs
+(perhaps behind a load-balancer), where the server name can help
+the server support team to quickly find the right log files.
- For safety reasons, text that does not match $smtpd_expansion_filter
-is censored.
+ Notes:
- This feature supports \n as a request for a line break in the
-contact text. Postfix automatically inserts after each line break
-the three-digit SMTP reply code (and optional enhanced status code)
-from the original Postfix reject message.
+
+
+-
NOT SUPPORTED are other attributes such as sender, recipient,
+or main.cf parameters.
+
+ -
For safety reasons, text that does not match
+$smtpd_expansion_filter is censored.
+
+
+
+ This feature supports the two-character sequence \n as a request
+for a line break in the footer text. Postfix automatically inserts
+after each line break the three-digit SMTP reply code (and optional
+enhanced status code) from the original Postfix reject message.
+
+
+ This feature is available in Postfix 2.8 and later.
+
+%PARAM postscreen_expansion_filter see "postconf -d" output
+
+ List of characters that are permitted in postscreen_reject_footer
+attribute expansions. See smtpd_expansion_filter for further
+details.
+
+ This feature is available in Postfix 2.8 and later.
+
+%PARAM postscreen_reject_footer $smtpd_reject_footer
+
+ Optional information that is appended after a 4XX or 5XX server
+response. See smtpd_reject_footer for further details.
+
+ This feature is available in Postfix 2.8 and later.
+
+%PARAM postscreen_command_filter $smtpd_command_filter
+
+ A mechanism to transform commands from remote SMTP clients.
+See smtpd_command_filter for further details.
This feature is available in Postfix 2.8 and later.
diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in
index 47ab4d16a..4ee8d8677 100644
--- a/postfix/src/global/Makefile.in
+++ b/postfix/src/global/Makefile.in
@@ -29,7 +29,8 @@ SRCS = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \
user_acl.c valid_mailhost_addr.c verify.c verify_clnt.c \
verp_sender.c wildcard_inet_addr.c xtext.c delivered_hdr.c \
fold_addr.c header_body_checks.c mkmap_proxy.c data_redirect.c \
- match_service.c mail_conf_nint.c addr_match_list.c mail_conf_nbool.c
+ match_service.c mail_conf_nint.c addr_match_list.c mail_conf_nbool.c \
+ smtp_reply_footer.c
OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \
@@ -60,7 +61,8 @@ OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
user_acl.o valid_mailhost_addr.o verify.o verify_clnt.o \
verp_sender.o wildcard_inet_addr.o xtext.o delivered_hdr.o \
fold_addr.o header_body_checks.o mkmap_proxy.o data_redirect.o \
- match_service.o mail_conf_nint.o addr_match_list.o mail_conf_nbool.o
+ match_service.o mail_conf_nint.o addr_match_list.o mail_conf_nbool.o \
+ smtp_reply_footer.o
HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \
conv_time.h db_common.h debug_peer.h debug_process.h defer.h \
@@ -85,7 +87,7 @@ HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
trace.h user_acl.h valid_mailhost_addr.h verify.h verify_clnt.h \
verp_sender.h wildcard_inet_addr.h xtext.h delivered_hdr.h \
fold_addr.h header_body_checks.h data_redirect.h match_service.h \
- addr_match_list.h
+ addr_match_list.h smtp_reply_footer.h
TESTSRC = rec2stream.c stream2rec.c recdump.c
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
@@ -795,25 +797,8 @@ delivered_hdr.o: quote_822_local.h
delivered_hdr.o: quote_flags.h
delivered_hdr.o: rec_type.h
delivered_hdr.o: record.h
-dict_ldap.o: ../../include/argv.h
-dict_ldap.o: ../../include/binhash.h
-dict_ldap.o: ../../include/dict.h
-dict_ldap.o: ../../include/match_list.h
-dict_ldap.o: ../../include/match_ops.h
-dict_ldap.o: ../../include/msg.h
-dict_ldap.o: ../../include/mymalloc.h
-dict_ldap.o: ../../include/name_code.h
-dict_ldap.o: ../../include/stringops.h
dict_ldap.o: ../../include/sys_defs.h
-dict_ldap.o: ../../include/vbuf.h
-dict_ldap.o: ../../include/vstream.h
-dict_ldap.o: ../../include/vstring.h
-dict_ldap.o: cfg_parser.h
-dict_ldap.o: db_common.h
dict_ldap.o: dict_ldap.c
-dict_ldap.o: dict_ldap.h
-dict_ldap.o: mail_conf.h
-dict_ldap.o: string_list.h
dict_mysql.o: ../../include/sys_defs.h
dict_mysql.o: dict_mysql.c
dict_pgsql.o: ../../include/sys_defs.h
@@ -1444,15 +1429,7 @@ mime_state.o: mail_params.h
mime_state.o: mime_state.c
mime_state.o: mime_state.h
mime_state.o: rec_type.h
-mkmap_cdb.o: ../../include/argv.h
-mkmap_cdb.o: ../../include/dict.h
-mkmap_cdb.o: ../../include/dict_cdb.h
-mkmap_cdb.o: ../../include/mymalloc.h
mkmap_cdb.o: ../../include/sys_defs.h
-mkmap_cdb.o: ../../include/vbuf.h
-mkmap_cdb.o: ../../include/vstream.h
-mkmap_cdb.o: ../../include/vstring.h
-mkmap_cdb.o: mkmap.h
mkmap_cdb.o: mkmap_cdb.c
mkmap_db.o: ../../include/argv.h
mkmap_db.o: ../../include/dict.h
@@ -1829,6 +1806,15 @@ sent.o: sent.c
sent.o: sent.h
sent.o: trace.h
sent.o: verify.h
+smtp_reply_footer.o: ../../include/mac_expand.h
+smtp_reply_footer.o: ../../include/mac_parse.h
+smtp_reply_footer.o: ../../include/msg.h
+smtp_reply_footer.o: ../../include/sys_defs.h
+smtp_reply_footer.o: ../../include/vbuf.h
+smtp_reply_footer.o: ../../include/vstring.h
+smtp_reply_footer.o: dsn_util.h
+smtp_reply_footer.o: smtp_reply_footer.c
+smtp_reply_footer.o: smtp_reply_footer.h
smtp_stream.o: ../../include/iostuff.h
smtp_stream.o: ../../include/msg.h
smtp_stream.o: ../../include/sys_defs.h
diff --git a/postfix/src/global/mail_conf.c b/postfix/src/global/mail_conf.c
index c5d3d4321..1fc7847fc 100644
--- a/postfix/src/global/mail_conf.c
+++ b/postfix/src/global/mail_conf.c
@@ -22,6 +22,9 @@
/* const char *mail_conf_eval(string)
/* const char *string;
/*
+/* const char *mail_conf_eval_once(string)
+/* const char *string;
+/*
/* const char *mail_conf_lookup_eval(name)
/* const char *name;
/* DESCRIPTION
@@ -51,6 +54,11 @@
/* string argument. The result is volatile and should be copied
/* if it is to be used for any appreciable amount of time.
/*
+/* mail_conf_eval_once() non-recursively expands any $parameters
+/* in the string argument. The result is volatile and should
+/* be copied if it is to be used for any appreciable amount
+/* of time.
+/*
/* mail_conf_lookup_eval() looks up the named parameter, and expands any
/* $parameters in the result. The result is volatile and should be
/* copied if it is to be used for any appreciable amount of time.
@@ -201,6 +209,15 @@ const char *mail_conf_eval(const char *string)
return (dict_eval(CONFIG_DICT, string, RECURSIVE));
}
+/* mail_conf_eval_once - expand one level of macros in string */
+
+const char *mail_conf_eval_once(const char *string)
+{
+#define NONRECURSIVE 0
+
+ return (dict_eval(CONFIG_DICT, string, NONRECURSIVE));
+}
+
/* mail_conf_lookup - lookup named variable */
const char *mail_conf_lookup(const char *name)
diff --git a/postfix/src/global/mail_conf.h b/postfix/src/global/mail_conf.h
index 5c0509214..ea6e8bd25 100644
--- a/postfix/src/global/mail_conf.h
+++ b/postfix/src/global/mail_conf.h
@@ -40,6 +40,7 @@ extern void mail_conf_flush(void);
extern void mail_conf_update(const char *, const char *);
extern const char *mail_conf_lookup(const char *);
extern const char *mail_conf_eval(const char *);
+extern const char *mail_conf_eval_once(const char *);
extern const char *mail_conf_lookup_eval(const char *);
/*
diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h
index c5644526b..fa01c5293 100644
--- a/postfix/src/global/mail_params.h
+++ b/postfix/src/global/mail_params.h
@@ -3423,6 +3423,18 @@ extern bool var_psc_disable_vrfy;
#define DEF_PSC_CCONN_LIMIT "$" VAR_SMTPD_CCONN_LIMIT
extern int var_psc_cconn_limit;
+#define VAR_PSC_REJ_FOOTER "postscreen_reject_footer"
+#define DEF_PSC_REJ_FOOTER "$" VAR_SMTPD_REJ_FOOTER
+extern char *var_psc_rej_footer;
+
+#define VAR_PSC_EXP_FILTER "postscreen_expansion_filter"
+#define DEF_PSC_EXP_FILTER "$" VAR_SMTPD_EXP_FILTER
+extern char *var_psc_exp_filter;
+
+#define VAR_PSC_CMD_FILTER "postscreen_command_filter"
+#define DEF_PSC_CMD_FILTER ""
+extern char *var_psc_cmd_filter;
+
#define VAR_DNSBLOG_DELAY "dnsblog_reply_delay"
#define DEF_DNSBLOG_DELAY "0s"
extern int var_dnsblog_delay;
@@ -3557,9 +3569,9 @@ extern bool var_tlsp_tls_set_sessid;
/*
* SMTPD "reject" contact info.
*/
-#define VAR_SMTPD_REJ_CONTACT "smtpd_reject_contact_information"
-#define DEF_SMTPD_REJ_CONTACT ""
-extern char *var_smtpd_rej_contact;
+#define VAR_SMTPD_REJ_FOOTER "smtpd_reject_footer"
+#define DEF_SMTPD_REJ_FOOTER ""
+extern char *var_smtpd_rej_footer;
/* LICENSE
/* .ad
diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h
index 84e825473..d33f0ccb4 100644
--- a/postfix/src/global/mail_proto.h
+++ b/postfix/src/global/mail_proto.h
@@ -254,6 +254,11 @@ extern char *mail_pathname(const char *, const char *);
#define MAIL_ATTR_CIPHER_USEBITS "cipher_usebits"
#define MAIL_ATTR_CIPHER_ALGBITS "cipher_algbits"
+ /*
+ * SMTP reply footer support.
+ */
+#define MAIL_ATTR_SERVER_NAME "server_name"
+
/* LICENSE
/* .ad
/* .fi
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index ffb3e0e7e..e92f57391 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 "20110105"
+#define MAIL_RELEASE_DATE "20110108"
#define MAIL_VERSION_NUMBER "2.8"
#ifdef SNAPSHOT
diff --git a/postfix/src/global/smtp_reply_footer.c b/postfix/src/global/smtp_reply_footer.c
new file mode 100644
index 000000000..5018a4706
--- /dev/null
+++ b/postfix/src/global/smtp_reply_footer.c
@@ -0,0 +1,166 @@
+/*++
+/* NAME
+/* smtp_reply_footer 3
+/* SUMMARY
+/* SMTP reply footer text support
+/* SYNOPSIS
+/* #include
+/*
+/* int smtp_reply_footer(buffer, start, template, filter,
+/* lookup, context)
+/* VSTRING *buffer;
+/* ssize_t start;
+/* char *template;
+/* const char *filter;
+/* const char *(*lookup) (const char *name, char *context);
+/* char *context;
+/* DESCRIPTION
+/* smtp_reply_footer() expands a reply template to an existing
+/* reply text.
+/*
+/* Arguments:
+/* .IP buffer
+/* Result buffer. This should contain a properly formatted
+/* one-line or multi-line SMTP reply, with or without the final
+/* . The reply code and optional enhanced status code
+/* will be replicated in the footer text. One space character
+/* after the SMTP reply code is replaced by '-'. If the existing
+/* reply ends in , the result text will also end in
+/* .
+/* .IP start
+/* The beginning of the SMTP reply that the footer will be
+/* appended to. This supports applications that buffer up
+/* multiple responses in one buffer.
+/* .IP template
+/* Template text, with optional $name attributes that will be
+/* expanded. The two-character sequence "\n" is replaced by a
+/* line break followed by a copy of the original SMTP reply
+/* code and optional enhanced status code.
+/* .IP filter
+/* The set of characters that are allowed in attribute expansion.
+/* .IP lookup
+/* Attribute name/value lookup function. The result value must
+/* be a null for a name that is not found, otherwise a pointer
+/* to null-terminated string.
+/* .IP context
+/* Call-back context for the lookup function.
+/* SEE ALSO
+/* mac_expand(3) macro expansion
+/* DIAGNOSTICS
+/* smtp_reply_footer() returns 0 upon success, -1 if the
+/* existing reply text is malformed.
+/*
+/* Fatal errors: memory allocation problem.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include
+#include
+#include
+
+/* Utility library. */
+
+#include
+#include
+
+/* Global library. */
+
+#include
+#include
+
+/* SLMs. */
+
+#define STR vstring_str
+
+int smtp_reply_footer(VSTRING *buffer, ssize_t start,
+ char *template,
+ const char *filter,
+ MAC_EXP_LOOKUP_FN lookup,
+ char *context)
+{
+ const char *myname = "smtp_reply_footer";
+ char *cp;
+ char *next;
+ char *end;
+ ssize_t dsn_len;
+ int crlf_at_end = 0;
+
+ /*
+ * Sanity check.
+ */
+ if (start < 0 || start > VSTRING_LEN(buffer))
+ msg_panic("%s: bad start: %ld", myname, (long) start);
+ if (*template == 0)
+ msg_panic("%s: empty template", myname);
+
+ /*
+ * Scan and patch the original response. If the response is not what we
+ * expect, we stop making changes.
+ */
+ for (cp = STR(buffer) + start, end = cp + strlen(cp);;) {
+ if (!ISDIGIT(cp[0]) || !ISDIGIT(cp[1]) || !ISDIGIT(cp[2])
+ || (cp[3] != ' ' && cp[3] != '-'))
+ return (-1);
+ cp[3] = '-';
+ if ((next = strstr(cp, "\r\n")) == 0) {
+ next = end;
+ break;
+ }
+ cp = next + 2;
+ if (cp == end) {
+ crlf_at_end = 1;
+ break;
+ }
+ }
+
+ /*
+ * Truncate text after the first null, and truncate the trailing CRLF.
+ */
+ if (next < vstring_end(buffer))
+ vstring_truncate(buffer, next - STR(buffer));
+
+ /*
+ * Append the footer text one line at a time. Caution: before we append
+ * parts from the buffer to itself, we must extend the buffer first,
+ * otherwise we would have a dangling pointer "read" bug.
+ */
+ dsn_len = dsn_valid(STR(buffer) + start + 4);
+ for (cp = template, end = cp + strlen(cp);;) {
+ if ((next = strstr(cp, "\\n")) != 0) {
+ *next = 0;
+ } else {
+ next = end;
+ }
+ /* Append a clone of the SMTP reply code. */
+ vstring_strcat(buffer, "\r\n");
+ VSTRING_SPACE(buffer, 3);
+ vstring_strncat(buffer, STR(buffer) + start, 3);
+ vstring_strcat(buffer, next != end ? "-" : " ");
+ /* Append a clone of the optional enhanced status code. */
+ if (dsn_len > 0) {
+ VSTRING_SPACE(buffer, dsn_len);
+ vstring_strncat(buffer, STR(buffer) + start + 4, (int) dsn_len);
+ vstring_strcat(buffer, " ");
+ }
+ /* Append one line of footer text. */
+ mac_expand(buffer, cp, MAC_EXP_FLAG_APPEND, filter, lookup, context);
+ if (next < end) {
+ *next = '\\';
+ cp = next + 2;
+ } else
+ break;
+ }
+ if (crlf_at_end)
+ vstring_strcat(buffer, "\r\n");
+ return (0);
+}
diff --git a/postfix/src/global/smtp_reply_footer.h b/postfix/src/global/smtp_reply_footer.h
new file mode 100644
index 000000000..6cb65f60e
--- /dev/null
+++ b/postfix/src/global/smtp_reply_footer.h
@@ -0,0 +1,37 @@
+#ifndef _SMTP_REPLY_FOOTER_H_INCLUDED_
+#define _SMTP_REPLY_FOOTER_H_INCLUDED_
+
+/*++
+/* NAME
+/* smtp_reply_footer 3h
+/* SUMMARY
+/* SMTP reply footer text support
+/* SYNOPSIS
+/* #include
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include
+#include
+
+ /*
+ * External interface.
+ */
+extern int smtp_reply_footer(VSTRING *, ssize_t, char *, const char *,
+ MAC_EXP_LOOKUP_FN, char *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
diff --git a/postfix/src/postscreen/Makefile.in b/postfix/src/postscreen/Makefile.in
index 615ebb8f8..013f0f7b4 100644
--- a/postfix/src/postscreen/Makefile.in
+++ b/postfix/src/postscreen/Makefile.in
@@ -2,11 +2,11 @@ SHELL = /bin/sh
SRCS = postscreen.c postscreen_dict.c postscreen_dnsbl.c \
postscreen_early.c postscreen_smtpd.c postscreen_misc.c \
postscreen_state.c postscreen_tests.c postscreen_send.c \
- postscreen_starttls.c
+ postscreen_starttls.c postscreen_expand.c
OBJS = postscreen.o postscreen_dict.o postscreen_dnsbl.o \
postscreen_early.o postscreen_smtpd.o postscreen_misc.o \
postscreen_state.o postscreen_tests.o postscreen_send.o \
- postscreen_starttls.o
+ postscreen_starttls.o postscreen_expand.o
HDRS =
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
@@ -78,6 +78,7 @@ postscreen.o: ../../include/mail_params.h
postscreen.o: ../../include/mail_proto.h
postscreen.o: ../../include/mail_server.h
postscreen.o: ../../include/mail_version.h
+postscreen.o: ../../include/maps.h
postscreen.o: ../../include/match_list.h
postscreen.o: ../../include/match_ops.h
postscreen.o: ../../include/msg.h
@@ -98,6 +99,7 @@ postscreen_dict.o: ../../include/dict.h
postscreen_dict.o: ../../include/dict_cache.h
postscreen_dict.o: ../../include/events.h
postscreen_dict.o: ../../include/htable.h
+postscreen_dict.o: ../../include/maps.h
postscreen_dict.o: ../../include/match_list.h
postscreen_dict.o: ../../include/match_ops.h
postscreen_dict.o: ../../include/msg.h
@@ -120,6 +122,7 @@ postscreen_dnsbl.o: ../../include/iostuff.h
postscreen_dnsbl.o: ../../include/ip_match.h
postscreen_dnsbl.o: ../../include/mail_params.h
postscreen_dnsbl.o: ../../include/mail_proto.h
+postscreen_dnsbl.o: ../../include/maps.h
postscreen_dnsbl.o: ../../include/match_list.h
postscreen_dnsbl.o: ../../include/match_ops.h
postscreen_dnsbl.o: ../../include/msg.h
@@ -141,6 +144,7 @@ postscreen_early.o: ../../include/dict_cache.h
postscreen_early.o: ../../include/events.h
postscreen_early.o: ../../include/htable.h
postscreen_early.o: ../../include/mail_params.h
+postscreen_early.o: ../../include/maps.h
postscreen_early.o: ../../include/match_list.h
postscreen_early.o: ../../include/match_ops.h
postscreen_early.o: ../../include/msg.h
@@ -153,6 +157,28 @@ postscreen_early.o: ../../include/vstream.h
postscreen_early.o: ../../include/vstring.h
postscreen_early.o: postscreen.h
postscreen_early.o: postscreen_early.c
+postscreen_expand.o: ../../include/addr_match_list.h
+postscreen_expand.o: ../../include/argv.h
+postscreen_expand.o: ../../include/attr.h
+postscreen_expand.o: ../../include/dict.h
+postscreen_expand.o: ../../include/dict_cache.h
+postscreen_expand.o: ../../include/events.h
+postscreen_expand.o: ../../include/htable.h
+postscreen_expand.o: ../../include/iostuff.h
+postscreen_expand.o: ../../include/mail_params.h
+postscreen_expand.o: ../../include/mail_proto.h
+postscreen_expand.o: ../../include/maps.h
+postscreen_expand.o: ../../include/match_list.h
+postscreen_expand.o: ../../include/match_ops.h
+postscreen_expand.o: ../../include/msg.h
+postscreen_expand.o: ../../include/string_list.h
+postscreen_expand.o: ../../include/stringops.h
+postscreen_expand.o: ../../include/sys_defs.h
+postscreen_expand.o: ../../include/vbuf.h
+postscreen_expand.o: ../../include/vstream.h
+postscreen_expand.o: ../../include/vstring.h
+postscreen_expand.o: postscreen.h
+postscreen_expand.o: postscreen_expand.c
postscreen_misc.o: ../../include/addr_match_list.h
postscreen_misc.o: ../../include/argv.h
postscreen_misc.o: ../../include/dict.h
@@ -162,6 +188,7 @@ postscreen_misc.o: ../../include/format_tv.h
postscreen_misc.o: ../../include/htable.h
postscreen_misc.o: ../../include/iostuff.h
postscreen_misc.o: ../../include/mail_params.h
+postscreen_misc.o: ../../include/maps.h
postscreen_misc.o: ../../include/match_list.h
postscreen_misc.o: ../../include/match_ops.h
postscreen_misc.o: ../../include/msg.h
@@ -180,10 +207,14 @@ postscreen_send.o: ../../include/dict_cache.h
postscreen_send.o: ../../include/events.h
postscreen_send.o: ../../include/htable.h
postscreen_send.o: ../../include/iostuff.h
+postscreen_send.o: ../../include/mac_expand.h
+postscreen_send.o: ../../include/mac_parse.h
postscreen_send.o: ../../include/mail_params.h
+postscreen_send.o: ../../include/maps.h
postscreen_send.o: ../../include/match_list.h
postscreen_send.o: ../../include/match_ops.h
postscreen_send.o: ../../include/msg.h
+postscreen_send.o: ../../include/smtp_reply_footer.h
postscreen_send.o: ../../include/string_list.h
postscreen_send.o: ../../include/sys_defs.h
postscreen_send.o: ../../include/vbuf.h
@@ -201,6 +232,7 @@ postscreen_smtpd.o: ../../include/events.h
postscreen_smtpd.o: ../../include/htable.h
postscreen_smtpd.o: ../../include/iostuff.h
postscreen_smtpd.o: ../../include/is_header.h
+postscreen_smtpd.o: ../../include/lex_822.h
postscreen_smtpd.o: ../../include/mail_params.h
postscreen_smtpd.o: ../../include/mail_proto.h
postscreen_smtpd.o: ../../include/maps.h
@@ -230,6 +262,7 @@ postscreen_starttls.o: ../../include/htable.h
postscreen_starttls.o: ../../include/iostuff.h
postscreen_starttls.o: ../../include/mail_params.h
postscreen_starttls.o: ../../include/mail_proto.h
+postscreen_starttls.o: ../../include/maps.h
postscreen_starttls.o: ../../include/match_list.h
postscreen_starttls.o: ../../include/match_ops.h
postscreen_starttls.o: ../../include/msg.h
@@ -256,6 +289,7 @@ postscreen_state.o: ../../include/htable.h
postscreen_state.o: ../../include/iostuff.h
postscreen_state.o: ../../include/mail_proto.h
postscreen_state.o: ../../include/mail_server.h
+postscreen_state.o: ../../include/maps.h
postscreen_state.o: ../../include/match_list.h
postscreen_state.o: ../../include/match_ops.h
postscreen_state.o: ../../include/msg.h
@@ -275,6 +309,7 @@ postscreen_tests.o: ../../include/dict_cache.h
postscreen_tests.o: ../../include/events.h
postscreen_tests.o: ../../include/htable.h
postscreen_tests.o: ../../include/mail_params.h
+postscreen_tests.o: ../../include/maps.h
postscreen_tests.o: ../../include/match_list.h
postscreen_tests.o: ../../include/match_ops.h
postscreen_tests.o: ../../include/msg.h
diff --git a/postfix/src/postscreen/postscreen.c b/postfix/src/postscreen/postscreen.c
index 580955461..cc7f3aa41 100644
--- a/postfix/src/postscreen/postscreen.c
+++ b/postfix/src/postscreen/postscreen.c
@@ -101,6 +101,8 @@
/* COMPATIBILITY CONTROLS
/* .ad
/* .fi
+/* .IP "\fBpostscreen_command_filter ($smtpd_command_filter)\fR"
+/* A mechanism to transform commands from remote SMTP clients.
/* .IP "\fBpostscreen_discard_ehlo_keyword_address_maps ($smtpd_discard_ehlo_keyword_address_maps)\fR"
/* Lookup tables, indexed by the remote SMTP client address, with
/* case insensitive lists of EHLO keywords (pipelining, starttls, auth,
@@ -254,6 +256,15 @@
/* .IP "\fBpostscreen_enforce_tls ($smtpd_enforce_tls)\fR"
/* Mandatory TLS: announce STARTTLS support to SMTP clients, and
/* require that clients use TLS encryption.
+/* TROUBLE SHOOTING CONTROLS
+/* .ad
+/* .fi
+/* .IP "\fBpostscreen_expansion_filter (see 'postconf -d' output)\fR"
+/* List of characters that are permitted in postscreen_reject_footer
+/* attribute expansions.
+/* .IP "\fBpostscreen_reject_footer ($smtpd_reject_footer)\fR"
+/* Optional information that is appended after a 4XX or 5XX server
+/* response.
/* MISCELLANEOUS CONTROLS
/* .ad
/* .fi
@@ -265,9 +276,6 @@
/* sub-second delay values.
/* .IP "\fBcommand_directory (see 'postconf -d' output)\fR"
/* The location of all postfix administrative commands.
-/* .IP "\fBipc_timeout (3600s)\fR"
-/* The time limit for sending or receiving information over an internal
-/* communication channel.
/* .IP "\fBmax_idle (100s)\fR"
/* The maximum amount of time that an idle Postfix daemon process waits
/* for an incoming connection before terminating voluntarily.
@@ -353,6 +361,9 @@ char *var_smtpd_banner;
bool var_disable_vrfy_cmd;
bool var_helo_required;
+char *var_smtpd_cmd_filter;
+char *var_psc_cmd_filter;
+
char *var_smtpd_forbid_cmds;
char *var_psc_forbid_cmds;
@@ -410,9 +421,15 @@ int var_psc_barlf_ttl;
int var_psc_cmd_count;
char *var_psc_cmd_time;
+char *var_smtpd_rej_footer;
+char *var_psc_rej_footer;
+
int var_smtpd_cconn_limit;
int var_psc_cconn_limit;
+char *var_smtpd_exp_filter;
+char *var_psc_exp_filter;
+
/*
* Global variables.
*/
@@ -835,6 +852,7 @@ static void post_jail_init(char *unused_name, char **unused_argv)
0, -1,
};
int cache_flags;
+ const char *tmp;
/*
* This routine runs after the skeleton code has entered the chroot jail.
@@ -843,6 +861,24 @@ static void post_jail_init(char *unused_name, char **unused_argv)
*/
var_use_limit = 0;
+ /*
+ * Workaround for parameters whose values may contain "$", and that have
+ * a default of "$parametername". Not sure if it would be a good idea to
+ * always to this in the mail_conf_raw(3) module.
+ */
+ if (*var_psc_rej_footer == '$'
+ && mail_conf_lookup(var_psc_rej_footer + 1)) {
+ tmp = mail_conf_eval_once(var_psc_rej_footer);
+ myfree(var_psc_rej_footer);
+ var_psc_rej_footer = mystrdup(tmp);
+ }
+ if (*var_psc_exp_filter == '$'
+ && mail_conf_lookup(var_psc_exp_filter + 1)) {
+ tmp = mail_conf_eval_once(var_psc_exp_filter);
+ myfree(var_psc_exp_filter);
+ var_psc_exp_filter = mystrdup(tmp);
+ }
+
/*
* Other one-time initialization.
*/
@@ -952,6 +988,7 @@ int main(int argc, char **argv)
VAR_SMTPD_EHLO_DIS_WORDS, DEF_SMTPD_EHLO_DIS_WORDS, &var_smtpd_ehlo_dis_words, 0, 0,
VAR_SMTPD_EHLO_DIS_MAPS, DEF_SMTPD_EHLO_DIS_MAPS, &var_smtpd_ehlo_dis_maps, 0, 0,
VAR_SMTPD_TLS_LEVEL, DEF_SMTPD_TLS_LEVEL, &var_smtpd_tls_level, 0, 0,
+ VAR_SMTPD_CMD_FILTER, DEF_SMTPD_CMD_FILTER, &var_smtpd_cmd_filter, 0, 0,
VAR_PSC_CACHE_MAP, DEF_PSC_CACHE_MAP, &var_psc_cache_map, 0, 0,
VAR_PSC_PREGR_BANNER, DEF_PSC_PREGR_BANNER, &var_psc_pregr_banner, 0, 0,
VAR_PSC_PREGR_ACTION, DEF_PSC_PREGR_ACTION, &var_psc_pregr_action, 1, 0,
@@ -968,6 +1005,7 @@ int main(int argc, char **argv)
VAR_PSC_EHLO_DIS_MAPS, DEF_PSC_EHLO_DIS_MAPS, &var_psc_ehlo_dis_maps, 0, 0,
VAR_PSC_DNSBL_REPLY, DEF_PSC_DNSBL_REPLY, &var_psc_dnsbl_reply, 0, 0,
VAR_PSC_TLS_LEVEL, DEF_PSC_TLS_LEVEL, &var_psc_tls_level, 0, 0,
+ VAR_PSC_CMD_FILTER, DEF_PSC_CMD_FILTER, &var_psc_cmd_filter, 0, 0,
0,
};
static const CONFIG_INT_TABLE int_table[] = {
@@ -1007,6 +1045,10 @@ int main(int argc, char **argv)
};
static const CONFIG_RAW_TABLE raw_table[] = {
VAR_PSC_CMD_TIME, DEF_PSC_CMD_TIME, &var_psc_cmd_time, 1, 0,
+ VAR_SMTPD_REJ_FOOTER, DEF_SMTPD_REJ_FOOTER, &var_smtpd_rej_footer, 0, 0,
+ VAR_PSC_REJ_FOOTER, DEF_PSC_REJ_FOOTER, &var_psc_rej_footer, 0, 0,
+ VAR_SMTPD_EXP_FILTER, DEF_SMTPD_EXP_FILTER, &var_smtpd_exp_filter, 1, 0,
+ VAR_PSC_EXP_FILTER, DEF_PSC_EXP_FILTER, &var_psc_exp_filter, 1, 0,
0,
};
static const CONFIG_NBOOL_TABLE nbool_table[] = {
diff --git a/postfix/src/postscreen/postscreen.h b/postfix/src/postscreen/postscreen.h
index f5b894e3d..74f35a30d 100644
--- a/postfix/src/postscreen/postscreen.h
+++ b/postfix/src/postscreen/postscreen.h
@@ -26,6 +26,7 @@
*/
#include
#include
+#include
/*
* Preliminary stuff, to be fixed.
@@ -67,6 +68,7 @@ typedef struct {
int read_state; /* command read state machine */
/* smtpd(8) compatibility */
int ehlo_discard_mask; /* EHLO filter */
+ VSTRING *expand_buf; /* macro expansion */
} PSC_STATE;
#define PSC_TIME_STAMP_NEW (0) /* test was never passed */
@@ -384,6 +386,8 @@ extern const char *psc_print_state_flags(int, const char *);
extern int psc_addr_match_list_match(ADDR_MATCH_LIST *, const char *);
extern const char *psc_cache_lookup(DICT_CACHE *, const char *);
extern void psc_cache_update(DICT_CACHE *, const char *, const char *);
+const char *psc_dict_get(DICT *, const char *);
+const char *psc_maps_find(MAPS *, const char *, int);
/*
* postscreen_dnsbl.c
@@ -448,6 +452,13 @@ extern void psc_send_socket(PSC_STATE *);
*/
extern void psc_starttls_open(PSC_STATE *, EVENT_NOTIFY_FN);
+ /*
+ * postscreen_expand.c
+ */
+extern VSTRING *psc_expand_filter;
+extern void psc_expand_init(void);
+extern const char *psc_expand_lookup(const char *, int, char *);
+
/* LICENSE
/* .ad
/* .fi
diff --git a/postfix/src/postscreen/postscreen_dict.c b/postfix/src/postscreen/postscreen_dict.c
index 92c0ba450..1db010251 100644
--- a/postfix/src/postscreen/postscreen_dict.c
+++ b/postfix/src/postscreen/postscreen_dict.c
@@ -18,6 +18,15 @@
/* DICT_CACHE *cache;
/* const char *key;
/* const char *value;
+/*
+/* void psc_dict_get(dict, key)
+/* DICT *dict;
+/* const char *key;
+/*
+/* void psc_maps_find(maps, key, flags)
+/* MAPS *maps;
+/* const char *key;
+/* int flags;
/* DESCRIPTION
/* This module implements wrappers around time-critical table
/* access functions. The functions log a warning when table
@@ -28,6 +37,9 @@
/*
/* psc_cache_lookup() and psc_cache_update() are wrappers around
/* the corresponding dict_cache() methods.
+/*
+/* psc_dict_get() and psc_maps_find() are wrappers around
+/* dict_get() and maps_find(), respectively.
/* LICENSE
/* .ad
/* .fi
@@ -46,6 +58,11 @@
/* Utility library. */
#include
+#include
+
+/* Global library. */
+
+#include
/* Application-specific. */
@@ -105,3 +122,29 @@ void psc_cache_update(DICT_CACHE *cache, const char *key, const char *value)
dict_cache_update(cache, key, value);
PSC_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "update");
}
+
+/* psc_dict_get - time-critical table lookup */
+
+const char *psc_dict_get(DICT *dict, const char *key)
+{
+ const char *myname = "psc_dict_get";
+ const char *result;
+
+ PSC_GET_TIME_BEFORE_LOOKUP;
+ result = dict_get(dict, key);
+ PSC_CHECK_TIME_AFTER_LOOKUP(dict->name, "lookup");
+ return (result);
+}
+
+/* psc_maps_find - time-critical table lookup */
+
+const char *psc_maps_find(MAPS *maps, const char *key, int flags)
+{
+ const char *myname = "psc_maps_find";
+ const char *result;
+
+ PSC_GET_TIME_BEFORE_LOOKUP;
+ result = maps_find(maps, key, flags);
+ PSC_CHECK_TIME_AFTER_LOOKUP(maps->title, "lookup");
+ return (result);
+}
diff --git a/postfix/src/postscreen/postscreen_early.c b/postfix/src/postscreen/postscreen_early.c
index 807a0c9d5..cd77f5afd 100644
--- a/postfix/src/postscreen/postscreen_early.c
+++ b/postfix/src/postscreen/postscreen_early.c
@@ -48,6 +48,7 @@
#include
static char *psc_teaser_greeting;
+static VSTRING *psc_escape_buf;
/* psc_early_event - handle pre-greet, EOF, and DNSBL results. */
@@ -172,9 +173,10 @@ static void psc_early_event(int event, char *context)
return;
}
read_buf[read_count] = 0;
+ escape(psc_escape_buf, read_buf, read_count);
msg_info("PREGREET %d after %s from [%s]:%s: %.100s", read_count,
psc_format_delta_time(psc_temp, state->start_time, &elapsed),
- PSC_CLIENT_ADDR_PORT(state), printable(read_buf, '?'));
+ PSC_CLIENT_ADDR_PORT(state), STR(psc_escape_buf));
PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_PREGR_FAIL);
switch (psc_pregr_action) {
case PSC_ACT_DROP:
@@ -288,5 +290,6 @@ void psc_early_init(void)
if (*var_psc_pregr_banner) {
vstring_sprintf(psc_temp, "220-%s\r\n", var_psc_pregr_banner);
psc_teaser_greeting = mystrdup(STR(psc_temp));
+ psc_escape_buf = vstring_alloc(100);
}
}
diff --git a/postfix/src/postscreen/postscreen_expand.c b/postfix/src/postscreen/postscreen_expand.c
new file mode 100644
index 000000000..24e6728e9
--- /dev/null
+++ b/postfix/src/postscreen/postscreen_expand.c
@@ -0,0 +1,141 @@
+/*++
+/* NAME
+/* postscreen_expand 3
+/* SUMMARY
+/* SMTP server macro expansion
+/* SYNOPSIS
+/* #include
+/*
+/* void psc_expand_init()
+/*
+/* VSTRING *psc_expand_filter;
+/*
+/* const char *psc_expand_lookup(name, unused_mode, context)
+/* const char *name;
+/* int unused_mode;
+/* char *context;
+/* DESCRIPTION
+/* This module expands session-related macros.
+/*
+/* psc_expand_init() performs one-time initialization
+/* of the psc_expand_filter buffer.
+/*
+/* The psc_expand_filter buffer contains the characters
+/* that are allowed in macro expansion, as specified with the
+/* psc_expand_filter configuration parameter.
+/*
+/* psc_expand_lookup() returns the value of the named
+/* macro or a null pointer.
+/*
+/* Arguments:
+/* .IP name
+/* Macro name.
+/* .IP context
+/* Call-back context (a PSC_STATE pointer).
+/* DIAGNOSTICS
+/* Panic: interface violations. Fatal errors: out of memory.
+/* internal protocol errors. postscreen_expand() returns the
+/* binary OR of MAC_PARSE_ERROR (syntax error) and MAC_PARSE_UNDEF
+/* (undefined macro name).
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include
+#include
+
+/* Utility library. */
+
+#include
+#include
+#include
+
+/* Global library. */
+
+#include
+#include
+
+/* Application-specific. */
+
+#include
+
+ /*
+ * Pre-parsed expansion filter.
+ */
+VSTRING *psc_expand_filter;
+
+/* psc_expand_init - initialize once during process lifetime */
+
+void psc_expand_init(void)
+{
+
+ /*
+ * Expand the expansion filter :-)
+ */
+ psc_expand_filter = vstring_alloc(10);
+ unescape(psc_expand_filter, var_psc_exp_filter);
+}
+
+/* psc_expand_lookup - generic SMTP attribute $name expansion */
+
+const char *psc_expand_lookup(const char *name, int unused_mode,
+ char *context)
+{
+ PSC_STATE *state = (PSC_STATE *) context;
+ time_t now;
+ struct tm *lt;
+
+ if (state->expand_buf == 0)
+ state->expand_buf = vstring_alloc(10);
+
+ if (msg_verbose > 1)
+ msg_info("psc_expand_lookup: ${%s}", name);
+
+#define STREQ(x,y) (*(x) == *(y) && strcmp((x), (y)) == 0)
+#define STREQN(x,y,n) (*(x) == *(y) && strncmp((x), (y), (n)) == 0)
+#define CONST_LEN(x) (sizeof(x) - 1)
+
+ /*
+ * Don't query main.cf parameters, as the result of expansion could
+ * reveal system-internal information in server replies.
+ *
+ * XXX: This said, multiple servers may be behind a single client-visible
+ * name or IP address, and each may generate its own logs. Therefore, it
+ * may be useful to expose the replying MTA id (myhostname) in the
+ * contact footer, to identify the right logs. So while we don't expose
+ * the raw configuration dictionary, we do expose "$myhostname" as
+ * expanded in var_myhostname.
+ *
+ * Return NULL only for non-existent names.
+ */
+ if (STREQ(name, MAIL_ATTR_SERVER_NAME)) {
+ return (var_myhostname);
+ } else if (STREQ(name, MAIL_ATTR_ACT_CLIENT_ADDR)) {
+ return (state->smtp_client_addr);
+ } else if (STREQ(name, MAIL_ATTR_ACT_CLIENT_PORT)) {
+ return (state->smtp_client_port);
+ } if (STREQ(name, MAIL_ATTR_LOCALTIME)) {
+ if (time(&now) == (time_t) - 1)
+ msg_fatal("time lookup failed: %m");
+ lt = localtime(&now);
+ VSTRING_RESET(state->expand_buf);
+ do {
+ VSTRING_SPACE(state->expand_buf, 100);
+ } while (strftime(STR(state->expand_buf),
+ vstring_avail(state->expand_buf),
+ "%b %d %H:%M:%S", lt) == 0);
+ return (STR(state->expand_buf));
+ } else {
+ msg_warn("unknown macro name \"%s\" in expansion request", name);
+ return (0);
+ }
+}
diff --git a/postfix/src/postscreen/postscreen_send.c b/postfix/src/postscreen/postscreen_send.c
index d74e60049..808afa69d 100644
--- a/postfix/src/postscreen/postscreen_send.c
+++ b/postfix/src/postscreen/postscreen_send.c
@@ -58,6 +58,7 @@
/* Global library. */
#include
+#include
/* Application-specific. */
@@ -74,7 +75,7 @@
int psc_send_reply(PSC_STATE *state, const char *text)
{
- int start;
+ ssize_t start;
int ret;
if (msg_verbose)
@@ -87,6 +88,10 @@ int psc_send_reply(PSC_STATE *state, const char *text)
*/
start = VSTRING_LEN(state->send_buf);
vstring_strcat(state->send_buf, text);
+ if (*var_psc_rej_footer && (*text == '4' || *text == '5'))
+ smtp_reply_footer(state->send_buf, start, var_psc_rej_footer,
+ STR(psc_expand_filter), psc_expand_lookup,
+ (char *) state);
/*
* XXX For soft_bounce support, it is not sufficient to fix replies here.
diff --git a/postfix/src/postscreen/postscreen_smtpd.c b/postfix/src/postscreen/postscreen_smtpd.c
index 5384eb80e..377347eb8 100644
--- a/postfix/src/postscreen/postscreen_smtpd.c
+++ b/postfix/src/postscreen/postscreen_smtpd.c
@@ -143,6 +143,7 @@
#include
#include
#include
+#include
/* TLS library. */
@@ -205,6 +206,11 @@ static void psc_smtpd_read_event(int, char *);
static MAPS *psc_ehlo_discard_maps;
static int psc_ehlo_discard_mask;
+ /*
+ * Command editing filter.
+ */
+static DICT *psc_cmd_filter;
+
/*
* Encapsulation. We must not forget turn off input/timer events when we
* terminate the SMTP protocol engine.
@@ -319,8 +325,8 @@ static int psc_ehlo_cmd(PSC_STATE *state, char *args)
* smtpd(8) compatibility: dynamic reply filtering.
*/
if (psc_ehlo_discard_maps != 0
- && (ehlo_words = maps_find(psc_ehlo_discard_maps,
- state->smtp_client_addr, 0)) != 0
+ && (ehlo_words = psc_maps_find(psc_ehlo_discard_maps,
+ state->smtp_client_addr, 0)) != 0
&& (discard_mask = ehlo_mask(ehlo_words)) != psc_ehlo_discard_mask) {
if (discard_mask && !(discard_mask & EHLO_MASK_SILENT))
msg_info("[%s]%s: discarding EHLO keywords: %s",
@@ -348,13 +354,14 @@ static void psc_starttls_resume(int unused_event, char *context)
PSC_STATE *state = (PSC_STATE *) context;
/*
- * Reset SMTP server state if STARTTLS was successful. Todo: reset SASL
- * AUTH state. Dovecot responses may change when it knows that a
- * connection is encrypted.
+ * Reset SMTP server state if STARTTLS was successful.
*/
if (state->flags & PSC_STATE_FLAG_USING_TLS) {
PSC_STRING_RESET(state->helo_name);
PSC_STRING_RESET(state->sender);
+#ifdef TODO_SASL_AUTH
+ /* Reset SASL AUTH state. Dovecot responses may change. */
+#endif
}
/*
@@ -791,11 +798,28 @@ static void psc_smtpd_read_event(int event, char *context)
}
/*
- * Terminate the command line, and reset the command buffer write
- * pointer and state machine in preparation for the next command. For
- * this to work as expected, VSTRING_RESET() must be non-destructive.
+ * Terminate the command buffer, and apply the last-resort command
+ * editing workaround.
*/
VSTRING_TERMINATE(state->cmd_buffer);
+ if (psc_cmd_filter != 0) {
+ const char *cp;
+
+ for (cp = STR(state->cmd_buffer); *cp && IS_SPACE_TAB(*cp); cp++)
+ /* void */ ;
+ if ((cp = psc_dict_get(psc_cmd_filter, cp)) != 0) {
+ msg_info("[%s]:%s: replacing command \"%.100s\" with \"%.100s\"",
+ state->smtp_client_addr, state->smtp_client_port,
+ STR(state->cmd_buffer), cp);
+ vstring_strcpy(state->cmd_buffer, cp);
+ }
+ }
+
+ /*
+ * Reset the command buffer write pointer and state machine in
+ * preparation for the next command. For this to work as expected,
+ * VSTRING_RESET() must be non-destructive.
+ */
state->read_state = PSC_SMTPD_CMD_ST_ANY;
VSTRING_RESET(state->cmd_buffer);
@@ -1099,6 +1123,12 @@ void psc_smtpd_init(void)
vstring_sprintf(psc_temp, "421 %s Service unavailable - try again later\r\n",
var_myhostname);
psc_smtpd_421_reply = mystrdup(STR(psc_temp));
+
+ /*
+ * Initialize the reply footer.
+ */
+ if (*var_psc_rej_footer)
+ psc_expand_init();
}
/* psc_smtpd_pre_jail_init - per-process deep protocol test initialization */
@@ -1113,8 +1143,16 @@ void psc_smtpd_pre_jail_init(void)
*
* XXX Bugger. This means we have to restart when the table changes!
*/
- psc_ehlo_discard_maps = maps_create(VAR_PSC_EHLO_DIS_MAPS,
- var_psc_ehlo_dis_maps,
- DICT_FLAG_LOCK);
+ if (*var_psc_ehlo_dis_maps)
+ psc_ehlo_discard_maps = maps_create(VAR_PSC_EHLO_DIS_MAPS,
+ var_psc_ehlo_dis_maps,
+ DICT_FLAG_LOCK);
psc_ehlo_discard_mask = ehlo_mask(var_psc_ehlo_dis_words);
+
+ /*
+ * Last-resort command editing support.
+ */
+ if (*var_psc_cmd_filter)
+ psc_cmd_filter = dict_open(var_psc_cmd_filter, O_RDONLY,
+ DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX);
}
diff --git a/postfix/src/postscreen/postscreen_state.c b/postfix/src/postscreen/postscreen_state.c
index 97ffae132..bb205d5e1 100644
--- a/postfix/src/postscreen/postscreen_state.c
+++ b/postfix/src/postscreen/postscreen_state.c
@@ -165,6 +165,7 @@ PSC_STATE *psc_new_session_state(VSTREAM *stream,
state->cmd_buffer = 0;
state->read_state = 0;
state->ehlo_discard_mask = 0; /* XXX Should be ~0 */
+ state->expand_buf = 0;
/*
* Update the stress level.
@@ -225,6 +226,8 @@ void psc_free_session_state(PSC_STATE *state)
myfree(state->sender);
if (state->cmd_buffer)
vstring_free(state->cmd_buffer);
+ if (state->expand_buf)
+ vstring_free(state->expand_buf);
myfree((char *) state);
if (psc_check_queue_length < 0 || psc_post_queue_length < 0)
diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c
index c288a210c..6a8750e3a 100644
--- a/postfix/src/smtp/smtp_proto.c
+++ b/postfix/src/smtp/smtp_proto.c
@@ -849,6 +849,10 @@ static int smtp_start_tls(SMTP_STATE *state)
SMTP_RESP_FAKE(&fake, "4.7.5"),
"Server certificate not verified"));
+
+ /* At this point there must not be any pending plaintext. */
+ vstream_fpurge(session->stream, VSTREAM_PURGE_BOTH);
+
/*
* At this point we have to re-negotiate the "EHLO" to reget the
* feature-list.
diff --git a/postfix/src/smtpd/Makefile.in b/postfix/src/smtpd/Makefile.in
index 856e8b8e6..44792befb 100644
--- a/postfix/src/smtpd/Makefile.in
+++ b/postfix/src/smtpd/Makefile.in
@@ -216,7 +216,6 @@ smtpd.o: smtpd_token.h
smtpd_chat.o: ../../include/argv.h
smtpd_chat.o: ../../include/attr.h
smtpd_chat.o: ../../include/cleanup_user.h
-smtpd_chat.o: ../../include/dsn_util.h
smtpd_chat.o: ../../include/int_filt.h
smtpd_chat.o: ../../include/iostuff.h
smtpd_chat.o: ../../include/line_wrap.h
@@ -236,6 +235,7 @@ smtpd_chat.o: ../../include/name_mask.h
smtpd_chat.o: ../../include/post_mail.h
smtpd_chat.o: ../../include/rec_type.h
smtpd_chat.o: ../../include/record.h
+smtpd_chat.o: ../../include/smtp_reply_footer.h
smtpd_chat.o: ../../include/smtp_stream.h
smtpd_chat.o: ../../include/stringops.h
smtpd_chat.o: ../../include/sys_defs.h
diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c
index 0026c2571..0ce3d8580 100644
--- a/postfix/src/smtpd/smtpd.c
+++ b/postfix/src/smtpd/smtpd.c
@@ -489,9 +489,9 @@
/* and body_checks.
/* .IP "\fBnotify_classes (resource, software)\fR"
/* The list of error classes that are reported to the postmaster.
-/* .IP "\fBsmtpd_reject_contact_information (empty)\fR"
-/* Optional contact information that is appended after each SMTP
-/* server 4XX or 5XX response.
+/* .IP "\fBsmtpd_reject_footer (empty)\fR"
+/* Optional information that is appended after each SMTP server
+/* 4XX or 5XX response.
/* .IP "\fBsoft_bounce (no)\fR"
/* Safety net to keep mail queued that would otherwise be returned to
/* the sender.
@@ -1187,7 +1187,7 @@ bool var_smtpd_enforce_tls;
bool var_smtpd_tls_wrappermode;
bool var_smtpd_tls_auth_only;
char *var_smtpd_cmd_filter;
-char *var_smtpd_rej_contact;
+char *var_smtpd_rej_footer;
#ifdef USE_TLS
char *var_smtpd_relay_ccerts;
@@ -3936,10 +3936,51 @@ static void chat_reset(SMTPD_STATE *state, int threshold)
static void smtpd_start_tls(SMTPD_STATE *state)
{
int rate;
+ int cert_present;
+ int requirecert;
+
+#ifdef USE_TLSPROXY
+
+ /*
+ * This is non-production code, for tlsproxy(8) load testing only. It
+ * implements enough to enable some Postfix features that depend on TLS
+ * encryption.
+ *
+ * To insert tlsproxy(8) between this process and the SMTP client, we swap
+ * the file descriptors between the state->tlsproxy and state->client
+ * VSTREAMS, so that we don't lose all the user-configurable
+ * state->client attributes (such as longjump buffers or timeouts).
+ *
+ * As we implement tlsproy support in the Postfix SMTP client we should
+ * develop a usable abstraction that encapsulates this stream plumbing in
+ * a library module.
+ */
+ vstream_control(state->tlsproxy, VSTREAM_CTL_DOUBLE, VSTREAM_CTL_END);
+ vstream_control(state->client, VSTREAM_CTL_SWAP_FD, state->tlsproxy,
+ VSTREAM_CTL_END);
+ (void) vstream_fclose(state->tlsproxy); /* direct-to-client stream! */
+ state->tlsproxy = 0;
+
+ /*
+ * After plumbing the plaintext stream, receive the TLS context object.
+ * For this we must use the same VSTREAM buffer that we also use to
+ * receive subsequent SMTP commands. The attribute protocol is robust
+ * enough that an adversary cannot inject their own bogus TLS context
+ * attributes into the stream.
+ */
+ state->tls_context = tls_proxy_context_receive(state->client);
+
+ /*
+ * XXX Maybe it is better to send this information to tlsproxy(8) when
+ * requesting service, effectively making a remote tls_server_start()
+ * call.
+ */
+ requirecert = (var_smtpd_tls_req_ccert && var_smtpd_enforce_tls);
+
+#else /* USE_TLSPROXY */
TLS_SERVER_START_PROPS props;
static char *cipher_grade;
static VSTRING *cipher_exclusions;
- int cert_present;
/*
* Wrapper mode uses a dedicated port and always requires TLS.
@@ -3976,20 +4017,23 @@ static void smtpd_start_tls(SMTPD_STATE *state)
* Perform the TLS handshake now. Check the client certificate
* requirements later, if necessary.
*/
+ requirecert = (var_smtpd_tls_req_ccert && var_smtpd_enforce_tls);
+
state->tls_context =
TLS_SERVER_START(&props,
ctx = smtpd_tls_ctx,
stream = state->client,
log_level = var_smtpd_tls_loglevel,
timeout = var_smtpd_starttls_tmout,
- requirecert = (var_smtpd_tls_req_ccert
- && var_smtpd_enforce_tls),
+ requirecert = requirecert,
serverid = state->service,
namaddr = state->namaddr,
cipher_grade = cipher_grade,
cipher_exclusions = STR(cipher_exclusions),
fpt_dgst = var_smtpd_tls_fpt_dgst);
+#endif /* USE_TLSPROXY */
+
/*
* For new (i.e. not re-used) TLS sessions, increment the client's new
* TLS session rate counter. We enforce the limit here only for human
@@ -4034,7 +4078,7 @@ static void smtpd_start_tls(SMTPD_STATE *state)
* here. We have a usable TLS session with the client, so no need to
* disable I/O, ... we can even be polite and send "421 ...".
*/
- if (props.requirecert && TLS_CERT_IS_TRUSTED(state->tls_context) == 0) {
+ if (requirecert && TLS_CERT_IS_TRUSTED(state->tls_context) == 0) {
/*
* Fetch and reject the next command (should be EHLO), then
@@ -4083,11 +4127,6 @@ static int starttls_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
const char *err;
int rate;
-#ifdef USE_TLSPROXY
- VSTREAM *proxy_stream;
-
-#endif
-
if (argc != 1) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
smtpd_chat_reply(state, "501 5.5.4 Syntax: STARTTLS");
@@ -4117,14 +4156,32 @@ static int starttls_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
smtpd_chat_reply(state, "502 5.5.1 Error: command not implemented");
return (-1);
}
-#ifndef USE_TLS_PROXY
+#ifdef USE_TLSPROXY
+
+ /*
+ * Note: state->tlsproxy is left open when smtp_flush() calls longjmp(),
+ * so we garbage-collect the VSTREAM in smtpd_state_reset().
+ */
+#define PROXY_OPEN_FLAGS \
+ (TLS_PROXY_FLAG_ROLE_SERVER | TLS_PROXY_FLAG_SEND_CONTEXT)
+
+ state->tlsproxy = tls_proxy_open(PROXY_OPEN_FLAGS, state->client,
+ state->addr, state->port,
+ var_smtpd_tmout);
+ if (state->tlsproxy == 0) {
+ state->error_mask |= MAIL_ERROR_SOFTWARE;
+ /* RFC 4954 Section 6. */
+ smtpd_chat_reply(state, "454 4.7.0 TLS not available due to local problem");
+ return (-1);
+ }
+#else /* USE_TLSPROXY */
if (smtpd_tls_ctx == 0) {
state->error_mask |= MAIL_ERROR_SOFTWARE;
/* RFC 4954 Section 6. */
smtpd_chat_reply(state, "454 4.7.0 TLS not available due to local problem");
return (-1);
}
-#endif
+#endif /* USE_TLSPROXY */
/*
* Enforce TLS handshake rate limit when this client negotiated too many
@@ -4148,13 +4205,17 @@ static int starttls_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
smtpd_chat_reply(state,
"454 4.7.0 Error: too many new TLS sessions from %s",
state->namaddr);
+#ifdef USE_TLSPROXY
+ (void) vstream_fclose(state->tlsproxy);
+ state->tlsproxy = 0;
+#endif
return (-1);
}
-#ifndef USE_TLSPROXY
smtpd_chat_reply(state, "220 2.0.0 Ready to start TLS");
- /* Flush before we switch the stream's read/write routines. */
+ /* Flush before we switch read/write routines or file descriptors. */
smtp_flush(state->client);
- vstream_fpurge(state->client, VSTREAM_PURGE_READ); /* Yay! */
+ /* At this point there must not be any pending plaintext. */
+ vstream_fpurge(state->client, VSTREAM_PURGE_BOTH);
/*
* Reset all inputs to the initial state.
@@ -4172,73 +4233,6 @@ static int starttls_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
*/
smtpd_start_tls(state);
return (0);
-#else /* USE_TLSPROXY */
-
- /*
- * This is non-production code, for tlsproxy(8) load testing only. It
- * implements enough to enable the Postfix features that depend on TLS
- * encryption.
- */
-#define PROXY_OPEN_FLAGS \
- (TLS_PROXY_FLAG_ROLE_SERVER | TLS_PROXY_FLAG_SEND_CONTEXT)
-
- proxy_stream = tls_proxy_open(PROXY_OPEN_FLAGS, state->client, state->addr,
- state->port, var_smtpd_tmout);
- if (proxy_stream == 0) {
- state->error_mask |= MAIL_ERROR_SOFTWARE;
- /* RFC 4954 Section 6. */
- smtpd_chat_reply(state, "454 4.7.0 TLS not available due to local problem");
- return (-1);
- }
- smtpd_chat_reply(state, "220 2.0.0 Ready to start TLS");
- smtp_flush(state->client);
- vstream_fpurge(state->client, VSTREAM_PURGE_READ);
-
- /*
- * Reset all inputs to the initial state.
- *
- * XXX RFC 2487 does not forbid the use of STARTTLS while mail transfer is
- * in progress, so we have to allow it even when it makes no sense.
- */
- helo_reset(state);
- mail_reset(state);
- rcpt_reset(state);
-#ifdef USE_SASL_AUTH
- if (var_smtpd_sasl_enable) {
- if (smtpd_sasl_is_active(state)) {
- smtpd_sasl_auth_reset(state);
- smtpd_sasl_deactivate(state);
- }
- smtpd_sasl_activate(state, VAR_SMTPD_SASL_TLS_OPTS,
- var_smtpd_sasl_tls_opts);
- }
-#endif
-
- /*
- * To insert tlsproxy(8) between this process and the SMTP client, we
- * swap the file descriptors between the proxy_stream and state->client
- * VSTREAMS, so that we don't have to worry about loss of all the
- * user-configurable state->client attributes (such as longjump buffers).
- */
- vstream_control(proxy_stream, VSTREAM_CTL_DOUBLE, VSTREAM_CTL_END);
- vstream_control(state->client, VSTREAM_CTL_SWAP_FD, proxy_stream,
- VSTREAM_CTL_END);
- (void) vstream_fclose(proxy_stream); /* direct-to-client stream! */
-
- /*
- * After plumbing the plaintext stream, receive the TLS context object.
- * For this we must use the same VSTREAM buffer that we also use to
- * receive subsequent SMTP commands.
- *
- * When the TLS handshake fails, the conversation is in an unknown state.
- * There is nothing we can do except to disconnect from the client.
- */
- state->tls_context = tls_proxy_state_receive(state->client);
- if (state->tls_context == 0)
- vstream_longjmp(state->client, SMTP_ERR_EOF);
-
- return (0);
-#endif /* USE_TLSPROXY */
}
/* tls_reset - undo STARTTLS */
@@ -4254,11 +4248,11 @@ static void tls_reset(SMTPD_STATE *state)
if (vstream_feof(state->client) || vstream_ferror(state->client))
failure = 1;
vstream_fflush(state->client); /* NOT: smtp_flush() */
-#ifndef USE_TLSPROXY
+#ifdef USE_TLSPROXY
+ tls_proxy_context_free(state->tls_context);
+#else
tls_server_stop(smtpd_tls_ctx, state->client, var_smtpd_starttls_tmout,
failure, state->tls_context);
-#else
- tls_proxy_state_free(state->tls_context);
#endif
state->tls_context = 0;
}
@@ -4379,7 +4373,17 @@ static void smtpd_proto(SMTPD_STATE *state)
#ifdef USE_TLS
if (SMTPD_STAND_ALONE(state) == 0 && var_smtpd_tls_wrappermode) {
#ifdef USE_TLSPROXY
- msg_fatal("Wrapper-mode is unimplemented.");
+ /* We garbage-collect the VSTREAM in smtpd_state_reset() */
+ state->tlsproxy = tls_proxy_open(PROXY_OPEN_FLAGS, state->client,
+ state->addr, state->port,
+ var_smtpd_tmout);
+ if (state->tlsproxy == 0) {
+ msg_warn("Wrapper-mode request dropped from %s for service %s."
+ " TLS context initialization failed. For details see"
+ " earlier warnings in your logs.",
+ state->namaddr, state->service);
+ break;
+ }
#else /* USE_TLSPROXY */
if (smtpd_tls_ctx == 0) {
msg_warn("Wrapper-mode request dropped from %s for service %s."
@@ -4388,6 +4392,7 @@ static void smtpd_proto(SMTPD_STATE *state)
state->namaddr, state->service);
break;
}
+#endif /* USE_TLSPROXY */
if (var_smtpd_cntls_limit > 0
&& !xclient_allowed
&& anvil_clnt
@@ -4401,7 +4406,6 @@ static void smtpd_proto(SMTPD_STATE *state)
break;
}
smtpd_start_tls(state);
-#endif /* USE_TLSPROXY */
}
#endif
@@ -4517,25 +4521,6 @@ static void smtpd_proto(SMTPD_STATE *state)
smtp_flush(state->client);
#endif
} else {
-#ifdef PREGREET
- if (*var_stress == 0 && strcmp(state->name, "unknown") == 0) {
- smtpd_chat_reply(state, "220-%s", var_smtpd_banner);
- smtp_flush(state->client);
- if (read_wait(vstream_fileno(state->client), 1) == 0) {
- int n = peekfd(vstream_fileno(state->client));
-
- smtpd_chat_query(state);
- msg_info("PREGREET %d from %s: %s",
- n, state->namaddr, vstring_str(state->buffer));
- state->error_mask |= MAIL_ERROR_POLICY;
- smtpd_chat_reply(state,
- "521 %s ESMTP not accepting connections",
- var_myhostname);
- /* Not: state->error_count++; */
- break;
- }
- }
-#endif
smtpd_chat_reply(state, "220 %s", var_smtpd_banner);
}
}
@@ -4587,7 +4572,7 @@ static void smtpd_proto(SMTPD_STATE *state)
for (cp = STR(state->buffer); *cp && IS_SPACE_TAB(*cp); cp++)
/* void */ ;
if ((cp = dict_get(smtpd_cmd_filter, cp)) != 0) {
- msg_info("%s: replacing client command \"%s\" with \"%s\"",
+ msg_info("%s: replacing command \"%.100s\" with \"%.100s\"",
state->namaddr, STR(state->buffer), cp);
vstring_strcpy(state->buffer, cp);
}
@@ -4914,6 +4899,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
if (getuid() == 0 || getuid() == var_owner_uid) {
if (var_smtpd_use_tls) {
#ifdef USE_TLS
+#ifndef USE_TLSPROXY
TLS_SERVER_INIT_PROPS props;
const char *cert_file;
int have_server_cert;
@@ -4980,6 +4966,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
fpt_dgst = var_smtpd_tls_fpt_dgst);
else
msg_warn("No server certs available. TLS won't be enabled");
+#endif /* USE_TLSPROXY */
#else
msg_warn("TLS has been selected, but TLS support is not compiled in");
#endif
@@ -5260,7 +5247,7 @@ int main(int argc, char **argv)
static const CONFIG_RAW_TABLE raw_table[] = {
VAR_SMTPD_EXP_FILTER, DEF_SMTPD_EXP_FILTER, &var_smtpd_exp_filter, 1, 0,
VAR_DEF_RBL_REPLY, DEF_DEF_RBL_REPLY, &var_def_rbl_reply, 1, 0,
- VAR_SMTPD_REJ_CONTACT, DEF_SMTPD_REJ_CONTACT, &var_smtpd_rej_contact, 0, 0,
+ VAR_SMTPD_REJ_FOOTER, DEF_SMTPD_REJ_FOOTER, &var_smtpd_rej_footer, 0, 0,
0,
};
diff --git a/postfix/src/smtpd/smtpd.h b/postfix/src/smtpd/smtpd.h
index 9b98ac7d3..0ffa1ee41 100644
--- a/postfix/src/smtpd/smtpd.h
+++ b/postfix/src/smtpd/smtpd.h
@@ -165,6 +165,9 @@ typedef struct {
* TLS related state.
*/
#ifdef USE_TLS
+#ifdef USE_TLSPROXY
+ VSTREAM *tlsproxy; /* tlsproxy(8) temp. handle */
+#endif
TLS_SESS_STATE *tls_context; /* TLS session state */
#endif
diff --git a/postfix/src/smtpd/smtpd_chat.c b/postfix/src/smtpd/smtpd_chat.c
index 72f17fd43..da6e80ce6 100644
--- a/postfix/src/smtpd/smtpd_chat.c
+++ b/postfix/src/smtpd/smtpd_chat.c
@@ -83,7 +83,7 @@
#include
#include
#include
-#include
+#include
/* Application-specific. */
@@ -147,7 +147,6 @@ void smtpd_chat_reply(SMTPD_STATE *state, const char *format,...)
char *cp;
char *next;
char *end;
- ssize_t dsn_len;
/*
* Slow down clients that make errors. Sleep-on-anything slows down
@@ -156,48 +155,16 @@ void smtpd_chat_reply(SMTPD_STATE *state, const char *format,...)
if (state->error_count >= var_smtpd_soft_erlim)
sleep(delay = var_smtpd_err_sleep);
- /*
- * The caller may send multi-line text, so we can't assume that there is
- * only one SMTP reply code at the beginning of the response.
- */
va_start(ap, format);
vstring_vsprintf(state->buffer, format, ap);
va_end(ap);
- /*
- * Append the optional contact footer. Caution: as we append parts from
- * the buffer to itself, extend the buffer before updating it, or else we
- * have a dangling pointer bug.
- */
- if (*var_smtpd_rej_contact
- && (*(cp = STR(state->buffer)) == '4' || *cp == '5')
- && ISDIGIT(cp[1]) && ISDIGIT(cp[2]) && cp[3] == ' ') {
- dsn_len = dsn_valid(cp + 4);
- for (cp = var_smtpd_rej_contact, end = cp + strlen(cp);;) {
- if ((next = strstr(cp, "\\n")) != 0) {
- *next = 0;
- } else {
- next = end;
- }
- /* Append a clone of the SMTP reply code. */
- VSTRING_SPACE(state->buffer, sizeof("\r\n550 "));
- vstring_sprintf_append(state->buffer, "\r\n%.3s ",
- STR(state->buffer));
- /* Append a clone of the optional enhanced status code. */
- if (dsn_len > 0) {
- VSTRING_SPACE(state->buffer, dsn_len + 1);
- vstring_sprintf_append(state->buffer, "%.*s ",
- (int) dsn_len, STR(state->buffer) + 4);
- }
- /* Append the actual contact information. */
- smtpd_expand(state, state->buffer, cp, MAC_EXP_FLAG_APPEND);
- if (next < end) {
- *next = '\\';
- cp = next + 2;
- } else
- break;
- }
- }
+ if (*var_smtpd_rej_footer
+ && (*(cp = STR(state->buffer)) == '4' || *cp == '5'))
+ smtp_reply_footer(state->buffer, 0, var_smtpd_rej_footer,
+ STR(smtpd_expand_filter), smtpd_expand_lookup,
+ (char *) state);
+
/* All 5xx replies must have a 5.xx.xx detail code. */
for (cp = STR(state->buffer), end = cp + strlen(STR(state->buffer));;) {
if (var_soft_bounce) {
diff --git a/postfix/src/smtpd/smtpd_expand.c b/postfix/src/smtpd/smtpd_expand.c
index 6683f4e0f..06dfa1b04 100644
--- a/postfix/src/smtpd/smtpd_expand.c
+++ b/postfix/src/smtpd/smtpd_expand.c
@@ -191,9 +191,18 @@ const char *smtpd_expand_lookup(const char *name, int unused_mode,
* Don't query main.cf parameters, as the result of expansion could
* reveal system-internal information in server replies.
*
+ * XXX: This said, multiple servers may be behind a single client-visible
+ * name or IP address, and each may generate its own logs. Therefore, it
+ * may be useful to expose the replying MTA id (myhostname) in the
+ * contact footer, to identify the right logs. So while we don't expose
+ * the raw configuration dictionary, we do expose "$myhostname" as
+ * expanded in var_myhostname.
+ *
* Return NULL only for non-existent names.
*/
- if (STREQ(name, MAIL_ATTR_ACT_CLIENT)) {
+ if (STREQ(name, MAIL_ATTR_SERVER_NAME)) {
+ return (var_myhostname);
+ } else if (STREQ(name, MAIL_ATTR_ACT_CLIENT)) {
return (state->namaddr);
} else if (STREQ(name, MAIL_ATTR_ACT_CLIENT_PORT)) {
return (state->port);
diff --git a/postfix/src/smtpd/smtpd_state.c b/postfix/src/smtpd/smtpd_state.c
index 8dc77a0b0..98f2f5b83 100644
--- a/postfix/src/smtpd/smtpd_state.c
+++ b/postfix/src/smtpd/smtpd_state.c
@@ -138,6 +138,9 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream,
state->dsn_buf = vstring_alloc(100);
state->dsn_orcpt_buf = vstring_alloc(100);
#ifdef USE_TLS
+#ifdef USE_TLSPROXY
+ state->tlsproxy = 0;
+#endif
state->tls_context = 0;
#endif
@@ -208,4 +211,8 @@ void smtpd_state_reset(SMTPD_STATE *state)
vstring_free(state->dsn_buf);
if (state->dsn_orcpt_buf)
vstring_free(state->dsn_orcpt_buf);
+#if (defined(USE_TLS) && defined(USE_TLSPROXY))
+ if (state->tlsproxy) /* still open after longjmp */
+ vstream_fclose(state->tlsproxy);
+#endif
}
diff --git a/postfix/src/tls/tls_proxy.h b/postfix/src/tls/tls_proxy.h
index 3cf093a51..fb8092323 100644
--- a/postfix/src/tls/tls_proxy.h
+++ b/postfix/src/tls/tls_proxy.h
@@ -35,10 +35,10 @@
extern VSTREAM *tls_proxy_open(int, VSTREAM *, const char *,
const char *, int);
-extern TLS_SESS_STATE *tls_proxy_state_receive(VSTREAM *);
-extern void tls_proxy_state_free(TLS_SESS_STATE *);
-extern int tls_proxy_print_state(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
-extern int tls_proxy_scan_state(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
+extern TLS_SESS_STATE *tls_proxy_context_receive(VSTREAM *);
+extern void tls_proxy_context_free(TLS_SESS_STATE *);
+extern int tls_proxy_context_print(ATTR_PRINT_MASTER_FN, VSTREAM *, int, void *);
+extern int tls_proxy_context_scan(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
#endif
diff --git a/postfix/src/tls/tls_proxy_clnt.c b/postfix/src/tls/tls_proxy_clnt.c
index 9f723d21a..a6877975d 100644
--- a/postfix/src/tls/tls_proxy_clnt.c
+++ b/postfix/src/tls/tls_proxy_clnt.c
@@ -14,10 +14,10 @@
/* const char *peer_port;
/* int timeout;
/*
-/* TLS_SESS_STATE *tls_proxy_state_receive(proxy_stream)
+/* TLS_SESS_STATE *tls_proxy_context_receive(proxy_stream)
/* VSTREAM *proxy_stream;
/*
-/* void tls_proxy_state_free(tls_context)
+/* void tls_proxy_context_free(tls_context)
/* TLS_SESS_STATE *tls_context;
/* DESCRIPTION
/* tls_proxy_open() prepares for inserting the tlsproxy(8)
@@ -34,17 +34,17 @@
/* buffer, timeout, etc.). Once the file descriptors are
/* swapped, the proxy stream should be closed.
/*
-/* tls_proxy_state_receive() receives the TLS context object
+/* tls_proxy_context_receive() receives the TLS context object
/* for the named proxy stream. This function must be called
/* only if the TLS_PROXY_SEND_CONTEXT flag was specified in
/* the tls_proxy_open() call. Note that this TLS context object
/* is not compatible with tls_session_free(). It must be given
-/* to tls_proxy_state_free() instead.
+/* to tls_proxy_context_free() instead.
/*
/* After this, the proxy_stream is ready for plain-text I/O.
/*
-/* tls_proxy_state_free() destroys a TLS context object that
-/* was received with tls_proxy_state_receive().
+/* tls_proxy_context_free() destroys a TLS context object that
+/* was received with tls_proxy_context_receive().
/*
/* Arguments:
/* .IP flags
@@ -68,7 +68,7 @@
/* .IP proxy_stream
/* Stream from tls_proxy_open().
/* .IP tls_context
-/* TLS session object from tls_proxy_state_receive().
+/* TLS session object from tls_proxy_context_receive().
/* LICENSE
/* .ad
/* .fi
@@ -188,27 +188,27 @@ VSTREAM *tls_proxy_open(int flags, VSTREAM *peer_stream,
return (tlsproxy_stream);
}
-/* tls_proxy_state_receive - receive TLS session object from tlsproxy(8) */
+/* tls_proxy_context_receive - receive TLS session object from tlsproxy(8) */
-TLS_SESS_STATE *tls_proxy_state_receive(VSTREAM *proxy_stream)
+TLS_SESS_STATE *tls_proxy_context_receive(VSTREAM *proxy_stream)
{
TLS_SESS_STATE *tls_context;
tls_context = (TLS_SESS_STATE *) mymalloc(sizeof(*tls_context));
if (attr_scan(proxy_stream, ATTR_FLAG_STRICT,
- ATTR_TYPE_FUNC, tls_proxy_scan_state, (char *) tls_context,
+ ATTR_TYPE_FUNC, tls_proxy_context_scan, (char *) tls_context,
ATTR_TYPE_END) != 1) {
- tls_proxy_state_free(tls_context);
+ tls_proxy_context_free(tls_context);
return (0);
} else {
return (tls_context);
}
}
-/* tls_proxy_state_free - destroy object from tls_proxy_state_receive() */
+/* tls_proxy_context_free - destroy object from tls_proxy_context_receive() */
-void tls_proxy_state_free(TLS_SESS_STATE *tls_context)
+void tls_proxy_context_free(TLS_SESS_STATE *tls_context)
{
if (tls_context->peer_CN)
myfree(tls_context->peer_CN);
diff --git a/postfix/src/tls/tls_proxy_print.c b/postfix/src/tls/tls_proxy_print.c
index da759fdeb..36bfc112f 100644
--- a/postfix/src/tls/tls_proxy_print.c
+++ b/postfix/src/tls/tls_proxy_print.c
@@ -6,18 +6,18 @@
/* SYNOPSIS
/* #include
/*
-/* int tls_proxy_print_state(print_fn, stream, flags, ptr)
+/* int tls_proxy_context_print(print_fn, stream, flags, ptr)
/* ATTR_PRINT_MASTER_FN print_fn;
/* VSTREAM *stream;
/* int flags;
/* void *ptr;
/* DESCRIPTION
-/* tls_proxy_print_state() writes a TLS_SESS_STATE structure
+/* tls_proxy_context_print() writes a TLS_SESS_STATE structure
/* to the named stream using the specified attribute print
/* routine. TLS_SESS_STATE() is meant to be passed as a call-back
/* to attr_print(), thusly:
/*
-/* ... ATTR_TYPE_FUNC, tls_proxy_print_state, (void *) tls_context, ...
+/* ... ATTR_TYPE_FUNC, tls_proxy_context_print, (void *) tls_context, ...
/* DIAGNOSTICS
/* Fatal: out of memory.
/* LICENSE
@@ -50,9 +50,9 @@
#include
#include
-/* tls_proxy_print_state - send TLS session state over stream */
+/* tls_proxy_context_print - send TLS session state over stream */
-int tls_proxy_print_state(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
+int tls_proxy_context_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
int flags, void *ptr)
{
TLS_SESS_STATE *tp = (TLS_SESS_STATE *) ptr;
diff --git a/postfix/src/tls/tls_proxy_scan.c b/postfix/src/tls/tls_proxy_scan.c
index c68472743..fd5621036 100644
--- a/postfix/src/tls/tls_proxy_scan.c
+++ b/postfix/src/tls/tls_proxy_scan.c
@@ -6,18 +6,18 @@
/* SYNOPSIS
/* #include
/*
-/* int tls_proxy_scan_state(scan_fn, stream, flags, ptr)
+/* int tls_proxy_context_scan(scan_fn, stream, flags, ptr)
/* ATTR_SCAN_MASTER_FN scan_fn;
/* VSTREAM *stream;
/* int flags;
/* void *ptr;
/* DESCRIPTION
-/* tls_proxy_scan_state() reads a TLS_SESS_STATE structure
+/* tls_proxy_context_scan() reads a TLS_SESS_STATE structure
/* from the named stream using the specified attribute scan
-/* routine. tls_proxy_scan_state() is meant to be passed as
+/* routine. tls_proxy_context_scan() is meant to be passed as
/* a call-back to attr_scan(), thusly:
/*
-/* ... ATTR_TYPE_FUNC, tls_proxy_scan_state, (void *) tls_context, ...
+/* ... ATTR_TYPE_FUNC, tls_proxy_context_scan, (void *) tls_context, ...
/* DIAGNOSTICS
/* Fatal: out of memory.
/* LICENSE
@@ -50,9 +50,9 @@
#include
#include
-/* tls_proxy_scan_state - receive TLS session state from stream */
+/* tls_proxy_context_scan - receive TLS session state from stream */
-int tls_proxy_scan_state(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
+int tls_proxy_context_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
int flags, void *ptr)
{
TLS_SESS_STATE *tls_context = (TLS_SESS_STATE *) ptr;
diff --git a/postfix/src/tlsproxy/tlsproxy.c b/postfix/src/tlsproxy/tlsproxy.c
index 8786f29bf..aefe43872 100644
--- a/postfix/src/tlsproxy/tlsproxy.c
+++ b/postfix/src/tlsproxy/tlsproxy.c
@@ -469,7 +469,7 @@ static void tlsp_strategy(TLSP_STATE *state)
}
if ((state->req_flags & TLS_PROXY_FLAG_SEND_CONTEXT) != 0
&& (attr_print(state->plaintext_stream, ATTR_FLAG_NONE,
- ATTR_TYPE_FUNC, tls_proxy_print_state,
+ ATTR_TYPE_FUNC, tls_proxy_context_print,
(char *) state->tls_context, ATTR_TYPE_END) != 0
|| vstream_fflush(state->plaintext_stream) != 0)) {
msg_warn("cannot send TLS context: %m");