From: Wietse Venema Date: Sat, 25 Jun 2016 05:00:00 +0000 (-0500) Subject: postfix-3.2-20160625 X-Git-Tag: v3.2.0-RC1~23 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=506a3e8993d1d73b397a113b89319ff997e8673b;p=thirdparty%2Fpostfix.git postfix-3.2-20160625 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index ad4a2be63..7246e3529 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -1,4 +1,8 @@ In addition to the names listed below, the following people provided + +20160618 + + Bugfix: useful inputs on many occasions: Paul D. Robertson, Simon J. Mudd. Apologies for any names omitted. @@ -22370,5 +22374,40 @@ Apologies for any names omitted. 20140612 - Bugfix: missing server address/port conversion. File: + Bugfix (introduced: 20090211): missing server address + conversion for non-proxy, non-postscreen connections. File: smtpd/smtpd_peer.c. + + Bugfix (introduced: 20160611) missing server port conversion + for non-proxy, non-postscreen connections, because there was + no server address conversion. File: smtpd/smtpd_peer.c. + +20160618 + + Bugfix(introduced: 20091121): with the introduction of + sender_dependent_default_transport_maps, the SMTP daemon + was not updated. This resulted in false rejects with + sender-dependent "error" transports. Based on a fix by + Russell Yanofsky. Files: global/resolve_clnt.c, + global/resolve_clnt.h, smtpd/smtpd_check.c, smtpd/smtpd_check.h, + smtpd/smtpd_milter.c, smtpd/smtpd_resolve.c, smtpd/smtpd_resolve.h. + +20160619 + + Refinements to the 20160618 fix. For more consistent results + with sender address validation, use the recipient address + (if available) as the sender-dependent address resolver + context. For better caching, pass sender context with all + attempts to resolve an email address. File: smtpd/smtpd.c, + smtpd/smtpd_check.c, smtpd/smtpd_milter.c. + +20160625 + + Cleanup: the Postfix SMTP server now passes network address + and port information to the Cyrus SASL library. Build with + ``make makefiles "CCARGS=$CCARGS -DNO_IP_CYRUS_SASL_AUTH"'' + for backwards compatibility. Files: makedefs, + smtpd/smtpd_sasl_glue.c, xsasl/xsasl.h, xsasl/xsasl_cyrus_server.c, + xsasl/xsasl_server.c. + + Cleanup: dnsblog manpage. File: dnsblog/dnsblog.c. diff --git a/postfix/WISHLIST b/postfix/WISHLIST index 488e361a1..c9f6558cd 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -9,6 +9,8 @@ Wish list: Propagate SMTPD_PEER_CODE_XXX from smtpd(8) to cleanup(8), so that {client_resolve} and {_} produce consistent results. + NO_IP_CYRUS_SASL_AUTH should be a main.cf parameter. + Modeline support in config files to enable/disable trailing #comment, and to give hints about how to handle an LHS or RHS. diff --git a/postfix/html/dnsblog.8.html b/postfix/html/dnsblog.8.html index 8e51362e4..229ccbae0 100644 --- a/postfix/html/dnsblog.8.html +++ b/postfix/html/dnsblog.8.html @@ -24,8 +24,8 @@ DNSBLOG(8) DNSBLOG(8) match and replies with the query arguments plus an address list with the resulting IP addresses, separated by whitespace, and the reply TTL. Otherwise it replies with the query arguments plus an empty address - list and the reply TTL; the reply TTL is -1 if there is no reply, or if - a negative reply contains no SOA record. Finally, The dnsblog(8) + list and the reply TTL; the reply TTL is -1 if there is no reply, or a + negative reply that contains no SOA record. Finally, the dnsblog(8) server closes the connection. DIAGNOSTICS diff --git a/postfix/makedefs b/postfix/makedefs index 694868c47..8b8f07acb 100644 --- a/postfix/makedefs +++ b/postfix/makedefs @@ -67,6 +67,10 @@ # # Note: this directive is for debugging and testing only. It # is not guaranteed to work on all platforms. +# .IP \fB-DNO_IP_CYRUS_SASL_AUTH\fR +# Don't pass remote SMTP client and Postfix SMTP server IP +# address and port information to the Cyrus SASL library. +# This is compatible with Postfix < 3.2. # .IP \fB-DNO_KQUEUE\fR # Do not build with FreeBSD/NetBSD/OpenBSD/MacOSX KQUEUE support. # By default, KQUEUE support is compiled in on platforms that diff --git a/postfix/man/man8/dnsblog.8 b/postfix/man/man8/dnsblog.8 index ba95973fe..c9a8bff35 100644 --- a/postfix/man/man8/dnsblog.8 +++ b/postfix/man/man8/dnsblog.8 @@ -29,8 +29,8 @@ query arguments plus an address list with the resulting IP addresses, separated by whitespace, and the reply TTL. Otherwise it replies with the query arguments plus an empty address list and the reply TTL; the reply TTL is \-1 if there -is no reply, or if a negative reply contains no SOA record. -Finally, The \fBdnsblog\fR(8) server closes the connection. +is no reply, or a negative reply that contains no SOA record. +Finally, the \fBdnsblog\fR(8) server closes the connection. .SH DIAGNOSTICS .ad .fi diff --git a/postfix/src/dnsblog/dnsblog.c b/postfix/src/dnsblog/dnsblog.c index 5243828b6..ef9842ec2 100644 --- a/postfix/src/dnsblog/dnsblog.c +++ b/postfix/src/dnsblog/dnsblog.c @@ -21,8 +21,8 @@ /* addresses, separated by whitespace, and the reply TTL. /* Otherwise it replies with the query arguments plus an empty /* address list and the reply TTL; the reply TTL is -1 if there -/* is no reply, or if a negative reply contains no SOA record. -/* Finally, The \fBdnsblog\fR(8) server closes the connection. +/* is no reply, or a negative reply that contains no SOA record. +/* Finally, the \fBdnsblog\fR(8) server closes the connection. /* DIAGNOSTICS /* Problems and transactions are logged to \fBsyslogd\fR(8). /* CONFIGURATION PARAMETERS diff --git a/postfix/src/global/dict_mysql.c b/postfix/src/global/dict_mysql.c index a0279f4f1..732b63c04 100644 --- a/postfix/src/global/dict_mysql.c +++ b/postfix/src/global/dict_mysql.c @@ -295,8 +295,9 @@ static void dict_mysql_quote(DICT *dict, const char *name, VSTRING *result) * We won't get integer overflows in 2*len + 1, because Postfix input * keys have reasonable size limits, better safe than sorry. */ - if (len > (INT_MAX - 1) / 2) - msg_panic("dict_mysql_quote: integer overflow in 2*%d+1", len); + if (len > (INT_MAX - VSTRING_LEN(result) - 1) / 2) + msg_panic("dict_mysql_quote: integer overflow in %lu+2*%d+1", + (unsigned long) VSTRING_LEN(result), len); buflen = 2 * len + 1; VSTRING_SPACE(result, buflen); diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 11e92caa3..f26efffd3 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 "20160612" +#define MAIL_RELEASE_DATE "20160625" #define MAIL_VERSION_NUMBER "3.2" #ifdef SNAPSHOT diff --git a/postfix/src/global/resolve_clnt.c b/postfix/src/global/resolve_clnt.c index 40ef3b77c..3014e4a1b 100644 --- a/postfix/src/global/resolve_clnt.c +++ b/postfix/src/global/resolve_clnt.c @@ -18,19 +18,11 @@ /* void resolve_clnt_init(reply) /* RESOLVE_REPLY *reply; /* -/* void resolve_clnt_query(address, reply) -/* const char *address; -/* RESOLVE_REPLY *reply; -/* /* void resolve_clnt_query_from(sender, address, reply) /* const char *sender; /* const char *address; /* RESOLVE_REPLY *reply; /* -/* void resolve_clnt_verify(address, reply) -/* const char *address; -/* RESOLVE_REPLY *reply; -/* /* void resolve_clnt_verify_from(sender, address, reply) /* const char *sender; /* const char *address; @@ -45,19 +37,17 @@ /* by resolve_clnt_query(). The structure is destroyed by passing /* it to resolve_clnt_free(). /* -/* resolve_clnt_query() sends an internal-form recipient address +/* resolve_clnt_query_from() sends an internal-form recipient address /* (user@domain) to the resolver daemon and returns the resulting /* transport name, next_hop host name, and internal-form recipient /* address. In case of communication failure the program keeps trying -/* until the mail system goes down. +/* until the mail system goes down. The internal-form sender +/* information is used for sender-dependent relayhost lookup. +/* Specify RESOLVE_NULL_FROM when the sender is unavailable. /* -/* resolve_clnt_verify() implements an alternative version that can +/* resolve_clnt_verify_from() implements an alternative version that can /* be used for address verification. /* -/* resolve_clnt_query_from() and resolve_clnt_verify_from() -/* allow the caller to supply sender context that will be used -/* for sender-dependent relayhost lookup. -/* /* In the resolver reply, the flags member is the bit-wise OR of /* zero or more of the following: /* .IP RESOLVE_FLAG_FINAL diff --git a/postfix/src/global/resolve_clnt.h b/postfix/src/global/resolve_clnt.h index a198bfdaf..b4290c0c1 100644 --- a/postfix/src/global/resolve_clnt.h +++ b/postfix/src/global/resolve_clnt.h @@ -53,11 +53,6 @@ extern void resolve_clnt_free(RESOLVE_REPLY *); #define RESOLVE_NULL_FROM "" -#define resolve_clnt_query(a, r) \ - resolve_clnt(RESOLVE_REGULAR, RESOLVE_NULL_FROM, (a), (r)) -#define resolve_clnt_verify(a, r) \ - resolve_clnt(RESOLVE_VERIFY, RESOLVE_NULL_FROM, (a), (r)) - #define resolve_clnt_query_from(f, a, r) \ resolve_clnt(RESOLVE_REGULAR, (f), (a), (r)) #define resolve_clnt_verify_from(f, a, r) \ diff --git a/postfix/src/smtpd/Makefile.in b/postfix/src/smtpd/Makefile.in index d5ffb4069..2ad34988f 100644 --- a/postfix/src/smtpd/Makefile.in +++ b/postfix/src/smtpd/Makefile.in @@ -531,6 +531,7 @@ smtpd_resolve.o: ../../include/mymalloc.h smtpd_resolve.o: ../../include/nvtable.h smtpd_resolve.o: ../../include/resolve_clnt.h smtpd_resolve.o: ../../include/rewrite_clnt.h +smtpd_resolve.o: ../../include/split_at.h smtpd_resolve.o: ../../include/stringops.h smtpd_resolve.o: ../../include/sys_defs.h smtpd_resolve.o: ../../include/vbuf.h diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 1365e7d8b..2e24a08b8 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -2286,7 +2286,9 @@ static int extract_addr(SMTPD_STATE *state, SMTPD_TOKEN *arg, if ((STR(state->addr_buf)[0] == 0 && !allow_empty_addr) || (strict_rfc821 && STR(state->addr_buf)[0] == '@') || (SMTPD_STAND_ALONE(state) == 0 - && smtpd_check_addr(STR(state->addr_buf), smtputf8) != 0)) { + && smtpd_check_addr(strcmp(state->where, SMTPD_CMD_MAIL) == 0 ? + state->recipient : state->sender, + STR(state->addr_buf), smtputf8) != 0)) { msg_warn("Illegal address syntax from %s in %s command: %s", state->namaddr, state->where, printable(STR(arg->vstrval), '?')); diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index a0287725e..546e46884 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -9,7 +9,8 @@ /* /* void smtpd_check_init() /* -/* int smtpd_check_addr(address, smtputf8) +/* int smtpd_check_addr(sender, address, smtputf8) +/* const char *sender; /* const char *address; /* int smtputf8; /* @@ -57,7 +58,9 @@ /* once during the process life time. /* /* smtpd_check_addr() sanity checks an email address and returns -/* non-zero in case of badness. +/* non-zero in case of badness. The sender argument provides sender +/* context for address resolution and caching, or a null pointer +/* if information is unavailable. /* /* smtpd_check_rewrite() should be called before opening a queue /* file or proxy connection, in order to establish the proper @@ -351,7 +354,8 @@ static int generic_checks(SMTPD_STATE *, ARGV *, const char *, const char *, con */ static int check_sender_rcpt_maps(SMTPD_STATE *, const char *); static int check_recipient_rcpt_maps(SMTPD_STATE *, const char *); -static int check_rcpt_maps(SMTPD_STATE *, const char *, const char *); +static int check_rcpt_maps(SMTPD_STATE *, const char *, const char *, + const char *); /* * Tempfail actions; @@ -1615,7 +1619,7 @@ static int permit_auth_destination(SMTPD_STATE *state, char *recipient) /* * Resolve the address. */ - reply = smtpd_resolve_addr(recipient); + reply = smtpd_resolve_addr(state->sender, recipient); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, recipient); @@ -1910,7 +1914,7 @@ static int permit_mx_backup(SMTPD_STATE *state, const char *recipient, /* * Resolve the address. */ - reply = smtpd_resolve_addr(recipient); + reply = smtpd_resolve_addr(state->sender, recipient); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, recipient); @@ -2098,7 +2102,8 @@ static int reject_unknown_address(SMTPD_STATE *state, const char *addr, /* * Resolve the address. */ - reply = smtpd_resolve_addr(addr); + reply = smtpd_resolve_addr(strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ? + state->recipient : state->sender, addr); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, addr); @@ -3155,7 +3160,8 @@ static int check_mail_access(SMTPD_STATE *state, const char *table, /* * Resolve the address. */ - reply = smtpd_resolve_addr(addr); + reply = smtpd_resolve_addr(strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ? + state->recipient : state->sender, addr); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, addr); @@ -3806,7 +3812,7 @@ static int reject_auth_sender_login_mismatch(SMTPD_STATE *state, const char *sen * Reject if the client is logged in and does not own the sender address. */ if (smtpd_sender_login_maps && state->sasl_username) { - reply = smtpd_resolve_addr(sender); + reply = smtpd_resolve_addr(state->recipient, sender); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, sender); if ((owners = check_mail_addr_find(state, sender, smtpd_sender_login_maps, @@ -3840,7 +3846,7 @@ static int reject_unauth_sender_login_mismatch(SMTPD_STATE *state, const char *s * owner. */ if (smtpd_sender_login_maps && !state->sasl_username) { - reply = smtpd_resolve_addr(sender); + reply = smtpd_resolve_addr(state->recipient, sender); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, sender); if (check_mail_addr_find(state, sender, smtpd_sender_login_maps, @@ -4658,7 +4664,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, /* smtpd_check_addr - address sanity check */ -int smtpd_check_addr(const char *addr, int smtputf8) +int smtpd_check_addr(const char *sender, const char *addr, int smtputf8) { const RESOLVE_REPLY *resolve_reply; const char *myname = "smtpd_check_addr"; @@ -4674,7 +4680,7 @@ int smtpd_check_addr(const char *addr, int smtputf8) */ if (addr == 0 || *addr == 0) return (0); - resolve_reply = smtpd_resolve_addr(addr); + resolve_reply = smtpd_resolve_addr(sender, addr); if (resolve_reply->flags & RESOLVE_FLAG_ERROR) return (-1); @@ -5084,7 +5090,8 @@ static int check_recipient_rcpt_maps(SMTPD_STATE *state, const char *recipient) if (state->warn_if_reject == 0) /* We really validate the recipient address. */ state->recipient_rcptmap_checked = 1; - return (check_rcpt_maps(state, recipient, SMTPD_NAME_RECIPIENT)); + return (check_rcpt_maps(state, state->sender, recipient, + SMTPD_NAME_RECIPIENT)); } /* check_sender_rcpt_maps - generic_checks() sender table check */ @@ -5103,12 +5110,14 @@ static int check_sender_rcpt_maps(SMTPD_STATE *state, const char *sender) if (state->warn_if_reject == 0) /* We really validate the sender address. */ state->sender_rcptmap_checked = 1; - return (check_rcpt_maps(state, sender, SMTPD_NAME_SENDER)); + return (check_rcpt_maps(state, state->recipient, sender, + SMTPD_NAME_SENDER)); } /* check_rcpt_maps - generic_checks() interface for recipient table check */ -static int check_rcpt_maps(SMTPD_STATE *state, const char *recipient, +static int check_rcpt_maps(SMTPD_STATE *state, const char *sender, + const char *recipient, const char *reply_class) { const RESOLVE_REPLY *reply; @@ -5120,7 +5129,7 @@ static int check_rcpt_maps(SMTPD_STATE *state, const char *recipient, /* * Resolve the address. */ - reply = smtpd_resolve_addr(recipient); + reply = smtpd_resolve_addr(sender, recipient); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, recipient); diff --git a/postfix/src/smtpd/smtpd_check.h b/postfix/src/smtpd/smtpd_check.h index a654cd6e0..e7f440145 100644 --- a/postfix/src/smtpd/smtpd_check.h +++ b/postfix/src/smtpd/smtpd_check.h @@ -13,7 +13,7 @@ * External interface. */ extern void smtpd_check_init(void); -extern int smtpd_check_addr(const char *, int); +extern int smtpd_check_addr(const char *, const char *, int); extern char *smtpd_check_rewrite(SMTPD_STATE *); extern char *smtpd_check_client(SMTPD_STATE *); extern char *smtpd_check_helo(SMTPD_STATE *, char *); diff --git a/postfix/src/smtpd/smtpd_milter.c b/postfix/src/smtpd/smtpd_milter.c index 463097e82..5deba6798 100644 --- a/postfix/src/smtpd/smtpd_milter.c +++ b/postfix/src/smtpd/smtpd_milter.c @@ -162,7 +162,7 @@ const char *smtpd_milter_eval(const char *name, void *ptr) return (0); if (state->sender[0] == 0) return (""); - reply = smtpd_resolve_addr(state->sender); + reply = smtpd_resolve_addr(state->recipient, state->sender); /* Sendmail 8.13 does not externalize the null string. */ if (STR(reply->recipient)[0]) quote_821_local(state->expand_buf, STR(reply->recipient)); @@ -173,13 +173,13 @@ const char *smtpd_milter_eval(const char *name, void *ptr) if (strcmp(name, S8_MAC_MAIL_HOST) == 0) { if (state->sender == 0) return (0); - reply = smtpd_resolve_addr(state->sender); + reply = smtpd_resolve_addr(state->recipient, state->sender); return (STR(reply->nexthop)); } if (strcmp(name, S8_MAC_MAIL_MAILER) == 0) { if (state->sender == 0) return (0); - reply = smtpd_resolve_addr(state->sender); + reply = smtpd_resolve_addr(state->recipient, state->sender); return (STR(reply->transport)); } @@ -197,7 +197,7 @@ const char *smtpd_milter_eval(const char *name, void *ptr) cp = split_at(STR(state->expand_buf), ' '); return (cp ? split_at(cp, ' ') : cp); } - reply = smtpd_resolve_addr(state->recipient); + reply = smtpd_resolve_addr(state->sender, state->recipient); /* Sendmail 8.13 does not externalize the null string. */ if (STR(reply->recipient)[0]) quote_821_local(state->expand_buf, STR(reply->recipient)); @@ -214,7 +214,7 @@ const char *smtpd_milter_eval(const char *name, void *ptr) (void) split_at(STR(state->expand_buf), ' '); return (STR(state->expand_buf)); } - reply = smtpd_resolve_addr(state->recipient); + reply = smtpd_resolve_addr(state->sender, state->recipient); return (STR(reply->nexthop)); } if (strcmp(name, S8_MAC_RCPT_MAILER) == 0) { @@ -222,7 +222,7 @@ const char *smtpd_milter_eval(const char *name, void *ptr) return (0); if (state->milter_reject_text) return (S8_RCPT_MAILER_ERROR); - reply = smtpd_resolve_addr(state->recipient); + reply = smtpd_resolve_addr(state->sender, state->recipient); return (STR(reply->transport)); } return (0); diff --git a/postfix/src/smtpd/smtpd_resolve.c b/postfix/src/smtpd/smtpd_resolve.c index 7cd8e4cda..0adf6904e 100644 --- a/postfix/src/smtpd/smtpd_resolve.c +++ b/postfix/src/smtpd/smtpd_resolve.c @@ -9,7 +9,8 @@ /* void smtpd_resolve_init(cache_size) /* int cache_size; /* -/* const RESOLVE_REPLY *smtpd_resolve_addr(addr) +/* const RESOLVE_REPLY *smtpd_resolve_addr(sender, addr) +/* const char *sender; /* const char *addr; /* DESCRIPTION /* This module maintains a resolve client cache that persists @@ -26,6 +27,8 @@ /* Arguments: /* .IP cache_size /* The requested cache size. +/* .IP sender +/* The message sender, or null pointer. /* .IP addr /* The address to resolve. /* DIAGNOSTICS @@ -56,6 +59,7 @@ #include #include #include +#include /* Global library. */ @@ -70,20 +74,28 @@ static CTABLE *smtpd_resolve_cache; #define STR(x) vstring_str(x) +#define SENDER_ADDR_JOIN_CHAR '\n' /* resolve_pagein - page in an address resolver result */ -static void *resolve_pagein(const char *addr, void *unused_context) +static void *resolve_pagein(const char *sender_plus_addr, void *unused_context) { + const char myname[] = "resolve_pagein"; static VSTRING *query; + static VSTRING *junk; + static VSTRING *sender_buf; RESOLVE_REPLY *reply; - char *tmp; + const char *sender; + const char *addr; /* * Initialize on the fly. */ - if (query == 0) + if (query == 0) { query = vstring_alloc(10); + junk = vstring_alloc(10); + sender_buf = vstring_alloc(10); + } /* * Initialize. @@ -91,14 +103,22 @@ static void *resolve_pagein(const char *addr, void *unused_context) reply = (RESOLVE_REPLY *) mymalloc(sizeof(*reply)); resolve_clnt_init(reply); + /* + * Split the sender and address. + */ + vstring_strcpy(junk, sender_plus_addr); + sender = STR(junk); + if ((addr = split_at(STR(junk), SENDER_ADDR_JOIN_CHAR)) == 0) + msg_panic("%s: bad search key: \"%s\"", myname, sender_plus_addr); + /* * Resolve the address. */ + rewrite_clnt_internal(MAIL_ATTR_RWR_LOCAL, sender, sender_buf); rewrite_clnt_internal(MAIL_ATTR_RWR_LOCAL, addr, query); - resolve_clnt_query(STR(query), reply); - tmp = mystrdup(STR(reply->recipient)); - casefold(reply->recipient, tmp); /* XXX */ - myfree(tmp); + resolve_clnt_query_from(STR(sender_buf), STR(query), reply); + vstring_strcpy(junk, STR(reply->recipient)); + casefold(reply->recipient, STR(junk)); /* XXX */ /* * Save the result. @@ -136,10 +156,17 @@ void smtpd_resolve_init(int cache_size) resolve_pageout, (void *) 0); } -/* smtpd_resolve_addr - resolve cached addres */ +/* smtpd_resolve_addr - resolve cached address */ -const RESOLVE_REPLY *smtpd_resolve_addr(const char *addr) +const RESOLVE_REPLY *smtpd_resolve_addr(const char *sender, const char *addr) { + static VSTRING *sender_plus_addr_buf; + + /* + * Initialize on the fly. + */ + if (sender_plus_addr_buf == 0) + sender_plus_addr_buf = vstring_alloc(10); /* * Sanity check. @@ -150,5 +177,9 @@ const RESOLVE_REPLY *smtpd_resolve_addr(const char *addr) /* * Reply from the read-through cache. */ - return (const RESOLVE_REPLY *) ctable_locate(smtpd_resolve_cache, addr); + vstring_sprintf(sender_plus_addr_buf, "%s%c%s", + sender ? sender : RESOLVE_NULL_FROM, + SENDER_ADDR_JOIN_CHAR, addr); + return (const RESOLVE_REPLY *) + ctable_locate(smtpd_resolve_cache, STR(sender_plus_addr_buf)); } diff --git a/postfix/src/smtpd/smtpd_resolve.h b/postfix/src/smtpd/smtpd_resolve.h index bfbc494da..c04c52a7a 100644 --- a/postfix/src/smtpd/smtpd_resolve.h +++ b/postfix/src/smtpd/smtpd_resolve.h @@ -17,7 +17,7 @@ * External interface. */ extern void smtpd_resolve_init(int); -extern const RESOLVE_REPLY *smtpd_resolve_addr(const char *); +extern const RESOLVE_REPLY *smtpd_resolve_addr(const char*, const char *); /* LICENSE /* .ad diff --git a/postfix/src/smtpd/smtpd_sasl_glue.c b/postfix/src/smtpd/smtpd_sasl_glue.c index 3dcd18fe6..569f771d7 100644 --- a/postfix/src/smtpd/smtpd_sasl_glue.c +++ b/postfix/src/smtpd/smtpd_sasl_glue.c @@ -218,10 +218,15 @@ void smtpd_sasl_activate(SMTPD_STATE *state, const char *sasl_opts_name, if ((state->sasl_server = XSASL_SERVER_CREATE(smtpd_sasl_impl, &create_args, stream = state->client, - server_addr = (state->dest_addr ? - state->dest_addr : ""), + addr_family = state->addr_family, + server_addr = ADDR_OR_EMPTY(state->dest_addr, + SERVER_ADDR_UNKNOWN), + server_port = ADDR_OR_EMPTY(state->dest_port, + SERVER_PORT_UNKNOWN), client_addr = ADDR_OR_EMPTY(state->addr, CLIENT_ADDR_UNKNOWN), + client_port = ADDR_OR_EMPTY(state->port, + CLIENT_PORT_UNKNOWN), service = var_smtpd_sasl_service, user_realm = REALM_OR_NULL(var_smtpd_sasl_realm), security_options = sasl_opts_val, diff --git a/postfix/src/xsasl/xsasl.h b/postfix/src/xsasl/xsasl.h index 976a676ae..b494d7e22 100644 --- a/postfix/src/xsasl/xsasl.h +++ b/postfix/src/xsasl/xsasl.h @@ -46,8 +46,11 @@ typedef struct XSASL_SERVER { */ typedef struct XSASL_SERVER_CREATE_ARGS { VSTREAM *stream; + int addr_family; const char *server_addr; + const char *server_port; const char *client_addr; + const char *client_port; const char *service; const char *user_realm; const char *security_options; @@ -64,9 +67,10 @@ extern ARGV *xsasl_server_types(void); #define xsasl_server_create(impl, args) \ (impl)->create((impl), (args)) -#define XSASL_SERVER_CREATE(impl, args, a1, a2, a3, a4, a5, a6, a7) \ +#define XSASL_SERVER_CREATE(impl, args, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \ xsasl_server_create((impl), (((args)->a1), ((args)->a2), ((args)->a3), \ - ((args)->a4), ((args)->a5), ((args)->a6), ((args)->a7), (args))) + ((args)->a4), ((args)->a5), ((args)->a6), ((args)->a7), ((args)->a8), \ + ((args)->a9), ((args)->a10), (args))) #define xsasl_server_done(impl) (impl)->done((impl)); /* diff --git a/postfix/src/xsasl/xsasl_cyrus_server.c b/postfix/src/xsasl/xsasl_cyrus_server.c index 70e7a9d68..89e1fc9a0 100644 --- a/postfix/src/xsasl/xsasl_cyrus_server.c +++ b/postfix/src/xsasl/xsasl_cyrus_server.c @@ -57,6 +57,7 @@ /* System library. */ #include +#include #include #include @@ -139,6 +140,10 @@ typedef int MECHANISM_COUNT_TYPE; typedef const char *SERVEROUT_TYPE; typedef const void *VOID_SERVEROUT_TYPE; +#endif + +#ifndef NO_IP_CYRUS_SASL_AUTH +#define USE_IP_CYRUS_SASL_AUTH #endif /* @@ -264,8 +269,8 @@ static XSASL_SERVER *xsasl_cyrus_server_create(XSASL_SERVER_IMPL *unused_impl, XSASL_SERVER_CREATE_ARGS *args) { const char *myname = "xsasl_cyrus_server_create"; - char *server_address; - char *client_address; + char *server_addr_port = 0; + char *client_addr_port = 0; sasl_conn_t *sasl_conn = 0; XSASL_CYRUS_SERVER *server = 0; int sasl_status; @@ -286,6 +291,15 @@ static XSASL_SERVER *xsasl_cyrus_server_create(XSASL_SERVER_IMPL *unused_impl, if (sasl_conn) \ sasl_dispose(&sasl_conn); \ } \ + XSASL_CYRUS_SERVER_CREATE_RETURN(x); \ + } while (0) + +#define XSASL_CYRUS_SERVER_CREATE_RETURN(x) \ + do { \ + if (server_addr_port) \ + myfree(server_addr_port); \ + if (client_addr_port) \ + myfree(client_addr_port); \ return (x); \ } while (0) @@ -296,27 +310,31 @@ static XSASL_SERVER *xsasl_cyrus_server_create(XSASL_SERVER_IMPL *unused_impl, #define NO_SESSION_CALLBACKS ((sasl_callback_t *) 0) #define NO_AUTH_REALM ((char *) 0) -#if SASL_VERSION_MAJOR >= 2 && defined(USE_SASL_IP_AUTH) +#if SASL_VERSION_MAJOR >= 2 && defined(USE_IP_CYRUS_SASL_AUTH) /* - * Get IP addresses of local and remote endpoints for SASL. + * Get IP address and port of local and remote endpoints for SASL. Some + * implementation supports "[ipv6addr]:port" and "ipv4addr:port" (e.g., + * https://illumos.org/man/3sasl/sasl_server_new), They still support the + * historical "address;port" syntax, so we stick with that for now. */ -#error "USE_SASL_IP_AUTH is not implemented" - + server_addr_port = (*args->server_addr && *args->server_port ? + concatenate(args->server_addr, ";", + args->server_port, (char *) 0) : 0); + client_addr_port = (*args->client_addr && *args->client_port ? + concatenate(args->client_addr, ";", + args->client_port, (char *) 0) : 0); #else /* - * Don't give any IP address information to SASL. SASLv1 doesn't use it, - * and in SASLv2 this will disable any mechanisms that do. + * Don't give any IP address information to SASL. */ - server_address = 0; - client_address = 0; #endif if ((sasl_status = SASL_SERVER_NEW(args->service, var_myhostname, args->user_realm ? args->user_realm : NO_AUTH_REALM, - server_address, client_address, + server_addr_port, client_addr_port, NO_SESSION_CALLBACKS, NO_SECURITY_LAYERS, &sasl_conn)) != SASL_OK) { msg_warn("SASL per-connection server initialization: %s", @@ -345,7 +363,7 @@ static XSASL_SERVER *xsasl_cyrus_server_create(XSASL_SERVER_IMPL *unused_impl, != XSASL_AUTH_OK) XSASL_CYRUS_SERVER_CREATE_ERROR_RETURN(0); - return (&server->xsasl); + XSASL_CYRUS_SERVER_CREATE_RETURN(&server->xsasl); } /* xsasl_cyrus_server_set_security - set security properties */ diff --git a/postfix/src/xsasl/xsasl_server.c b/postfix/src/xsasl/xsasl_server.c index 6b45ab8b0..669a867a6 100644 --- a/postfix/src/xsasl/xsasl_server.c +++ b/postfix/src/xsasl/xsasl_server.c @@ -126,11 +126,15 @@ /* after successful authentication. /* /* Arguments: +/* .IP addr_family +/* The network address family: AF_INET6 or AF_INET. /* .IP auth_method /* AUTH command authentication method. /* .IP client_addr /* IPv4 or IPv6 address (no surrounding [] or ipv6: prefix), /* or zero-length string if unavailable. +/* .IP client_port +/* TCP port or zero-length string if unavailable. /* .IP init_resp /* AUTH command initial response or null pointer. /* .IP implementation @@ -148,6 +152,8 @@ /* .IP server_addr /* IPv4 or IPv6 address (no surrounding [] or ipv6: prefix), /* or zero-length string if unavailable. +/* .IP server_port +/* TCP port or zero-length string if unavailable. /* .IP server_reply /* BASE64 encoded server non-error reply (without SMTP reply /* code or enhanced status code), or ASCII error description.