2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-22 18:07:41 +00:00

postfix-2.9-20111230

This commit is contained in:
Wietse Venema 2011-12-30 00:00:00 -05:00 committed by Viktor Dukhovni
parent ae6c8a149c
commit 08997a0334
20 changed files with 123 additions and 65 deletions

View File

@ -17431,3 +17431,15 @@ Apologies for any names omitted.
global/addr_list_match.c, domain_list.c, string_list.c,
namadr_list.c, trivial-rewrite/resolve.c, smtpd/smtpd.c,
smtpd/smtpd_check.c, global/flush_clnt.c, flush/flush.c.
20111226
Cleanup: reset the global dict_errno flag before table
lookup, to avoid false alarms about table lookup errors.
Files: util/dict_thash.c, global/dict_sqlite.c, global.maps.c.
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.

View File

@ -150,8 +150,7 @@ static void dict_memcache_set(DICT_MC *dict_mc, const char *value, int ttl)
if (count > 0)
sleep(dict_mc->err_pause);
if ((fp = auto_clnt_access(dict_mc->clnt)) == 0) {
if (errno == ECONNREFUSED)
break;
break;
} else if (memcache_printf(fp, "set %s %d %d %ld",
STR(dict_mc->key_buf), dict_mc->mc_flags, ttl, data_len) < 0
|| memcache_fwrite(fp, value, strlen(value)) < 0
@ -190,8 +189,7 @@ static const char *dict_memcache_get(DICT_MC *dict_mc)
if (count > 0)
sleep(dict_mc->err_pause);
if ((fp = auto_clnt_access(dict_mc->clnt)) == 0) {
if (errno == ECONNREFUSED)
break;
break;
} else if (memcache_printf(fp, "get %s", STR(dict_mc->key_buf)) < 0
|| memcache_get(fp, dict_mc->clnt_buf, dict_mc->max_line) < 0) {
if (count > 0)
@ -239,8 +237,7 @@ static int dict_memcache_del(DICT_MC *dict_mc)
if (count > 0)
sleep(dict_mc->err_pause);
if ((fp = auto_clnt_access(dict_mc->clnt)) == 0) {
if (errno == ECONNREFUSED)
break;
break;
} else if (memcache_printf(fp, "delete %s", STR(dict_mc->key_buf)) < 0
|| memcache_get(fp, dict_mc->clnt_buf, dict_mc->max_line) < 0) {
if (count > 0)
@ -342,6 +339,7 @@ static void dict_memcache_update(DICT *dict, const char *name,
{
const char *myname = "dict_memcache_update";
DICT_MC *dict_mc = (DICT_MC *) dict;
DICT *backup = dict_mc->backup;
int backup_errno = 0;
/*
@ -360,19 +358,18 @@ static void dict_memcache_update(DICT *dict, const char *name,
/*
* Update the backup database last.
*/
if (dict_mc->backup) {
if (backup) {
dict_errno = 0;
dict_mc->backup->update(dict_mc->backup, name, value);
backup->update(backup, name, value);
backup_errno = dict_errno;
}
if (msg_verbose)
msg_info("%s: %s: update key \"%s\"(%s) => \"%s\" %s",
myname, dict_mc->dict.name, name, STR(dict_mc->key_buf),
value, dict_mc->mc_errno ? "(memcache error)" :
backup_errno ? "(backup error)" : "(no error)");
dict_errno = (dict_mc->backup ? backup_errno : dict_mc->mc_errno);
dict_errno = (backup ? backup_errno : dict_mc->mc_errno);
}
/* dict_memcache_lookup - lookup memcache */
@ -381,6 +378,7 @@ static const char *dict_memcache_lookup(DICT *dict, const char *name)
{
const char *myname = "dict_memcache_lookup";
DICT_MC *dict_mc = (DICT_MC *) dict;
DICT *backup = dict_mc->backup;
const char *retval;
int backup_errno = 0;
@ -401,8 +399,8 @@ static const char *dict_memcache_lookup(DICT *dict, const char *name)
* Search the backup database last. Update the memcache if the data is
* found.
*/
if (retval == 0 && dict_mc->backup) {
retval = dict_mc->backup->lookup(dict_mc->backup, name);
if (retval == 0 && backup) {
retval = backup->lookup(backup, name);
backup_errno = dict_errno;
/* Update the cache. */
if (retval != 0)
@ -414,7 +412,7 @@ static const char *dict_memcache_lookup(DICT *dict, const char *name)
retval ? retval : dict_mc->mc_errno ? "(memcache error)" :
backup_errno ? "(backup error)" : "(not found)");
dict_errno = (dict_mc->backup ? backup_errno : dict_mc->mc_errno);
dict_errno = (backup ? backup_errno : dict_mc->mc_errno);
return (retval);
}
@ -425,6 +423,7 @@ static int dict_memcache_delete(DICT *dict, const char *name)
{
const char *myname = "dict_memcache_delete";
DICT_MC *dict_mc = (DICT_MC *) dict;
DICT *backup = dict_mc->backup;
int backup_errno = 0;
int del_res;
@ -444,19 +443,18 @@ static int dict_memcache_delete(DICT *dict, const char *name)
/*
* Update the persistent database last.
*/
if (dict_mc->backup) {
if (backup) {
dict_errno = 0;
del_res = dict_mc->backup->delete(dict_mc->backup, name);
del_res = backup->delete(backup, name);
backup_errno = dict_errno;
}
if (msg_verbose)
msg_info("%s: %s: delete key \"%s\"(%s) => %s",
myname, dict_mc->dict.name, name, STR(dict_mc->key_buf),
dict_mc->mc_errno ? "(memcache error)" :
backup_errno ? "(backup error)" : "(no error)");
dict_errno = (dict_mc->backup ? backup_errno : dict_mc->mc_errno);
dict_errno = (backup ? backup_errno : dict_mc->mc_errno);
return (del_res);
}
@ -467,11 +465,15 @@ static int dict_memcache_sequence(DICT *dict, int function, const char **key,
const char **value)
{
DICT_MC *dict_mc = (DICT_MC *) dict;
DICT *backup = dict_mc->backup;
if (dict_mc->backup == 0)
msg_fatal("database %s:%s: first/next support requires backup database",
DICT_TYPE_MEMCACHE, dict_mc->dict.name);
return (dict_mc->backup->sequence(dict_mc->backup, function, key, value));
if (backup == 0) {
msg_warn("database %s:%s: first/next support requires backup database",
DICT_TYPE_MEMCACHE, dict_mc->dict.name);
return (1);
} else {
return (backup->sequence(backup, function, key, value));
}
}
/* dict_memcache_close - close memcache */

View File

@ -292,6 +292,7 @@ static void dict_proxy_update(DICT *dict, const char *key, const char *value)
msg_fatal("%s update access is not configured for table \"%s\"",
dict_proxy->service, dict->name);
case PROXY_STAT_OK:
dict_errno = 0;
return;
case PROXY_STAT_RETRY:
dict_errno = DICT_ERR_RETRY;

View File

@ -150,6 +150,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.
*/

View File

@ -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 "20111224"
#define MAIL_RELEASE_DATE "20111230"
#define MAIL_VERSION_NUMBER "2.9"
#ifdef SNAPSHOT

View File

@ -194,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;
}
}

View File

@ -1,6 +1,7 @@
unknown: dict_open: fail:1maps
unknown: dict_register: fail:1maps(0,lock) 1
"": not found
unknown: warning: fail:1maps lookup of foobar failed
unknown: maps_find: whatever: foobar: search aborted
"foobar": lookup error
unknown: maps_free: fail:1maps(0,lock)

View File

@ -40,7 +40,7 @@ foo/168.100.189.3: NO
bar/168.100.189.3: NO
foo/168.100.189.3: YES
bar/168.100.189.3: NO
./namadr_list: warning: fail:1(0,lock|fold_fix): table lookup problem
./namadr_list: warning: fail:1: table lookup problem
bar/168.100.189.3: ERROR
./namadr_list: warning: fail:1(0,lock|fold_fix): table lookup problem
./namadr_list: warning: fail:1: table lookup problem
bar/168.100.189.3: ERROR

View File

@ -1,6 +1,6 @@
mydestination=example.com destination=example.com YES
mydestination=example.net destination=example.com NO
unknown: warning: fail:1_resolve_local(0,lock|fold_fix): table lookup problem
unknown: warning: fail:1_resolve_local: table lookup problem
mydestination=fail:1_resolve_local destination=example.com ERROR
mydestination=fail:1_resolve_local destination=example.com.. NO
mydestination=fail:1_resolve_local destination= NO

View File

@ -9,7 +9,7 @@
168.100.189.3: permit
> mynetworks=fail:1
> address=168.100.189.4
unknown: warning: fail:1(0,lock|fold_fix): table lookup problem
unknown: warning: fail:1: table lookup problem
unknown: warning: server_acl: permit_mynetworks: mynetworks lookup error -- ignoring the remainder of this access list
168.100.189.4: error
> server_acl=fail:1,reject

View File

@ -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) {
@ -303,15 +304,15 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp)
* Skip delivery when this recipient does not exist.
*/
if ((errno = mypwnam_err(state.msg_attr.user, &mbox_pwd)) != 0) {
msg_warn("error looking up passwd info for %s: %m",
state.msg_attr.user);
dsb_simple(state.msg_attr.why, "4.0.0", "user lookup error");
*statusp = defer_append(BOUNCE_FLAGS(state.request),
BOUNCE_ATTR(state.msg_attr));
return (YES);
msg_warn("error looking up passwd info for %s: %m",
state.msg_attr.user);
dsb_simple(state.msg_attr.why, "4.0.0", "user lookup error");
*statusp = defer_append(BOUNCE_FLAGS(state.request),
BOUNCE_ATTR(state.msg_attr));
return (YES);
}
if (mbox_pwd == 0)
return (NO);
return (NO);
/*
* No early returns or we have a memory leak.
@ -341,7 +342,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) == '/') {

View File

@ -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;

View File

@ -714,10 +714,11 @@ int main(int argc, char **argv)
VAR_RCPT_CANON_MAPS, DEF_RCPT_CANON_MAPS, &var_rcpt_canon_maps, 0, 0,
VAR_RELOCATED_MAPS, DEF_RELOCATED_MAPS, &var_relocated_maps, 0, 0,
VAR_TRANSPORT_MAPS, DEF_TRANSPORT_MAPS, &var_transport_maps, 0, 0,
VAR_PROXY_READ_MAPS, DEF_PROXY_READ_MAPS, &var_proxy_read_maps, 0, 0,
VAR_PROXY_WRITE_MAPS, DEF_PROXY_WRITE_MAPS, &var_proxy_write_maps, 0, 0,
VAR_VERIFY_MAP, DEF_VERIFY_MAP, &var_verify_map, 0, 0,
VAR_PSC_CACHE_MAP, DEF_PSC_CACHE_MAP, &var_psc_cache_map, 0, 0,
/* The following two must be last for $mapname to work as expected. */
VAR_PROXY_READ_MAPS, DEF_PROXY_READ_MAPS, &var_proxy_read_maps, 0, 0,
VAR_PROXY_WRITE_MAPS, DEF_PROXY_WRITE_MAPS, &var_proxy_write_maps, 0, 0,
0,
};

View File

@ -1264,22 +1264,22 @@ static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs)
prints[0] = state->tls_context->peer_fingerprint;
prints[1] = state->tls_context->peer_pkey_fprint;
/* After lookup error, leave dict_errno at its non-zero value. */
for (i = 0; i < 2 && found == 0 && dict_errno == 0; ++i)
/* After lookup error, leave dict_errno at non-zero value. */
for (i = 0; i < 2; ++i) {
found = maps_find(relay_ccerts, prints[i], DICT_FLAG_NONE);
if (found) {
if (msg_verbose)
msg_info("Relaying allowed for certified client: %s", found);
return (SMTPD_CHECK_OK);
} else if (dict_errno != 0) {
msg_warn("relay_clientcerts: lookup error for fingerprint '%s', "
"pkey fingerprint %s", prints[0], prints[1]);
return (SMTPD_CHECK_ERROR);
} else {
if (msg_verbose)
msg_info("relay_clientcerts: No match for fingerprint '%s', "
if (found != 0) {
if (msg_verbose)
msg_info("Relaying allowed for certified client: %s", found);
return (SMTPD_CHECK_OK);
} else if (dict_errno != 0) {
msg_warn("relay_clientcerts: lookup error for fingerprint '%s', "
"pkey fingerprint %s", prints[0], prints[1]);
return (SMTPD_CHECK_ERROR);
}
}
if (msg_verbose)
msg_info("relay_clientcerts: No match for fingerprint '%s', "
"pkey fingerprint %s", prints[0], prints[1]);
}
#else
dict_errno = 0;

View File

@ -57,7 +57,7 @@ OK
>>> recipient_restrictions permit_mynetworks
OK
>>> rcpt reject@dunno.domain
./smtpd_check: warning: fail:1_mynetworks(0,lock|fold_fix): table lookup problem
./smtpd_check: warning: fail:1_mynetworks: table lookup problem
./smtpd_check: <queue id>: reject: RCPT from foo.dunno.com[131.155.210.17]: 451 4.3.0 <reject@dunno.domain>: Temporary lookup failure; from=<reject@dunno.domain> to=<reject@dunno.domain> proto=SMTP helo=<foobar>
451 4.3.0 <reject@dunno.domain>: Temporary lookup failure
>>> #
@ -91,6 +91,7 @@ OK
>>> recipient_restrictions permit_tls_clientcerts
OK
>>> rcpt reject@dunno.domain
./smtpd_check: warning: fail:1_certs lookup of abcdef failed
./smtpd_check: warning: relay_clientcerts: lookup error for fingerprint 'abcdef', pkey fingerprint abcdef
./smtpd_check: <queue id>: reject: RCPT from foo.dunno.com[131.155.210.17]: 451 4.3.0 <reject@dunno.domain>: Temporary lookup failure; from=<> to=<reject@dunno.domain> proto=SMTP helo=<foobar>
451 4.3.0 <reject@dunno.domain>: Temporary lookup failure
@ -118,7 +119,7 @@ OK
>>> mydestination fail:1_mydestination
OK
>>> rcpt user@example.com
./smtpd_check: warning: fail:1_mydestination(0,lock|fold_fix): table lookup problem
./smtpd_check: warning: fail:1_mydestination: table lookup problem
./smtpd_check: <queue id>: reject: RCPT from foo.dunno.com[131.155.210.17]: 451 4.3.0 <user@example.com>: Temporary lookup failure; from=<> to=<user@example.com> proto=SMTP helo=<foobar>
451 4.3.0 <user@example.com>: Temporary lookup failure
>>> #
@ -129,5 +130,6 @@ OK
>>> virtual_alias_maps fail:1_virtual
OK
>>> rcpt user@example.com
./smtpd_check: warning: fail:1_virtual lookup of user@example.com failed
./smtpd_check: <queue id>: reject: RCPT from foo.dunno.com[131.155.210.17]: 451 4.3.0 <user@example.com>: Temporary lookup failure; from=<> to=<user@example.com> proto=SMTP helo=<foobar>
451 4.3.0 <user@example.com>: Temporary lookup failure

View File

@ -379,8 +379,10 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr,
rcpt_domain = strrchr(STR(nextrcpt), '@') + 1;
if (resolve_local(rcpt_domain)) /* XXX */
domain = 0;
else if (dict_errno != 0)
else if (dict_errno != 0) {
*flags |= RESOLVE_FLAG_FAIL;
FREE_MEMORY_AND_RETURN;
}
} else {
*flags |= RESOLVE_FLAG_ERROR;
}

View File

@ -253,12 +253,19 @@ const char *dict_cache_lookup(DICT_CACHE *cp, const char *cache_key)
if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE)
msg_info("%s: key=%s (pretend not found - scheduled for deletion)",
myname, cache_key);
dict_errno = 0;
return (0);
} else {
cache_val = dict_get(cp->db, cache_key);
#if 0
if (cache_val == 0 && dict_errno != 0)
msg_warn("%s: cache lookup for '%s' failed due to error",
cp->name, cache_key);
#endif
if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE)
msg_info("%s: key=%s value=%s", myname, cache_key,
cache_val ? cache_val : "(not found)");
cache_val ? cache_val : dict_errno ?
"error" : "(not found)");
return (cache_val);
}
}
@ -304,6 +311,10 @@ int dict_cache_delete(DICT_CACHE *cp, const char *cache_key)
zero_means_found = 0;
} else {
zero_means_found = dict_del(cp->db, cache_key);
#if 0
if (zero_means_found != 0)
msg_warn("%s: could not delete entry for %s", cp->name, cache_key);
#endif
if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE)
msg_info("%s: key=%s (%s)", myname, cache_key,
zero_means_found == 0 ? "found" : "not found");
@ -366,7 +377,7 @@ int dict_cache_sequence(DICT_CACHE *cp, int first_next,
msg_info("%s: delete-behind key=%s value=%s",
myname, previous_curr_key, previous_curr_val);
if (dict_del(cp->db, previous_curr_key) != 0)
msg_warn("database %s: could not delete entry for %s",
msg_warn("%s: could not delete entry for %s",
cp->name, previous_curr_key);
}
@ -465,6 +476,13 @@ static void dict_cache_clean_event(int unused_event, char *cache_context)
/*
* Cache cleanup completed. Report vital statistics.
*/
#if 0
else if (dict_errno != 0) {
msg_warn("%s: cache cleanup scan failed due to error", cp->name);
dict_cache_clean_stat_log_reset(cp, "partial");
next_interval = cp->exp_interval;
}
#endif
else {
if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE)
msg_info("%s: done %s cache cleanup scan", myname, cp->name);

View File

@ -96,6 +96,8 @@ static int dict_thash_sequence(DICT *dict, int function,
const char *myname = "dict_thash_sequence";
DICT_THASH *dict_thash = (DICT_THASH *) dict;
dict_errno = 0;
/*
* Determine and execute the seek function.
*/

View File

@ -143,6 +143,7 @@ static ARGV *match_list_parse(ARGV *list, char *string, int init_match)
vstring_sprintf(buf, "%s%s(%o,%s)", match ? "" : "!",
item, OPEN_FLAGS, dict_flags_str(DICT_FLAGS));
map_type_name_flags = STR(buf) + (match == 0);
/* XXX Should increment existing map refcount. */
if (dict_handle(map_type_name_flags) == 0)
dict_register(map_type_name_flags,
dict_open(item, OPEN_FLAGS, DICT_FLAGS));
@ -228,6 +229,7 @@ int match_list_match(MATCH_LIST *list,...)
void match_list_free(MATCH_LIST *list)
{
/* XXX Should decrement map refcounts. */
argv_free(list->patterns);
myfree((char *) list->match_func);
myfree((char *) list->match_args);

View File

@ -111,7 +111,7 @@ static int match_error(int flags, const char *fmt,...)
int match_string(int flags, const char *string, const char *pattern)
{
const char *myname = "match_string";
int match;
DICT *dict;
if (msg_verbose)
msg_info("%s: %s ~? %s", myname, string, pattern);
@ -120,11 +120,13 @@ int match_string(int flags, const char *string, const char *pattern)
* Try dictionary lookup: exact match.
*/
if (MATCH_DICTIONARY(pattern)) {
match = (dict_lookup(pattern, string) != 0);
if (match != 0)
if ((dict = dict_handle(pattern)) == 0)
msg_panic("%s: unknown dictionary: %s", myname, pattern);
if (dict_get(dict, string) != 0)
return (1);
if (dict_errno != 0)
return (match_error(flags, "%s: table lookup problem", pattern));
return (match_error(flags, "%s:%s: table lookup problem",
dict->type, dict->name));
return (0);
}
@ -174,8 +176,8 @@ int match_hostname(int flags, const char *name, const char *pattern)
if (match != 0)
break;
if (dict_errno != 0)
return (match_error(flags, "%s: table lookup problem",
pattern));
return (match_error(flags, "%s:%s: table lookup problem",
dict->type, dict->name));
}
if ((next = strchr(entry + 1, '.')) == 0)
break;
@ -216,6 +218,7 @@ int match_hostaddr(int flags, const char *addr, const char *pattern)
const char *myname = "match_hostaddr";
char *saved_patt;
CIDR_MATCH match_info;
DICT *dict;
VSTRING *err;
int rc;
@ -232,10 +235,13 @@ int match_hostaddr(int flags, const char *addr, const char *pattern)
* Try dictionary lookup. This can be case insensitive.
*/
if (MATCH_DICTIONARY(pattern)) {
if (dict_lookup(pattern, addr) != 0)
if ((dict = dict_handle(pattern)) == 0)
msg_panic("%s: unknown dictionary: %s", myname, pattern);
if (dict_get(dict, addr) != 0)
return (1);
if (dict_errno != 0)
return (match_error(flags, "%s: table lookup problem", pattern));
return (match_error(flags, "%s:%s: table lookup problem",
dict->type, dict->name));
return (0);
}
@ -290,9 +296,9 @@ int match_hostaddr(int flags, const char *addr, const char *pattern)
err = cidr_match_parse(&match_info, saved_patt, (VSTRING *) 0);
myfree(saved_patt);
if (err != 0) {
dict_errno = DICT_ERR_CONFIG;
rc = match_error(flags, "%s", vstring_str(err));
vstring_free(err);
dict_errno = DICT_ERR_CONFIG;
return (rc);
}
return (cidr_match_execute(&match_info, addr) != 0);