From a3e9b5d9c21b3f6a1e03c81dc16ec7a957d6bc2c Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Wed, 1 Feb 2012 00:00:00 -0500 Subject: [PATCH] postfix-2.8.8 --- postfix/HISTORY | 52 +++++++++++++++++++ postfix/src/bounce/bounce_trace_service.c | 37 +++++++++++-- postfix/src/global/dict_ldap.c | 63 +++++++++++++---------- postfix/src/global/dict_sqlite.c | 13 ++++- postfix/src/global/mail_version.h | 4 +- postfix/src/global/maps.c | 6 +++ postfix/src/local/mailbox.c | 6 ++- postfix/src/local/unknown.c | 3 +- postfix/src/tlsproxy/tlsproxy.c | 2 +- postfix/src/util/dict.c | 2 + postfix/src/xsasl/xsasl_dovecot_server.c | 5 -- 11 files changed, 151 insertions(+), 42 deletions(-) diff --git a/postfix/HISTORY b/postfix/HISTORY index 42ac70fc8..71ac5fbaf 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -16695,3 +16695,55 @@ Apologies for any names omitted. Portability: OpenBSD 5.x is supported. Files: makedefs, util/sys_defs.h. + + Portability: Dovecot now officially supports more socket + types for its authentication server. File: + xsasl/xsasl_dovecot_server.c. + +20111126 + + Bitrot: changes in error reporting to the under-documented + OpenLDAP API. Problem reported by Quanah Gibson-Mount. Fix + by Viktor Dukhovni. File: global/dict_ldap.c. + +20111205 + + Bugfix: tlsproxy(8) stored TLS sessions with a serverID of + "tlsproxy" instead of "smtpd", wasting an opportunity for + session reuse. File: tlsproxy/tlsproxy.c. + +20111211 + + Bugfix: missing lookup table entry and terminator, causing + proxymap server segfault when postscreen(8) or verify(8) + attempted to access their cache via the proxymap server. + This could never have worked anyway, because the Postfix + 2.8 proxymap protocol does not support cache cleanup. File + util/dict.c. + +20111226 + + Bugfix (introduced 20110426): after lookup error with + mailbox_transport_maps, mailbox_command_maps or + fallback_transport_maps, the local delivery agent did not + log the problem before deferring mail, and produced no defer + logfile record. Files: local/mailbox.c, local/unknown.c. + +20120127 + + Bugfix (introduced: Postfix 2.8): the Postfix client sqlite + quoting routine returned the unquoted result instead of the + quoted text. The opportunities for misuse are limited, + because Postfix sqlite files are usually owned by root, and + Postfix daemons usually run with non-root privileges so + they can't corrupt the database. Problem reported by Rob + McGee (rob0). File: global/dict_sqlite.c. + +20120130 + + Bugfix (introduced: Postfix 2.3): the trace service did not + distinguish between notifications for a non-bounce or a + bounce message. This code pre-dates DSN support and should + have been updated when it was re-purposed to handle DSN + SUCCESS notifications. Problem reported by Sabahattin + Gucukoglu. File: bounce/bounce_trace_service.c. diff --git a/postfix/src/bounce/bounce_trace_service.c b/postfix/src/bounce/bounce_trace_service.c index 850515902..824931d60 100644 --- a/postfix/src/bounce/bounce_trace_service.c +++ b/postfix/src/bounce/bounce_trace_service.c @@ -83,8 +83,39 @@ int bounce_trace_service(int flags, char *service, char *queue_name, BOUNCE_INFO *bounce_info; int bounce_status = 1; VSTREAM *bounce; - VSTRING *new_id = vstring_alloc(10); + int notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks, + var_notify_classes); + VSTRING *new_id; int count; + const char *sender; + + /* + * For consistency with fail/delay notifications, send notification for a + * non-bounce message as a single-bounce message, send notification for a + * single-bounce message as a double-bounce message, and drop requests to + * send notification for a double-bounce message. + */ +#define NULL_SENDER MAIL_ADDR_EMPTY /* special address */ + + if (strcasecmp(recipient, mail_addr_double_bounce()) == 0) { + msg_info("%s: not sending trace/success notification for " + "double-bounce message", queue_id); + return (0); + } else if (*recipient == 0) { + if ((notify_mask & MAIL_ERROR_2BOUNCE) != 0) { + recipient = var_2bounce_rcpt; + sender = mail_addr_double_bounce(); + } else { + msg_info("%s: not sending trace/success notification " + "for single-bounce message", queue_id); + if (mail_queue_remove(service, queue_id) && errno != ENOENT) + msg_fatal("remove %s %s: %m", service, queue_id); + return (0); + } + } else { + /* Always send notification for non-bounce message. */ + sender = NULL_SENDER; + } /* * Initialize. Open queue file, bounce log, etc. @@ -126,7 +157,6 @@ int bounce_trace_service(int flags, char *service, char *queue_name, bounce_mail_free(bounce_info); return (0); } -#define NULL_SENDER MAIL_ADDR_EMPTY /* special address */ #define NULL_TRACE_FLAGS 0 /* @@ -139,7 +169,8 @@ int bounce_trace_service(int flags, char *service, char *queue_name, * there are fewer potential left-over files to remove up when we create * a new queue file. */ - if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient, + new_id = vstring_alloc(10); + if ((bounce = post_mail_fopen_nowait(sender, recipient, INT_FILT_MASK_BOUNCE, NULL_TRACE_FLAGS, new_id)) != 0) { diff --git a/postfix/src/global/dict_ldap.c b/postfix/src/global/dict_ldap.c index f9df3c597..40c3915ef 100644 --- a/postfix/src/global/dict_ldap.c +++ b/postfix/src/global/dict_ldap.c @@ -225,6 +225,7 @@ #include "mail_conf.h" #if defined(USE_LDAP_SASL) && defined(LDAP_API_FEATURE_X_OPENLDAP) + /* * SASL headers, for sasl_interact_t. Either SASL v1 or v2 should be fine. */ @@ -242,13 +243,13 @@ #define DICT_LDAP_DO_SASL(d) ((d)->bind == DICT_LDAP_BIND_SASL) static const NAME_CODE bindopt_table[] = { - CONFIG_BOOL_NO, DICT_LDAP_BIND_NONE, - "none", DICT_LDAP_BIND_NONE, - CONFIG_BOOL_YES, DICT_LDAP_BIND_SIMPLE, - "simple", DICT_LDAP_BIND_SIMPLE, + CONFIG_BOOL_NO, DICT_LDAP_BIND_NONE, + "none", DICT_LDAP_BIND_NONE, + CONFIG_BOOL_YES, DICT_LDAP_BIND_SIMPLE, + "simple", DICT_LDAP_BIND_SIMPLE, #ifdef LDAP_API_FEATURE_X_OPENLDAP #if defined(USE_LDAP_SASL) - "sasl", DICT_LDAP_BIND_SASL, + "sasl", DICT_LDAP_BIND_SASL, #endif #endif 0, -1, @@ -292,9 +293,9 @@ typedef struct { #ifdef LDAP_API_FEATURE_X_OPENLDAP #if defined(USE_LDAP_SASL) int sasl; - char *sasl_mechs; - char *sasl_realm; - char *sasl_authz; + char *sasl_mechs; + char *sasl_realm; + char *sasl_authz; int sasl_minssf; #endif int ldap_ssl; @@ -451,28 +452,26 @@ static int dict_ldap_set_errno(LDAP *ld, int rc) } #if defined(USE_LDAP_SASL) && defined(LDAP_API_FEATURE_X_OPENLDAP) + /* * Context structure for SASL property callback. */ typedef struct bind_props { - char *authcid; - char *passwd; - char *realm; - char *authzid; + char *authcid; + char *passwd; + char *realm; + char *authzid; } bind_props; -static int -ldap_b2_interact(LDAP *ld, unsigned flags, void *props, void *inter) +static int ldap_b2_interact(LDAP *ld, unsigned flags, void *props, void *inter) { sasl_interact_t *in; - bind_props *ctx = (bind_props *)props; + bind_props *ctx = (bind_props *) props; - for (in = inter; in->id != SASL_CB_LIST_END; in++) - { + for (in = inter; in->id != SASL_CB_LIST_END; in++) { in->result = NULL; - switch(in->id) - { + switch (in->id) { case SASL_CB_GETREALM: in->result = ctx->realm; break; @@ -491,6 +490,7 @@ ldap_b2_interact(LDAP *ld, unsigned flags, void *props, void *inter) } return LDAP_SUCCESS; } + #endif /* dict_ldap_result - Read and parse LDAP result */ @@ -498,6 +498,7 @@ ldap_b2_interact(LDAP *ld, unsigned flags, void *props, void *inter) static int dict_ldap_result(LDAP *ld, int msgid, int timeout, LDAPMessage **res) { struct timeval mytimeval; + int err; mytimeval.tv_sec = timeout; mytimeval.tv_usec = 0; @@ -506,9 +507,12 @@ static int dict_ldap_result(LDAP *ld, int msgid, int timeout, LDAPMessage **res) if (ldap_result(ld, msgid, GET_ALL, &mytimeval, res) == -1) return (dict_ldap_get_errno(ld)); - if (dict_ldap_get_errno(ld) == LDAP_TIMEOUT) { - (void) dict_ldap_abandon(ld, msgid); - return (dict_ldap_set_errno(ld, LDAP_TIMEOUT)); + if ((err = dict_ldap_get_errno(ld)) != LDAP_SUCCESS) { + if (err == LDAP_TIMEOUT) { + (void) dict_ldap_abandon(ld, msgid); + return (dict_ldap_set_errno(ld, LDAP_TIMEOUT)); + } + return err; } return LDAP_SUCCESS; } @@ -529,7 +533,7 @@ static int dict_ldap_bind_sasl(DICT_LDAP *dict_ldap) vstring_sprintf(minssf, "minssf=%d", dict_ldap->sasl_minssf); if ((rc = ldap_set_option(dict_ldap->ld, LDAP_OPT_X_SASL_SECPROPS, - (char *) minssf)) != LDAP_OPT_SUCCESS) + (char *) minssf)) != LDAP_OPT_SUCCESS) return (rc); props.authcid = dict_ldap->bind_dn; @@ -538,13 +542,14 @@ static int dict_ldap_bind_sasl(DICT_LDAP *dict_ldap) props.authzid = dict_ldap->sasl_authz; if ((rc = ldap_sasl_interactive_bind_s(dict_ldap->ld, NULL, - dict_ldap->sasl_mechs, NULL, NULL, - LDAP_SASL_QUIET, ldap_b2_interact, - &props)) != LDAP_SUCCESS) + dict_ldap->sasl_mechs, NULL, NULL, + LDAP_SASL_QUIET, ldap_b2_interact, + &props)) != LDAP_SUCCESS) return (rc); return (LDAP_SUCCESS); } + #endif /* dict_ldap_bind_st - Synchronous simple auth with timeout */ @@ -552,6 +557,7 @@ static int dict_ldap_bind_sasl(DICT_LDAP *dict_ldap) static int dict_ldap_bind_st(DICT_LDAP *dict_ldap) { int rc; + int err = LDAP_SUCCESS; int msgid; LDAPMessage *res; struct berval cred; @@ -567,7 +573,8 @@ static int dict_ldap_bind_st(DICT_LDAP *dict_ldap) return (rc); #define FREE_RESULT 1 - return (ldap_parse_sasl_bind_result(dict_ldap->ld, res, 0, FREE_RESULT)); + rc = ldap_parse_result(dict_ldap->ld, res, &err, 0, 0, 0, 0, FREE_RESULT); + return (rc == LDAP_SUCCESS ? err : rc); } /* search_st - Synchronous search with timeout */ @@ -868,6 +875,7 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap) #define DN_LOG_VAL(dict_ldap) \ ((dict_ldap)->bind_dn[0] ? (dict_ldap)->bind_dn : "empty or implicit") + /* * If this server requires a bind, do so. Thanks to Sam Tardieu for * noticing that the original bind call was broken. @@ -1873,6 +1881,7 @@ DICT *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags) #ifdef LDAP_API_FEATURE_X_OPENLDAP #if defined(USE_LDAP_SASL) + /* * SASL options */ diff --git a/postfix/src/global/dict_sqlite.c b/postfix/src/global/dict_sqlite.c index c349930e3..e422a6f79 100644 --- a/postfix/src/global/dict_sqlite.c +++ b/postfix/src/global/dict_sqlite.c @@ -57,6 +57,12 @@ /* AUTHOR(S) /* Axel Steiner /* ast@treibsand.com +/* +/* Adopted and updated by: +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA /*--*/ /* System library. */ @@ -109,7 +115,7 @@ static void dict_sqlite_quote(DICT *dict, const char *raw_text, VSTRING *result) /* Fix 20100616 */ if (quoted_text == 0) msg_fatal("dict_sqlite_quote: out of memory"); - vstring_strcat(result, raw_text); + vstring_strcat(result, quoted_text); sqlite3_free(quoted_text); } @@ -150,6 +156,11 @@ static const char *dict_sqlite_lookup(DICT *dict, const char *name) int expansion = 0; int status; + /* + * In case of return without lookup (skipped key, etc.). + */ + dict_errno = 0; + /* * Don't frustrate future attempts to make Postfix UTF-8 transparent. */ diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 921b117d5..cc33bb8ec 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,8 +20,8 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20111105" -#define MAIL_VERSION_NUMBER "2.8.7" +#define MAIL_RELEASE_DATE "20120201" +#define MAIL_VERSION_NUMBER "2.8.8" #ifdef SNAPSHOT # define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE diff --git a/postfix/src/global/maps.c b/postfix/src/global/maps.c index f0cb35526..79f8b91b5 100644 --- a/postfix/src/global/maps.c +++ b/postfix/src/global/maps.c @@ -163,6 +163,11 @@ const char *maps_find(MAPS *maps, const char *name, int flags) const char *expansion; DICT *dict; + /* + * In case of return without map lookup (empty name or no maps). + */ + dict_errno = 0; + /* * Temp. workaround, for buggy callers that pass zero-length keys when * given partial addresses. @@ -189,6 +194,7 @@ const char *maps_find(MAPS *maps, const char *name, int flags) *map_name, name, expansion); return (expansion); } else if (dict_errno != 0) { + msg_warn("%s:%s lookup of %s failed", dict->type, dict->name, name); break; } } diff --git a/postfix/src/local/mailbox.c b/postfix/src/local/mailbox.c index 58b01f79f..89c739274 100644 --- a/postfix/src/local/mailbox.c +++ b/postfix/src/local/mailbox.c @@ -289,7 +289,8 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp) } else if (dict_errno != 0) { /* Details in the logfile. */ dsb_simple(state.msg_attr.why, "4.3.0", "table lookup failure"); - *statusp = DEL_STAT_DEFER; + *statusp = defer_append(BOUNCE_FLAGS(state.request), + BOUNCE_ATTR(state.msg_attr)); return (YES); } if (*var_mailbox_transport) { @@ -333,7 +334,8 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp) } else if (dict_errno != 0) { /* Details in the logfile. */ dsb_simple(state.msg_attr.why, "4.3.0", "table lookup failure"); - status = DEL_STAT_DEFER; + status = defer_append(BOUNCE_FLAGS(state.request), + BOUNCE_ATTR(state.msg_attr)); } else if (*var_mailbox_command) { status = deliver_command(state, usr_attr, var_mailbox_command); } else if (*var_home_mailbox && LAST_CHAR(var_home_mailbox) == '/') { diff --git a/postfix/src/local/unknown.c b/postfix/src/local/unknown.c index eb5bbf250..57e49af84 100644 --- a/postfix/src/local/unknown.c +++ b/postfix/src/local/unknown.c @@ -120,7 +120,8 @@ int deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr) } else if (dict_errno != 0) { /* Details in the logfile. */ dsb_simple(state.msg_attr.why, "4.3.0", "table lookup failure"); - return (DEL_STAT_DEFER); + return (defer_append(BOUNCE_FLAGS(state.request), + BOUNCE_ATTR(state.msg_attr))); } if (*var_fallback_transport) { state.msg_attr.rcpt.offset = -1L; diff --git a/postfix/src/tlsproxy/tlsproxy.c b/postfix/src/tlsproxy/tlsproxy.c index 3c6b3c6c9..92aba47e8 100644 --- a/postfix/src/tlsproxy/tlsproxy.c +++ b/postfix/src/tlsproxy/tlsproxy.c @@ -692,7 +692,7 @@ static void tlsp_start_tls(TLSP_STATE *state) timeout = 0, /* unused */ requirecert = (var_tlsp_tls_req_ccert && var_tlsp_enforce_tls), - serverid = state->service, + serverid = MAIL_SERVICE_SMTPD, /* XXX */ namaddr = state->remote_endpt, cipher_grade = cipher_grade, cipher_exclusions = STR(cipher_exclusions), diff --git a/postfix/src/util/dict.c b/postfix/src/util/dict.c index 10b2a3f6d..885b8f504 100644 --- a/postfix/src/util/dict.c +++ b/postfix/src/util/dict.c @@ -536,6 +536,8 @@ static const NAME_MASK dict_mask[] = { "no_unauth", (1 << 13), /* disallow unauthenticated data */ "fold_fix", (1 << 14), /* case-fold with fixed-case key map */ "fold_mul", (1 << 15), /* case-fold with multi-case key map */ + "open_lock", (1 << 16), /* permanent lock upon open */ + 0, }; /* dict_flags_str - convert mask to string for debugging purposes */ diff --git a/postfix/src/xsasl/xsasl_dovecot_server.c b/postfix/src/xsasl/xsasl_dovecot_server.c index be7f82249..6c75dc9c1 100644 --- a/postfix/src/xsasl/xsasl_dovecot_server.c +++ b/postfix/src/xsasl/xsasl_dovecot_server.c @@ -371,11 +371,6 @@ XSASL_SERVER_IMPL *xsasl_dovecot_server_init(const char *server_type, { XSASL_DOVECOT_SERVER_IMPL *xp; - if (strchr(path_info, '/') == 0) - msg_warn("when SASL type is \"%s\", SASL path \"%s\" " - "should be a socket pathname", - server_type, path_info); - xp = (XSASL_DOVECOT_SERVER_IMPL *) mymalloc(sizeof(*xp)); xp->xsasl.create = xsasl_dovecot_server_create; xp->xsasl.done = xsasl_dovecot_server_done;