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.
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.
bounce_mail_free(bounce_info);
return (0);
}
-#define NULL_SENDER MAIL_ADDR_EMPTY /* special address */
#define NULL_TRACE_FLAGS 0
/*
* 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) {
#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.
*/
#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,
#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;
}
#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;
}
return LDAP_SUCCESS;
}
+
#endif
/* dict_ldap_result - Read and parse LDAP result */
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;
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;
}
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;
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 */
static int dict_ldap_bind_st(DICT_LDAP *dict_ldap)
{
int rc;
+ int err = LDAP_SUCCESS;
int msgid;
LDAPMessage *res;
struct berval cred;
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 */
#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.
#ifdef LDAP_API_FEATURE_X_OPENLDAP
#if defined(USE_LDAP_SASL)
+
/*
* SASL options
*/
/* 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. */
/* 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);
}
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.
*/
* 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
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.
*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;
}
}
} 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) {
} 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) == '/') {
} 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;
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),
"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 */
{
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;