UNIX, but not for AIX4 and IRIX6. Albert Chin. File:
util/sys_defs.h.
+20050622
+
+ Cleanup: the DNS lookup code now accommodates name server
+ replies longer than 4 kbytes, with a hard upper limit of
+ 32kbytes. For safety reasons, the number of MX host addresses
+ that the SMTP client will try was reduced from unlimited
+ to just 5, so that Postfix won't spend forever trying to
+ connect to dozens and dozens of bogus MX hosts. Files:
+ dns/dns_lookup.c, global/mail_params.h.
+
+ Cleanup: the code that handles a 4xx or 5xx SMTP server
+ greeting was moved from the connection management module
+ to the protocol engine, for cleaner error handling. This
+ means that the failed session now counts towards the limit
+ on the total number of SMTP sessions per domain name (default:
+ smtp_mx_session_limit = 2). Files: smtp/smtp_connect.c,
+ smtp/smtp_proto.c.
+
Open problems:
Laptop friendliness: make the qmgr remember when the next
eliminate the hack that uses one character lookahead to
find out if the server wants to talk to us.
- Low: replace_sender/replace_recipient actions in access maps?
+ Low: replace_sender/replace_recipient actions in access
+ maps?
Feature: need "soft-bounce before fall-back relay" for SOHO
type operations, so they can send direct mail without having
</DD>
<DT><b><a name="smtp_mx_address_limit">smtp_mx_address_limit</a>
-(default: 0)</b></DT><DD>
+(default: 5)</b></DT><DD>
<p>
The maximal number of MX (mail exchanger) IP addresses that can
-result from mail exchanger lookups, or zero (no limit).
+result from mail exchanger lookups, or zero (no limit). Prior to
+Postfix 2.3, this limit was disabled.
</p>
<p>
This feature is available in Postfix 2.3 and later.
- <b>-V</b> (with Postfix 2.3 use <b>-XV</b>)
+ <b>-XV</b> (Postfix 2.2 and earlier: <b>-V</b>)
Variable Envelope Return Path. Given an envelope
sender address of the form <i>owner-listname</i>@<i>origin</i>,
each recipient <i>user</i>@<i>domain</i> receives mail with a
the <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a></b> configuration parame-
ter.
- <b>-V</b><i>xy</i> (with Postfix 2.3 use <b>-XV</b><i>xy</i>)
- As <b>-V</b>, but uses <i>x</i> and <i>y</i> as the VERP delimiter char-
- acters, instead of the characters specified with
- the <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a></b> configuration parame-
- ter.
-
- <b>-XV</b> Variable Envelope Return Path. Given an envelope
- sender address of the form <i>owner-listname</i>@<i>origin</i>,
- each recipient <i>user</i>@<i>domain</i> receives mail with a
- personalized envelope sender address.
-
- By default, the personalized envelope sender
- address is <i>owner-listname</i><b>+</b><i>user</i><b>=</b><i>domain</i>@<i>origin</i>. The
- default <b>+</b> and <b>=</b> characters are configurable with
- the <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a></b> configuration parame-
- ter.
-
- This feature is available in Postfix version 2.3
- and later.
-
- <b>-XV</b><i>xy</i> As <b>-V</b>, but uses <i>x</i> and <i>y</i> as the VERP delimiter char-
- acters, instead of the characters specified with
- the <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a></b> configuration parame-
- ter.
-
- This feature is available in Postfix version 2.3
- and later.
+ <b>-XV</b><i>xy</i> (Postfix 2.2 and earlier: <b>-V</b><i>xy</i>)
+ As <b>-XV</b>, but uses <i>x</i> and <i>y</i> as the VERP delimiter
+ characters, instead of the characters specified
+ with the <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a></b> configuration
+ parameter.
<b>-v</b> Send an email report of the first delivery attempt
(Postfix versions 2.1 and later). Mail delivery
Available in Postfix version 2.1 and later:
- <b><a href="postconf.5.html#smtp_mx_address_limit">smtp_mx_address_limit</a> (0)</b>
+ <b><a href="postconf.5.html#smtp_mx_address_limit">smtp_mx_address_limit</a> (5)</b>
The maximal number of MX (mail exchanger) IP
addresses that can result from mail exchanger
lookups, or zero (no limit).
support DSN.
This feature is available in Postfix 2.3 and later.
-.IP "\fB-V\fR (with Postfix 2.3 use \fB-XV\fR)"
+.IP "\fB-XV\fR (Postfix 2.2 and earlier: \fB-V\fR)"
Variable Envelope Return Path. Given an envelope sender address
of the form \fIowner-listname\fR@\fIorigin\fR, each recipient
\fIuser\fR@\fIdomain\fR receives mail with a personalized envelope
\fIowner-listname\fB+\fIuser\fB=\fIdomain\fR@\fIorigin\fR. The default
\fB+\fR and \fB=\fR characters are configurable with the
\fBdefault_verp_delimiters\fR configuration parameter.
-.IP "\fB-V\fIxy\fR (with Postfix 2.3 use \fB-XV\fIxy\fR)"
-As \fB-V\fR, but uses \fIx\fR and \fIy\fR as the VERP delimiter
+.IP "\fB-XV\fIxy\fR (Postfix 2.2 and earlier: \fB-V\fIxy\fR)"
+As \fB-XV\fR, but uses \fIx\fR and \fIy\fR as the VERP delimiter
characters, instead of the characters specified with the
\fBdefault_verp_delimiters\fR configuration parameter.
-.IP \fB-XV\fR
-Variable Envelope Return Path. Given an envelope sender address
-of the form \fIowner-listname\fR@\fIorigin\fR, each recipient
-\fIuser\fR@\fIdomain\fR receives mail with a personalized envelope
-sender address.
-.sp
-By default, the personalized envelope sender address is
-\fIowner-listname\fB+\fIuser\fB=\fIdomain\fR@\fIorigin\fR. The default
-\fB+\fR and \fB=\fR characters are configurable with the
-\fBdefault_verp_delimiters\fR configuration parameter.
-.sp
-This feature is available in Postfix version 2.3 and later.
-.IP \fB-XV\fIxy\fR
-As \fB-V\fR, but uses \fIx\fR and \fIy\fR as the VERP delimiter
-characters, instead of the characters specified with the
-\fBdefault_verp_delimiters\fR configuration parameter.
-.sp
-This feature is available in Postfix version 2.3 and later.
.IP \fB-v\fR
Send an email report of the first delivery attempt (Postfix
versions 2.1 and later). Mail delivery
.PP
Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
The default time unit is s (seconds).
-.SH smtp_mx_address_limit (default: 0)
+.SH smtp_mx_address_limit (default: 5)
The maximal number of MX (mail exchanger) IP addresses that can
-result from mail exchanger lookups, or zero (no limit).
+result from mail exchanger lookups, or zero (no limit). Prior to
+Postfix 2.3, this limit was disabled.
.PP
This feature is available in Postfix 2.1 and later.
.SH smtp_mx_session_limit (default: 2)
receiving the server response.
.PP
Available in Postfix version 2.1 and later:
-.IP "\fBsmtp_mx_address_limit (0)\fR"
+.IP "\fBsmtp_mx_address_limit (5)\fR"
The maximal number of MX (mail exchanger) IP addresses that can
result from mail exchanger lookups, or zero (no limit).
.IP "\fBsmtp_mx_session_limit (2)\fR"
The default time unit is s (seconds).
</p>
-%PARAM smtp_mx_address_limit 0
+%PARAM smtp_mx_address_limit 5
<p>
The maximal number of MX (mail exchanger) IP addresses that can
-result from mail exchanger lookups, or zero (no limit).
+result from mail exchanger lookups, or zero (no limit). Prior to
+Postfix 2.3, this limit was disabled.
</p>
<p>
* MTA can't use that same information in its own DSNs.
*
* Postfix always reports an Original-Recipient field, because it is more
- * more useful and more inconsistent.
+ * more useful and more consistent.
*/
if (bounce_info->log_handle->rcpt.dsn_orcpt) {
post_mail_fprintf(bounce, "Original-Recipient: %s",
/*
* Structure to keep track of things while decoding a name server reply.
*/
-#define DNS_REPLY_SIZE 4096 /* in case we're using TCP */
+#define DEF_DNS_REPLY_SIZE 4096 /* in case we're using TCP */
+#define MAX_DNS_REPLY_SIZE 32768 /* in case we're using TCP */
typedef struct DNS_REPLY {
- unsigned char buf[DNS_REPLY_SIZE]; /* raw reply data */
+ unsigned char *buf; /* raw reply data */
+ size_t buf_len; /* reply buffer length */
int query_count; /* number of queries */
int answer_count; /* number of answers */
unsigned char *query_start; /* start of query data */
int len;
unsigned long saved_options;
+ /*
+ * Initialize the reply buffer.
+ */
+ if (reply->buf == 0) {
+ reply->buf = mymalloc(DEF_DNS_REPLY_SIZE);
+ reply->buf_len = DEF_DNS_REPLY_SIZE;
+ }
+
/*
* Initialize the name service.
*/
if ((flags & USER_FLAGS) != flags)
msg_panic("dns_query: bad flags: %d", flags);
saved_options = (_res.options & USER_FLAGS);
- _res.options &= ~saved_options;
- _res.options |= flags;
/*
* Perform the lookup. Claim that the information cannot be found if and
* only if the name server told us so.
*/
- len = res_search((char *) name, C_IN, type, reply->buf, sizeof(reply->buf));
- _res.options &= ~flags;
- _res.options |= saved_options;
- if (len < 0) {
- if (why)
- vstring_sprintf(why, "Host or domain name not found. "
- "Name service error for name=%s type=%s: %s",
+ for (;;) {
+ _res.options &= ~saved_options;
+ _res.options |= flags;
+ len = res_search((char *) name, C_IN, type, reply->buf, reply->buf_len);
+ _res.options &= ~flags;
+ _res.options |= saved_options;
+ if (len < 0) {
+ if (why)
+ vstring_sprintf(why, "Host or domain name not found. "
+ "Name service error for name=%s type=%s: %s",
name, dns_strtype(type), dns_strerror(h_errno));
- if (msg_verbose)
- msg_info("dns_query: %s (%s): %s",
- name, dns_strtype(type), dns_strerror(h_errno));
- switch (h_errno) {
- case NO_RECOVERY:
- return (DNS_FAIL);
- case HOST_NOT_FOUND:
- case NO_DATA:
- return (DNS_NOTFOUND);
- default:
- return (DNS_RETRY);
+ if (msg_verbose)
+ msg_info("dns_query: %s (%s): %s",
+ name, dns_strtype(type), dns_strerror(h_errno));
+ switch (h_errno) {
+ case NO_RECOVERY:
+ return (DNS_FAIL);
+ case HOST_NOT_FOUND:
+ case NO_DATA:
+ return (DNS_NOTFOUND);
+ default:
+ return (DNS_RETRY);
+ }
}
+ if (msg_verbose)
+ msg_info("dns_query: %s (%s): OK", name, dns_strtype(type));
+
+ reply_header = (HEADER *) reply->buf;
+ if (reply_header->tc == 0 || reply->buf_len >= MAX_DNS_REPLY_SIZE)
+ break;
+ reply->buf = myrealloc(reply->buf, 2 * reply->buf_len);
+ reply->buf_len *= 2;
}
- if (msg_verbose)
- msg_info("dns_query: %s (%s): OK", name, dns_strtype(type));
/*
* Paranoia.
*/
- if (len > sizeof(reply->buf)) {
+ if (len > reply->buf_len) {
msg_warn("reply length %d > buffer length %d for name=%s type=%s",
- len, (int) sizeof(reply->buf), name, dns_strtype(type));
- len = sizeof(reply->buf);
+ len, (int) reply->buf_len, name, dns_strtype(type));
+ len = reply->buf_len;
}
/*
* Initialize the reply structure. Some structure members are filled on
* the fly while the reply is being parsed.
*/
- if ((reply->end = reply->buf + len) > reply->buf + sizeof(reply->buf))
- reply->end = reply->buf + sizeof(reply->buf);
- reply_header = (HEADER *) reply->buf;
+ reply->end = reply->buf + len;
reply->query_start = reply->buf + sizeof(HEADER);
reply->answer_start = 0;
reply->query_count = ntohs(reply_header->qdcount);
{
char cname[DNS_NAME_LEN];
int c_len = sizeof(cname);
- DNS_REPLY reply;
+ static DNS_REPLY reply;
int count;
int status;
extern int var_smtp_dns_lookup;
#define VAR_SMTP_MXADDR_LIMIT "smtp_mx_address_limit"
-#define DEF_SMTP_MXADDR_LIMIT 0
+#define DEF_SMTP_MXADDR_LIMIT 5
extern int var_smtp_mxaddr_limit;
#define VAR_SMTP_MXSESS_LIMIT "smtp_mx_session_limit"
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20050621"
+#define MAIL_RELEASE_DATE "20050622"
#define MAIL_VERSION_NUMBER "2.3"
#define VAR_MAIL_VERSION "mail_version"
/* support DSN.
/*
/* This feature is available in Postfix 2.3 and later.
-/* .IP "\fB-V\fR (with Postfix 2.3 use \fB-XV\fR)"
+/* .IP "\fB-XV\fR (Postfix 2.2 and earlier: \fB-V\fR)"
/* Variable Envelope Return Path. Given an envelope sender address
/* of the form \fIowner-listname\fR@\fIorigin\fR, each recipient
/* \fIuser\fR@\fIdomain\fR receives mail with a personalized envelope
/* \fIowner-listname\fB+\fIuser\fB=\fIdomain\fR@\fIorigin\fR. The default
/* \fB+\fR and \fB=\fR characters are configurable with the
/* \fBdefault_verp_delimiters\fR configuration parameter.
-/* .IP "\fB-V\fIxy\fR (with Postfix 2.3 use \fB-XV\fIxy\fR)"
-/* As \fB-V\fR, but uses \fIx\fR and \fIy\fR as the VERP delimiter
+/* .IP "\fB-XV\fIxy\fR (Postfix 2.2 and earlier: \fB-V\fIxy\fR)"
+/* As \fB-XV\fR, but uses \fIx\fR and \fIy\fR as the VERP delimiter
/* characters, instead of the characters specified with the
/* \fBdefault_verp_delimiters\fR configuration parameter.
-/* .IP \fB-XV\fR
-/* Variable Envelope Return Path. Given an envelope sender address
-/* of the form \fIowner-listname\fR@\fIorigin\fR, each recipient
-/* \fIuser\fR@\fIdomain\fR receives mail with a personalized envelope
-/* sender address.
-/* .sp
-/* By default, the personalized envelope sender address is
-/* \fIowner-listname\fB+\fIuser\fB=\fIdomain\fR@\fIorigin\fR. The default
-/* \fB+\fR and \fB=\fR characters are configurable with the
-/* \fBdefault_verp_delimiters\fR configuration parameter.
-/* .sp
-/* This feature is available in Postfix version 2.3 and later.
-/* .IP \fB-XV\fIxy\fR
-/* As \fB-V\fR, but uses \fIx\fR and \fIy\fR as the VERP delimiter
-/* characters, instead of the characters specified with the
-/* \fBdefault_verp_delimiters\fR configuration parameter.
-/* .sp
-/* This feature is available in Postfix version 2.3 and later.
/* .IP \fB-v\fR
/* Send an email report of the first delivery attempt (Postfix
/* versions 2.1 and later). Mail delivery
/* receiving the server response.
/* .PP
/* Available in Postfix version 2.1 and later:
-/* .IP "\fBsmtp_mx_address_limit (0)\fR"
+/* .IP "\fBsmtp_mx_address_limit (5)\fR"
/* The maximal number of MX (mail exchanger) IP addresses that can
/* result from mail exchanger lookups, or zero (no limit).
/* .IP "\fBsmtp_mx_session_limit (2)\fR"
#include <smtp_addr.h>
#include <smtp_reuse.h>
-/* smtp_salvage - salvage the server reply before disconnecting */
-
-static VSTRING *smtp_salvage(VSTREAM *stream)
-{
- int len = vstream_peek(stream);
- VSTRING *buf = vstring_alloc(len);
-
- /*
- * We know the server replied with 4... or 5...; salvage whatever we have
- * received in the VSTREAM buffer and sanitize any non-printable crud.
- */
- vstream_fread(stream, STR(buf), len);
- VSTRING_AT_OFFSET(buf, len); /* XXX not public interface */
- VSTRING_TERMINATE(buf);
- translit(STR(buf), "\r\n", " ");
- printable(STR(buf), '?');
- return (buf);
-}
-
/* smtp_connect_addr - connect to explicit address */
static SMTP_SESSION *smtp_connect_addr(const char *dest, DNS_RR *addr,
/*
* Skip this host if it takes no action within some time limit. XXX Some
- * MTAs use 426 for to indicate a timeout error.
+ * MTAs use 426 to indicate a timeout error.
*/
if (read_wait(sock, var_smtp_helo_tmout) < 0) {
smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
vstream_ungetc(stream, ch);
/*
- * Skip this host if it sends a 4xx or 5xx greeting. This prevents us
- * from counting it towards the MX session limit. Unfortunately, this
- * also means that we have to salvage the server's response ourself so
- * that it can be included in logging or in non-delivery reports. It does
- * not hurt if we keep the test for a 4xx or 5xx greeting in smtp_helo().
- *
- * Do not propagate the server's DSN code. We are skipping this problem!
+ * Bundle up what we have into a nice SMTP_SESSION object.
*/
- if (ch == '4' || (ch == '5' && var_smtp_skip_5xx_greeting)) {
- VSTRING *salvage_buf = smtp_salvage(stream);
-
- smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
- "4.3.0", 420, "420 Connection rejected by server",
- "connect to %s[%s]: server refused to talk to me: %s",
- addr->name, hostaddr.buf, STR(salvage_buf));
- vstring_free(salvage_buf);
- smtp_errno = SMTP_ERR_RETRY;
- vstream_fclose(stream);
- return (0);
- }
return (smtp_session_alloc(stream, dest, addr->name,
hostaddr.buf, port, sess_flags));
}
switch ((resp = smtp_chat_resp(session))->code / 100) {
case 2:
break;
- case 4:
case 5:
- /* Handled in smtp_connect(). */
+ if (var_smtp_skip_5xx_greeting)
+ STR(resp->dsn_buf)[0] = '4';
+ /* FALLTHROUGH */
default:
return (smtp_site_fail(state, session->host, resp,
"host %s refused to talk to me: %s",
#include <vstring.h>
extern VSTRING *tls_session_passivate(SSL_SESSION *);
-extern SSL_SESSION *tls_session_activate(char *, int);
+extern SSL_SESSION *tls_session_activate(const char *, int);
/*
* tls_stream.c.
#include <sys_defs.h>
#include <ctype.h>
+#include <string.h>
#ifdef USE_TLS
/* tls_session_activate - activate passivated session */
-SSL_SESSION *tls_session_activate(char *session_data, int session_data_len)
+SSL_SESSION *tls_session_activate(const char *session_data, int session_data_len)
{
SSL_SESSION *session;
- unsigned char *ptr;
+ const unsigned char *ptr;
/*
* Activate the SSL_SESSION object.
*/
- ptr = (unsigned char *) session_data;
+ ptr = (const unsigned char *) session_data;
session = d2i_SSL_SESSION((SSL_SESSION **) 0, &ptr, session_data_len);
if (!session)
tls_print_errors();