Bugfix: simplified and improved the 20050422 fall-back relay
fix. File: smtp/smtp_connect.c.
+20050427
+
+ Final solution for the 20050422 fall-back relay problem:
+ truncate the fall-back host list when the local MTA is MX
+ for some destination. Files: util/argv.c, smtp/smtp_connect.c.
+
+ Cleanup: extra dsn_vstring_update_dsn() routine to shut up
+ GCC complaints about valid code. Files: src/global/dsn_util.c,
+ src/global/mbox_open.c, src/lmtp/lmtp_addr.c, src/smtp/smtp_addr.c,
+ src/smtp/smtp_connect.c.
+
Open problems:
Med: disable header address rewriting after XCLIENT?
smtpd_recipient_restrictions =
permit_mynetworks
reject_unauth_destination
- hash:/etc/postfix/recipient_access
+ check_recipient_access hash:/etc/postfix/recipient_access
/etc/postfix/recipient_access:
joe@my.domain permissive
/etc/postfix/main.cf:
smtpd_recipient_restrictions =
- hash:/etc/postfix/access
+ check_recipient_access hash:/etc/postfix/access
...the usual stuff...
/etc/postfix/access:
/etc/postfix/main.cf:
smtpd_recipient_restrictions =
- hash:/etc/postfix/protected_destinations
+ check_recipient_access hash:/etc/postfix/protected_destinations
...the usual stuff...
smtpd_restriction_classes = insiders_only
E\bEn\bna\bab\bbl\bli\bin\bng\bg S\bSA\bAS\bSL\bL a\bau\but\bth\bhe\ben\bnt\bti\bic\bca\bat\bti\bio\bon\bn i\bin\bn t\bth\bhe\be P\bPo\bos\bst\btf\bfi\bix\bx S\bSM\bMT\bTP\bP c\bcl\bli\bie\ben\bnt\bt
Turn on client-side SASL authentication, and specify a table with per-host or
-per-destination username and password information. Postfix first looks up the
-server hostname; if no entry is found, then Postfix looks up the destination
-domain name. Usually, this is the right-hand part of an email address, but it
-can also be a hostname or address enclosed in [], with an optional ":port", as
-specified with relayhost in with transport_maps.
+per-destination username and password information. Postfix first searches the
+table for an entry with the server hostname; if no entry is found, then Postfix
+searches the table for an entry with the next-hop destination. Usually, that is
+the right-hand part of an email address, but it can also be the information
+that is specified with the relayhost parameter or with a transport(5) table.
/etc/postfix/main.cf:
smtp_sasl_auth_enable = yes
<a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
<a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>
<a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>
- hash:/etc/postfix/recipient_access
+ <a href="postconf.5.html#check_recipient_access">check_recipient_access</a> hash:/etc/postfix/recipient_access
/etc/postfix/recipient_access:
joe@my.domain permissive
<pre>
/etc/postfix/main.cf:
<a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
- hash:/etc/postfix/access
+ <a href="postconf.5.html#check_recipient_access">check_recipient_access</a> hash:/etc/postfix/access
<i>...the usual stuff...</i>
/etc/postfix/access:
<pre>
/etc/postfix/main.cf:
<a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
- hash:/etc/postfix/protected_destinations
+ <a href="postconf.5.html#check_recipient_access">check_recipient_access</a> hash:/etc/postfix/protected_destinations
<i>...the usual stuff...</i>
<a href="postconf.5.html#smtpd_restriction_classes">smtpd_restriction_classes</a> = insiders_only
<p> Turn on client-side SASL authentication, and specify a table
with per-host or per-destination username and password information.
-Postfix first looks up the server hostname; if no entry is found,
-then Postfix looks up the destination domain name. Usually, this
-is the right-hand part of an email address, but it can also be a
-hostname or address enclosed in [], with an optional ":port", as
-specified with <a href="postconf.5.html#relayhost">relayhost</a> in with <a href="postconf.5.html#transport_maps">transport_maps</a>. </p>
+Postfix first searches the table for an entry with the server
+hostname; if no entry is found, then Postfix searches the table for
+an entry with the next-hop destination. Usually, that is the
+right-hand part of an email address, but it can also be the information
+that is specified with the <a href="postconf.5.html#relayhost">relayhost</a> parameter or with a <a href="transport.5.html">transport(5)</a>
+table. </p>
<blockquote>
<pre>
smtpd_recipient_restrictions =
permit_mynetworks
reject_unauth_destination
- hash:/etc/postfix/recipient_access
+ check_recipient_access hash:/etc/postfix/recipient_access
/etc/postfix/recipient_access:
joe@my.domain permissive
<pre>
/etc/postfix/main.cf:
smtpd_recipient_restrictions =
- hash:/etc/postfix/access
+ check_recipient_access hash:/etc/postfix/access
<i>...the usual stuff...</i>
/etc/postfix/access:
<pre>
/etc/postfix/main.cf:
smtpd_recipient_restrictions =
- hash:/etc/postfix/protected_destinations
+ check_recipient_access hash:/etc/postfix/protected_destinations
<i>...the usual stuff...</i>
smtpd_restriction_classes = insiders_only
<p> Turn on client-side SASL authentication, and specify a table
with per-host or per-destination username and password information.
-Postfix first looks up the server hostname; if no entry is found,
-then Postfix looks up the destination domain name. Usually, this
-is the right-hand part of an email address, but it can also be a
-hostname or address enclosed in [], with an optional ":port", as
-specified with relayhost in with transport_maps. </p>
+Postfix first searches the table for an entry with the server
+hostname; if no entry is found, then Postfix searches the table for
+an entry with the next-hop destination. Usually, that is the
+right-hand part of an email address, but it can also be the information
+that is specified with the relayhost parameter or with a transport(5)
+table. </p>
<blockquote>
<pre>
/* const char *dsn;
/* const char *format;
/*
+/* DSN_VSTRING *dsn_vstring_update_dsn(dv, dsn)
+/* DSN_VSTRING *dv;
+/* const char *dsn;
+/*
/* void dsn_vstring_free(dv)
/* DSN_VSTRING *dv;
/*
/* free text, or both. Specify a null pointer (or zero-length
/* string) for information that should not be updated.
/*
+/* dsn_vstring_update_dsn() pacifies the gcc compiler.
+/*
/* dsn_vstring_free() recycles the storage that was allocated
/* by dsn_vstring_alloc() and dsn_vstring_update().
/*
}
return (dv);
}
+
+/* dsn_vstring_update_dsn - update DSN */
+
+DSN_VSTRING *dsn_vstring_update_dsn(DSN_VSTRING *dv, const char *dsn)
+{
+ size_t len;
+
+ if ((len = dsn_valid(dsn)) == 0)
+ msg_panic("dsn_vstring_update_dsn: bad dsn: \"%s\"", dsn);
+ DSN_UPDATE(dv->dsn, dsn, len);
+ return (dv);
+}
extern DSN_VSTRING *dsn_vstring_alloc(int);
extern PRINTFLIKE(3, 4) DSN_VSTRING *dsn_vstring_update(DSN_VSTRING *, const char *, const char *,...);
+extern DSN_VSTRING *dsn_vstring_update_dsn(DSN_VSTRING *, const char *);
extern void dsn_vstring_free(DSN_VSTRING *);
/* LICENSE
* Patches change the patchlevel and the release date. Snapshots change the
* release date only.
*/
-#define MAIL_RELEASE_DATE "20050426"
+#define MAIL_RELEASE_DATE "20050427"
#define MAIL_VERSION_NUMBER "2.3"
#define VAR_MAIL_VERSION "mail_version"
st = &local_statbuf;
if ((fp = safe_open(path, flags | O_NONBLOCK, mode, st,
chown_uid, chown_gid, why->vstring)) == 0) {
- dsn_vstring_update(why, mbox_dsn(errno, def_dsn), "");
+ dsn_vstring_update_dsn(why, mbox_dsn(errno, def_dsn));
return (0);
}
close_on_exec(vstream_fileno(fp), CLOSE_ON_EXEC);
if (dot_lockfile(path, why->vstring) == 0) {
locked |= MBOX_DOT_LOCK;
} else if (errno == EEXIST) {
- dsn_vstring_update(why, mbox_dsn(EAGAIN, def_dsn), "");
+ dsn_vstring_update_dsn(why, mbox_dsn(EAGAIN, def_dsn));
vstream_fclose(fp);
return (0);
} else if (lock_style & MBOX_DOT_LOCK_MAY_FAIL) {
msg_warn("%s", vstring_str(why->vstring));
} else {
- dsn_vstring_update(why, mbox_dsn(errno, def_dsn), "");
+ dsn_vstring_update_dsn(why, mbox_dsn(errno, def_dsn));
vstream_fclose(fp);
return (0);
}
&& HUNKY_DORY(MBOX_FCNTL_LOCK, MYFLOCK_STYLE_FCNTL)) {
locked |= lock_style;
} else {
- dsn_vstring_update(why, mbox_dsn(errno, def_dsn), "");
+ dsn_vstring_update_dsn(why, mbox_dsn(errno, def_dsn));
if (locked & MBOX_DOT_LOCK)
dot_unlockfile(path);
vstream_fclose(fp);
addr_list = dns_rr_append(addr_list, addr);
break;
default:
- dsn_vstring_update(why, "4.4.3", "");
+ dsn_vstring_update_dsn(why, "4.4.3");
lmtp_errno = LMTP_RETRY;
break;
case DNS_FAIL:
- dsn_vstring_update(why, "4.4.3", "");
+ dsn_vstring_update_dsn(why, "4.4.3");
lmtp_errno = LMTP_FAIL;
break;
case DNS_NOTFOUND:
- dsn_vstring_update(why, "4.4.4", "");
+ dsn_vstring_update_dsn(why, "4.4.4");
lmtp_errno = LMTP_FAIL;
break;
}
addr_list = dns_rr_append(addr_list, addr);
return (addr_list);
default:
- dsn_vstring_update(why, "4.4.3", "");
+ dsn_vstring_update_dsn(why, "4.4.3");
smtp_errno = SMTP_ERR_RETRY;
return (addr_list);
case DNS_FAIL:
- dsn_vstring_update(why, "4.4.3", "");
+ dsn_vstring_update_dsn(why, "4.4.3");
if (smtp_errno != SMTP_ERR_RETRY)
smtp_errno = SMTP_ERR_FAIL;
return (addr_list);
case DNS_NOTFOUND:
- dsn_vstring_update(why, "4.4.4", "");
+ dsn_vstring_update_dsn(why, "4.4.4");
if (smtp_errno != SMTP_ERR_RETRY)
smtp_errno = SMTP_ERR_FAIL;
/* maybe native naming service will succeed */
*/
switch (dns_lookup(name, T_MX, 0, &mx_names, (VSTRING *) 0, why->vstring)) {
default:
- dsn_vstring_update(why, "4.4.3", "");
+ dsn_vstring_update_dsn(why, "4.4.3");
smtp_errno = SMTP_ERR_RETRY;
if (var_ign_mx_lookup_err)
addr_list = smtp_host_addr(name, misc_flags, why);
break;
case DNS_FAIL:
- dsn_vstring_update(why, "5.4.3", "");
+ dsn_vstring_update_dsn(why, "5.4.3");
smtp_errno = SMTP_ERR_FAIL;
if (var_ign_mx_lookup_err)
addr_list = smtp_host_addr(name, misc_flags, why);
addr_list = smtp_domain_addr(domain, misc_flags, why, &i_am_mx);
/* If we're MX host, don't connect to non-MX backups. */
if (i_am_mx)
- cpp[1] = 0;
+ argv_truncate(sites, cpp - sites->argv + 1);
}
state->final_server = (cpp[1] == 0);
*/
if (IS_FALLBACK_RELAY(cpp, sites, non_fallback_sites)) {
msg_warn("%s configuration problem", VAR_FALLBACK_RELAY);
- dsn_vstring_update(why, "4.3.5", "");
+ dsn_vstring_update_dsn(why, "4.3.5");
smtp_errno = SMTP_ERR_RETRY;
}
*/
else if (strcmp(sites->argv[0], var_relayhost) == 0) {
msg_warn("%s configuration problem", VAR_RELAYHOST);
- dsn_vstring_update(why, "4.3.5", "");
+ dsn_vstring_update_dsn(why, "4.3.5");
smtp_errno = SMTP_ERR_RETRY;
}
/*
/* void argv_terminate(argvp);
/* ARGV *argvp;
+/*
+/* void argv_truncate(argvp, len);
+/* ARGV *argvp;
+/* int len;
/* DESCRIPTION
/* The functions in this module manipulate arrays of string
/* pointers. An ARGV structure contains the following members:
/* returns a null pointer.
/*
/* argv_terminate() null-terminates its string array argument.
+/*
+/* argv_truncate() trucates its argument to the specified
+/* number of entries, but does not reallocate memory. The
+/* result is null-terminated.
/* SEE ALSO
/* msg(3) diagnostics interface
/* DIAGNOSTICS
*/
argvp->argv[argvp->argc] = 0;
}
+
+/* argv_truncate - truncate string array */
+
+void argv_truncate(ARGV *argvp, int len)
+{
+ char **cpp;
+
+ /*
+ * Sanity check.
+ */
+ if (len < 0)
+ msg_panic("argv_truncate: bad length %d", len);
+
+ if (len < argvp->argc) {
+ for (cpp = argvp->argv + len; cpp < argvp->argv + argvp->argc; cpp++)
+ myfree(*cpp);
+ argvp->argc = len;
+ argvp->argv[argvp->argc] = 0;
+ }
+}
extern void argv_add(ARGV *,...);
extern void argv_addn(ARGV *,...);
extern void argv_terminate(ARGV *);
+extern void argv_truncate(ARGV *, int);
extern ARGV *argv_free(ARGV *);
extern ARGV *argv_split(const char *, const char *);