operation, to avoid logging large numbers of warnings about
a problem with low-value information. File: util/msg_rate_delay.c,
util/dict_cache.c.
+
+20120110
+
+ Cleanup: added logging for failed table lookups and replaced
+ some "fatal" errors by warnings. Files: cleanup/cleanup_addr.c,
+ cleanup/cleanup_message.c, cleanup/cleanup_milter.c,
+ cleanup/cleanup_masquerade.c, global/header_body_checks.c,
+ global/smtp_stream.c, postscreen/postscreen_dnsbl.c,
+ postscreen/postscreen_smtpd.c, smtp/smtp_chat.c,
+ smtp/smtp_proto.c, smtp/smtp_sasl_auth_cache.c,
+ smtp/smtp_sasl_glue.c, smtp/smtp_session.c, smtp/smtp_trouble.c,
+ smtpd/smtpd.c, smtpd/smtpd_check.c.
If you upgrade from Postfix 2.7 or earlier, read RELEASE_NOTES-2.8
before proceeding.
+Major changes with snapshot 20111208
+====================================
+
+The LDAP, *SQL and memcache clients now "catch" table lookup errors
+in the "domain" feature, instead of terminating with a fatal error.
+
+Major changes with snapshot 20111202
+====================================
+
+Degrade gracefully when some or all network protocols specified
+with inet_protocols are unavailable, instead of terminating with a
+fatal error. This eliminates build errors on non-standard systems
+where opening an IPv4 socket results in an error, and on non-standard
+systems where opening an IPv6 socket results in an error. In the
+worst case, the master daemon will log a message that it disables
+all type "inet" services. This will still allow local submission
+and local delivery.
+
+Major changes with snapshot 20111222
+====================================
+
+The Postfix SMTP server now "catches" errors with database lookups
+in mynetworks, TLS client certificate tables, debug_peer_list,
+smtpd_client_event_limit_exceptions, permit_mx_backup_networks and
+local_header_rewrite_clients, and reports "server configuration
+error" or "table lookup error" instead of terminating with a fatal
+error.
+
+Major changes with snapshot 20111229
+====================================
+
+The trivial-rewrite server now "catches" errors with database lookups
+in virtual_alias_domains, relay_domains, virtual_mailbox_domains,
+instead of terminating with a fatal error. This means fewer occasions
+where trivial-rewrite clients (such as the SMTP server) will appear
+to hang.
+
Incompatible changes with snapshot 20111218
===========================================
Support for external SASL authentication via the XCLIENT command.
This is used to accept SASL authentication from an SMTP proxy such
-as nginx. This support works even without having to specify
+as NGINX. This support works even without having to specify
"smtpd_sasl_auth_enable = yes" in main.cf.
Major changes with snapshot 20111213
Remove this file from the stable release.
+ In daemons, open surrogate map when real map is unavailable,
+ effectively redirecting to fail:.
+
Things to do after the stable release:
Before proxymap can be exposed to the network to share,
./cleanup_masquerade '' !a.b.c,b.c xxx@a.b.c >>cleanup_masq.tmp
./cleanup_masquerade '' a.b.c,b.c xxx@aaa.b.c >>cleanup_masq.tmp
./cleanup_masquerade '' a.b.c,b.c xxx@b.c >>cleanup_masq.tmp
+ ./cleanup_masquerade 'fail:whatever' xy xxx@b.c >>cleanup_masq.tmp
diff cleanup_masq.ref cleanup_masq.tmp
rm -f cleanup_masq.tmp
/*
* cleanup_masquerade.c
*/
-extern int cleanup_masquerade_external(VSTRING *, ARGV *);
-extern int cleanup_masquerade_internal(VSTRING *, ARGV *);
-extern int cleanup_masquerade_tree(TOK822 *, ARGV *);
+extern int cleanup_masquerade_external(CLEANUP_STATE *, VSTRING *, ARGV *);
+extern int cleanup_masquerade_internal(CLEANUP_STATE *, VSTRING *, ARGV *);
+extern int cleanup_masquerade_tree(CLEANUP_STATE *, TOK822 *, ARGV *);
/*
* cleanup_recipient.c
cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
if (cleanup_masq_domains
&& (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_FROM))
- cleanup_masquerade_internal(clean_addr, cleanup_masq_domains);
+ cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains);
}
CLEANUP_OUT_BUF(state, REC_TYPE_FROM, clean_addr);
if (state->sender) /* XXX Can't happen */
state->sender = mystrdup(STR(clean_addr)); /* Used by Milter client */
if ((state->flags & CLEANUP_FLAG_BCC_OK)
&& *STR(clean_addr)
- && cleanup_send_bcc_maps
- && (bcc = mail_addr_find(cleanup_send_bcc_maps, STR(clean_addr),
- IGNORE_EXTENSION)) != 0)
- cleanup_addr_bcc(state, bcc);
+ && cleanup_send_bcc_maps) {
+ if ((bcc = mail_addr_find(cleanup_send_bcc_maps, STR(clean_addr),
+ IGNORE_EXTENSION)) != 0) {
+ cleanup_addr_bcc(state, bcc);
+ } else if (cleanup_send_bcc_maps->error) {
+ msg_warn("%s: %s lookup problem",
+ state->queue_id, cleanup_send_bcc_maps->title);
+ state->errs |= CLEANUP_STAT_WRITE;
+ }
+ }
vstring_free(clean_addr);
}
cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
if (cleanup_masq_domains
&& (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT))
- cleanup_masquerade_internal(clean_addr, cleanup_masq_domains);
+ cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains);
}
cleanup_out_recipient(state, state->dsn_orcpt, state->dsn_notify,
state->orig_rcpt, STR(clean_addr));
state->recip = mystrdup(STR(clean_addr)); /* Used by Milter client */
if ((state->flags & CLEANUP_FLAG_BCC_OK)
&& *STR(clean_addr)
- && cleanup_rcpt_bcc_maps
- && (bcc = mail_addr_find(cleanup_rcpt_bcc_maps, STR(clean_addr),
- IGNORE_EXTENSION)) != 0)
- cleanup_addr_bcc(state, bcc);
+ && cleanup_rcpt_bcc_maps) {
+ if ((bcc = mail_addr_find(cleanup_rcpt_bcc_maps, STR(clean_addr),
+ IGNORE_EXTENSION)) != 0) {
+ cleanup_addr_bcc(state, bcc);
+ } else if (cleanup_rcpt_bcc_maps->error) {
+ msg_warn("%s: %s lookup problem",
+ state->queue_id, cleanup_rcpt_bcc_maps->title);
+ state->errs |= CLEANUP_STAT_WRITE;
+ }
+ }
vstring_free(clean_addr);
}
/* cleanup_addr_bcc_dsn - process automatic BCC recipient */
void cleanup_addr_bcc_dsn(CLEANUP_STATE *state, const char *bcc,
- const char *dsn_orcpt, int dsn_notify)
+ const char *dsn_orcpt, int dsn_notify)
{
VSTRING *clean_addr = vstring_alloc(100);
cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
if (cleanup_masq_domains
&& (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT))
- cleanup_masquerade_internal(clean_addr, cleanup_masq_domains);
+ cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains);
}
cleanup_out_recipient(state, dsn_orcpt, dsn_notify,
STR(clean_addr), STR(clean_addr));
maps_create(VAR_BODY_CHECKS, var_body_checks, DICT_FLAG_LOCK);
if (*var_masq_exceptions)
cleanup_masq_exceptions =
- string_list_init(MATCH_FLAG_NONE, var_masq_exceptions);
+ string_list_init(MATCH_FLAG_RETURN, var_masq_exceptions);
if (*var_masq_classes)
cleanup_masq_flags = name_mask(VAR_MASQ_CLASSES, masq_class_table,
var_masq_classes);
masq_list: a.b.c,b.c
address: xxx@aa.a.b.c
result: xxx@a.b.c
+errs: 0
----------
exceptions: xxx
masq_list: a.b.c,b.c
address: xxx@aa.a.b.c
result: xxx@aa.a.b.c
+errs: 0
----------
exceptions: yyy
masq_list: a.b.c,b.c
address: xxx@aa.a.b.c
result: xxx@a.b.c
+errs: 0
----------
exceptions:
masq_list: !a.b.c,b.c
address: xxx@aa.a.b.c
result: xxx@aa.a.b.c
+errs: 0
----------
exceptions:
masq_list: a.b.c,b.c
address: xxx@a.b.c
result: xxx@a.b.c
+errs: 0
----------
exceptions:
masq_list: !a.b.c,b.c
address: xxx@a.b.c
result: xxx@a.b.c
+errs: 0
----------
exceptions:
masq_list: a.b.c,b.c
address: xxx@aaa.b.c
result: xxx@b.c
+errs: 0
----------
exceptions:
masq_list: a.b.c,b.c
address: xxx@b.c
result: xxx@b.c
+errs: 0
+----------
+exceptions: fail:whatever
+masq_list: xy
+address: xxx@b.c
+result: xxx@b.c
+errs: 2
/* cleanup_masquerade_external - masquerade address external form */
-int cleanup_masquerade_external(VSTRING *addr, ARGV *masq_domains)
+int cleanup_masquerade_external(CLEANUP_STATE *state, VSTRING *addr,
+ ARGV *masq_domains)
{
char *domain;
ssize_t domain_len;
name = mystrndup(STR(addr), domain - 1 - STR(addr));
excluded = (string_list_match(cleanup_masq_exceptions, lowercase(name)) != 0);
myfree(name);
+ if (cleanup_masq_exceptions->error) {
+ msg_info("%s: %s lookup error -- deferring delivery",
+ state->queue_id, VAR_MASQ_EXCEPTIONS);
+ state->errs |= CLEANUP_STAT_WRITE;
+ }
if (excluded)
return (0);
}
/* cleanup_masquerade_tree - masquerade address node */
-int cleanup_masquerade_tree(TOK822 *tree, ARGV *masq_domains)
+int cleanup_masquerade_tree(CLEANUP_STATE *state, TOK822 *tree,
+ ARGV *masq_domains)
{
VSTRING *temp = vstring_alloc(100);
int did_rewrite;
tok822_externalize(temp, tree->head, TOK822_STR_DEFL);
- did_rewrite = cleanup_masquerade_external(temp, masq_domains);
+ did_rewrite = cleanup_masquerade_external(state, temp, masq_domains);
tok822_free_tree(tree->head);
tree->head = tok822_scan(STR(temp), &tree->tail);
/* cleanup_masquerade_internal - masquerade address internal form */
-int cleanup_masquerade_internal(VSTRING *addr, ARGV *masq_domains)
+int cleanup_masquerade_internal(CLEANUP_STATE *state, VSTRING *addr,
+ ARGV *masq_domains)
{
VSTRING *temp = vstring_alloc(100);
int did_rewrite;
quote_822_local(temp, STR(addr));
- did_rewrite = cleanup_masquerade_external(temp, masq_domains);
+ did_rewrite = cleanup_masquerade_external(state, temp, masq_domains);
unquote_822_local(addr, STR(temp));
vstring_free(temp);
{
VSTRING *addr;
ARGV *masq_domains;
+ CLEANUP_STATE state;
if (argc != 4)
msg_fatal("usage: %s exceptions masquerade_list address", argv[0]);
var_masq_exceptions = argv[1];
cleanup_masq_exceptions =
- string_list_init(MATCH_FLAG_NONE, var_masq_exceptions);
+ string_list_init(MATCH_FLAG_RETURN, var_masq_exceptions);
masq_domains = argv_split(argv[2], " ,\t\r\n");
addr = vstring_alloc(1);
if (strchr(argv[3], '@') == 0)
vstream_printf("masq_list: %s\n", argv[2]);
vstream_printf("address: %s\n", argv[3]);
- cleanup_masquerade_external(addr, masq_domains);
+ state.errs = 0;
+ cleanup_masquerade_external(&state, addr, masq_domains);
vstream_printf("result: %s\n", STR(addr));
+ vstream_printf("errs: %d\n", state.errs);
vstream_fflush(VSTREAM_OUT);
vstring_free(addr);
if (cleanup_masq_domains
&& (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_FROM))
did_rewrite |=
- cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
+ cleanup_masquerade_tree(state, *tpp, cleanup_masq_domains);
}
}
if (did_rewrite) {
if (cleanup_masq_domains
&& (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_RCPT))
did_rewrite |=
- cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
+ cleanup_masquerade_tree(state, *tpp, cleanup_masq_domains);
}
}
if (did_rewrite) {
hdr_opts = header_opts_find(result);
myfree((char *) result);
}
+ } else if (checks->error) {
+ msg_warn("%s: %s map lookup problem -- deferring delivery",
+ state->queue_id, checks->title);
+ state->errs |= CLEANUP_STAT_WRITE;
}
}
myfree((char *) result);
return;
}
+ } else if (cleanup_body_checks->error) {
+ msg_warn("%s: %s map lookup problem -- deferring delivery",
+ state->queue_id, cleanup_body_checks->title);
+ state->errs |= CLEANUP_STAT_WRITE;
}
}
cleanup_out(state, type, buf, len);
buf, (off_t) 0);
if (ret == 0) {
return (0);
+ } else if (ret == HBC_CHECKS_STAT_ERROR) {
+ msg_warn("%s: %s lookup error -- deferring delivery",
+ state->queue_id, VAR_MILT_HEAD_CHECKS);
+ state->errs |= CLEANUP_STAT_WRITE;
+ return (0);
} else {
if (ret != STR(buf)) {
vstring_strcpy(buf, ret);
return (path);
}
-/* flush_policy_ok - check logging policy */
-
-static int flush_policy_ok(const char *site)
-{
- return (domain_list_match(flush_domains, site));
-}
-
/* flush_add_service - append queue ID to per-site fast flush logfile */
static int flush_add_service(const char *site, const char *queue_id)
/*
* If this site is not eligible for logging, deny the request.
*/
- if (flush_policy_ok(site) == 0)
- return (FLUSH_STAT_DENY);
+ if (domain_list_match(flush_domains, site) == 0)
+ return (flush_domains->error ? FLUSH_STAT_FAIL : FLUSH_STAT_DENY);
/*
* Map site to path and update log.
/*
* If this site is not eligible for logging, deny the request.
*/
- if (flush_policy_ok(site) == 0)
- return (FLUSH_STAT_DENY);
+ if (domain_list_match(flush_domains, site) == 0)
+ return (flush_domains->error ? FLUSH_STAT_FAIL : FLUSH_STAT_DENY);
/*
* Map site name to path name and flush the log.
DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, DICT_STAT_FAIL);
} else {
seq_res = backup->sequence(backup, function, key, value);
- msg_info("%s: %s: key \"%s\" => %s",
- myname, dict_mc->dict.name, *key ? *key : "(not found)",
- *value ? *value : backup->error ? "(backup error)" :
- "(not found)");
+ if (msg_verbose)
+ msg_info("%s: %s: key \"%s\" => %s",
+ myname, dict_mc->dict.name, *key ? *key : "(not found)",
+ *value ? *value : backup->error ? "(backup error)" :
+ "(not found)");
DICT_ERR_VAL_RETURN(dict, backup->error, seq_res);
}
}
/* not be called.
/*
/* hbc_header_checks() inspects the specified logical header.
-/* The result is either the original header, HBC_CHECK_STAT_IGNORE
-/* (meaning: discard the header) or a new header (meaning:
-/* replace the header and destroy the new header with myfree()).
+/* The result is either the original header, HBC_CHECKS_STAT_IGNORE
+/* (meaning: discard the header), HBC_CHECKS_STAT_ERROR, or a
+/* new header (meaning: replace the header and destroy the new
+/* header with myfree()).
/*
/* hbc_header_checks_free() returns memory to the pool.
/*
-/* hbc_body_checks_create(), dbhc_body_checks(), dbhc_body_free()
+/* hbc_body_checks_create(), hbc_body_checks(), hbc_body_free()
/* perform similar functions for body lines.
/*
/* Arguments:
* Something that is guaranteed to be different from a real string result
* from header/body_checks.
*/
+char hbc_checks_error;
const char hbc_checks_unknown;
/*
return (hbc_action(context, hbc->call_backs,
mp->map_class, HBC_CTXT_HEADER, action,
STR(header), LEN(header), offset));
+ } else if (mp->maps && mp->maps->error) {
+ return (HBC_CHECKS_STAT_ERROR);
} else {
return (STR(header));
}
return (hbc_action(context, hbc->call_backs,
mp->map_class, HBC_CTXT_BODY, action,
line, len, offset));
+ } else if (mp->maps->error) {
+ return (HBC_CHECKS_STAT_ERROR);
} else {
return ((char *) line);
}
} HBC_CHECKS;
#define HBC_CHECKS_STAT_IGNORE ((char *) 0)
+#define HBC_CHECKS_STAT_ERROR (&hbc_checks_error)
#define HBC_CHECKS_STAT_UNKNOWN (&hbc_checks_unknown)
extern HBC_CHECKS *hbc_header_checks_create(const char *, const char *,
*/
#define HBC_HEADER_SIZE (MIME_HDR_LAST - MIME_HDR_FIRST + 1)
extern void _hbc_checks_free(HBC_CHECKS *, ssize_t);
+extern char hbc_checks_error;
extern const char hbc_checks_unknown;
/* LICENSE
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20120108"
+#define MAIL_RELEASE_DATE "20120110"
#define MAIL_VERSION_NUMBER "2.9"
#ifdef SNAPSHOT
maps = (MAPS *) mymalloc(sizeof(*maps));
maps->title = mystrdup(title);
maps->argv = argv_alloc(2);
+ maps->error = 0;
/*
* For each specified type:name pair, either register a new dictionary,
*map_name, name, expansion);
return (expansion);
} else if ((maps->error = dict->error) != 0) {
- msg_warn("%s:%s lookup of %s failed", dict->type, dict->name, name);
+ msg_warn("%s:%s lookup error for \"%.100s\"",
+ dict->type, dict->name, name);
break;
}
}
/* the application.
/* This error is never generated by the smtp_stream(3) module, but
/* is defined for application-specific use.
+/* .IP SMTP_ERR_APPL
+/* Application error - the program cannot proceed with this
+/* SMTP session.
/* .IP SMTP_ERR_NONE
/* A non-error code that makes setjmp()/longjmp() convenient
/* to use.
#define SMTP_ERR_TIME 2 /* time out */
#define SMTP_ERR_QUIET 3 /* silent cleanup (application) */
#define SMTP_ERR_NONE 4 /* non-error case */
+#define SMTP_ERR_APPL 5 /* application error - can't proceed */
extern void smtp_stream_setup(VSTREAM *, int, int);
extern void PRINTFLIKE(2, 3) smtp_printf(VSTREAM *, const char *,...);
unknown.o: ../../include/attr.h
unknown.o: ../../include/been_here.h
unknown.o: ../../include/bounce.h
+unknown.o: ../../include/defer.h
unknown.o: ../../include/deliver_pass.h
unknown.o: ../../include/deliver_request.h
unknown.o: ../../include/delivered_hdr.h
#include <mail_addr.h>
#include <sent.h>
#include <deliver_pass.h>
+#include <defer.h>
/* Application-specific. */
-postalias: fatal: fail:aliases: query error: Unknown error: 0
-postalias: fatal: fail:aliases: query error: Unknown error: 0
-postalias: fatal: fail:aliases: delete error: Unknown error: 0
-postalias: fatal: fail:aliases: delete error: Unknown error: 0
-postalias: fatal: fail:aliases: sequence error: Unknown error: 0
-postalias: fatal: fail:aliases: write error: Unknown error: 0
-postalias: fatal: fail:aliases: write error: Unknown error: 0
+postalias: fatal: table fail:aliases: query error: Unknown error: 0
+postalias: fatal: table fail:aliases: query error: Unknown error: 0
+postalias: fatal: table fail:aliases: delete error: Unknown error: 0
+postalias: fatal: table fail:aliases: delete error: Unknown error: 0
+postalias: fatal: table fail:aliases: sequence error: Unknown error: 0
+postalias: fatal: table fail:aliases: write error: Unknown error: 0
+postalias: fatal: table fail:aliases: write error: Unknown error: 0
*/
mkmap_append(mkmap, STR(key_buffer), STR(value_buffer));
if (mkmap->dict->error)
- msg_fatal("%s:%s: write error: %m",
+ msg_fatal("table %s:%s: write error: %m",
mkmap->dict->type, mkmap->dict->name);
}
*/
mkmap_append(mkmap, "@", "@");
if (mkmap->dict->error)
- msg_fatal("%s:%s: write error: %m",
+ msg_fatal("table %s:%s: write error: %m",
mkmap->dict->type, mkmap->dict->name);
/*
break;
}
if (dicts[n]->error)
- msg_fatal("%s:%s: query error: %m",
+ msg_fatal("table %s:%s: query error: %m",
dicts[n]->type, dicts[n]->name);
}
}
vstream_printf("%s\n", value);
}
if (dict->error)
- msg_fatal("%s:%s: query error: %m", dict->type, dict->name);
+ msg_fatal("table %s:%s: query error: %m", dict->type, dict->name);
vstream_fflush(VSTREAM_OUT);
dict_close(dict);
return (value != 0);
while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF) {
for (n = 0; n < map_count; n++) {
found |= (dict_del(dicts[n], STR(keybuf)) == 0);
- if (dicts[n]->error)
- msg_fatal("%s:%s: delete error: %m",
- dicts[n]->type, dicts[n]->name);
- }
+ if (dicts[n]->error)
+ msg_fatal("table %s:%s: delete error: %m",
+ dicts[n]->type, dicts[n]->name);
+ }
}
/*
dict = dict_open3(map_type, map_name, open_flags, dict_flags);
status = dict_del(dict, key);
if (dict->error)
- msg_fatal("%s:%s: delete error: %m", dict->type, dict->name);
+ msg_fatal("table %s:%s: delete error: %m", dict->type, dict->name);
dict_close(dict);
return (status == 0);
}
vstream_printf("%s: %s\n", key, value);
}
if (dict->error)
- msg_fatal("%s:%s: sequence error: %m", dict->type, dict->name);
+ msg_fatal("table %s:%s: sequence error: %m", dict->type, dict->name);
vstream_fflush(VSTREAM_OUT);
dict_close(dict);
}
./postmap -q xx fail:aliases
echo xx | ./postmap -q - fail:aliases
+echo xx | ./postmap -bq - fail:aliases
./postmap -d xx fail:aliases
echo xx | ./postmap -d - fail:aliases
./postmap -s fail:aliases
-postmap: fatal: fail:aliases: query error: Unknown error: 0
-postmap: fatal: fail:aliases: query error: Unknown error: 0
-postmap: fatal: fail:aliases: delete error: Unknown error: 0
-postmap: fatal: fail:aliases: delete error: Unknown error: 0
-postmap: fatal: fail:aliases: sequence error: Unknown error: 0
-postmap: fatal: fail:aliases: write error: Unknown error: 0
-postmap: fatal: fail:aliases: write error: Unknown error: 0
+postmap: fatal: table fail:aliases: query error: Unknown error: 0
+postmap: fatal: table fail:aliases: query error: Unknown error: 0
+postmap: fatal: table fail:aliases: query error: Unknown error: 0
+postmap: fatal: table fail:aliases: delete error: Unknown error: 0
+postmap: fatal: table fail:aliases: delete error: Unknown error: 0
+postmap: fatal: table fail:aliases: sequence error: Unknown error: 0
+postmap: fatal: table fail:aliases: write error: Unknown error: 0
+postmap: fatal: table fail:aliases: write error: Unknown error: 0
*/
mkmap_append(mkmap, key, value);
if (mkmap->dict->error)
- msg_fatal("%s:%s: write error: %m",
+ msg_fatal("table %s:%s: write error: %m",
mkmap->dict->type, mkmap->dict->name);
}
break;
}
if (dicts[n]->error)
- msg_fatal("%s:%s: query error: %m",
+ msg_fatal("table %s:%s: query error: %m",
dicts[n]->type, dicts[n]->name);
}
}
break;
}
if (dicts[n]->error)
- msg_fatal("%s:%s: query error: %m",
+ msg_fatal("table %s:%s: query error: %m",
dicts[n]->type, dicts[n]->name);
}
}
vstream_printf("%s\n", value);
}
if (dict->error)
- msg_fatal("%s:%s: query error: %m", dict->type, dict->name);
+ msg_fatal("table %s:%s: query error: %m", dict->type, dict->name);
vstream_fflush(VSTREAM_OUT);
dict_close(dict);
return (value != 0);
for (n = 0; n < map_count; n++) {
found |= (dict_del(dicts[n], STR(keybuf)) == 0);
if (dicts[n]->error)
- msg_fatal("%s:%s: delete error: %m",
+ msg_fatal("table %s:%s: delete error: %m",
dicts[n]->type, dicts[n]->name);
}
}
dict = dict_open3(map_type, map_name, open_flags, dict_flags);
status = dict_del(dict, key);
if (dict->error)
- msg_fatal("%s:%s: delete error: %m", dict->type, dict->name);
+ msg_fatal("table %s:%s: delete error: %m", dict->type, dict->name);
dict_close(dict);
return (status == 0);
}
vstream_printf("%s %s\n", key, value);
}
if (dict->error)
- msg_fatal("%s:%s: sequence error: %m", dict->type, dict->name);
+ msg_fatal("table %s:%s: sequence error: %m", dict->type, dict->name);
vstream_fflush(VSTREAM_OUT);
dict_close(dict);
}
if (psc_dnsbl_reply == 0
|| (head->safe_dnsbl = dict_get(psc_dnsbl_reply, saved_site)) == 0)
head->safe_dnsbl = ht->key;
+ if (psc_dnsbl_reply && psc_dnsbl_reply->error)
+ msg_fatal("%s:%s lookup error", psc_dnsbl_reply->type,
+ psc_dnsbl_reply->name);
head->first = 0;
}
psc_smtpd_format_ehlo_reply(psc_temp, discard_mask);
reply = STR(psc_temp);
state->ehlo_discard_mask = discard_mask;
+ } else if (psc_ehlo_discard_maps && psc_ehlo_discard_maps->error) {
+ msg_fatal("%s lookup error for %s",
+ psc_ehlo_discard_maps->title, state->smtp_client_addr);
} else if (state->flags & PSC_STATE_FLAG_USING_TLS) {
reply = psc_smtpd_ehlo_reply_tls;
state->ehlo_discard_mask = psc_ehlo_discard_mask | EHLO_MASK_STARTTLS;
STR(state->cmd_buffer), cp);
vstring_strcpy(state->cmd_buffer, cp);
} else if (psc_cmd_filter->error != 0) {
- /* XXX log something, even if regexps don't soft-fail. */
+ msg_fatal("%s:%s lookup error for \"%.100s\"",
+ psc_cmd_filter->type, psc_cmd_filter->name, cp);
}
}
smtp_sasl_glue.o: ../../include/recipient_list.h
smtp_sasl_glue.o: ../../include/resolve_clnt.h
smtp_sasl_glue.o: ../../include/scache.h
+smtp_sasl_glue.o: ../../include/smtp_stream.h
smtp_sasl_glue.o: ../../include/split_at.h
smtp_sasl_glue.o: ../../include/string_list.h
smtp_sasl_glue.o: ../../include/stringops.h
smtp_session.o: ../../include/recipient_list.h
smtp_session.o: ../../include/resolve_clnt.h
smtp_session.o: ../../include/scache.h
+smtp_session.o: ../../include/smtp_stream.h
smtp_session.o: ../../include/string_list.h
smtp_session.o: ../../include/stringops.h
smtp_session.o: ../../include/sys_defs.h
/* smtp_chat_append - append record to SMTP transaction log */
static void smtp_chat_append(SMTP_SESSION *session, const char *direction,
- const char *data)
+ const char *data)
{
char *line;
smtp_chat_append(session, " ", new_reply);
}
} else if (smtp_chat_resp_filter->error != 0) {
- /* XXX log something, even if regexps don't soft-fail. */
+ msg_warn("%s: table %s:%s lookup error for %s",
+ session->state->request->queue_id,
+ smtp_chat_resp_filter->type,
+ smtp_chat_resp_filter->name,
+ printable(STR(session->buffer), '?'));
+ vstream_longjmp(session->stream, SMTP_ERR_APPL);
}
}
if (chat_append_flag) {
* is not on by default.
*/
if (resp->str[strspn(resp->str, "20 *\t\n")] == 0) {
+ /* Best effort only. Ignore errors. */
if (smtp_pix_bug_maps != 0
&& (pix_bug_words =
maps_find(smtp_pix_bug_maps,
|| (ehlo_words = maps_find(smtp_ehlo_dis_maps,
state->session->addr, 0)) == 0)
ehlo_words = var_smtp_ehlo_dis_words;
+ if (smtp_ehlo_dis_maps && smtp_ehlo_dis_maps->error) {
+ msg_warn("%s: %s map lookup error for %s",
+ session->state->request->queue_id,
+ smtp_ehlo_dis_maps->title, state->session->addr);
+ vstream_longjmp(session->stream, SMTP_ERR_APPL);
+ }
discard_mask = ehlo_mask(ehlo_words);
if (discard_mask && !(discard_mask & EHLO_MASK_SILENT))
msg_info("discarding EHLO keywords: %s",
header_info, buf, offset);
if (result == 0)
return;
+ if (result == HBC_CHECKS_STAT_ERROR) {
+ msg_warn("%s: smtp header checks lookup error",
+ state->request->queue_id);
+ vstream_longjmp(state->session->stream, SMTP_ERR_APPL);
+ }
if (result != STR(buf)) {
vstring_strcpy(buf, result);
myfree(result);
result = hbc_body_checks(context, smtp_body_checks, buf, len, offset);
if (result == buf) {
smtp_text_out(state, type, buf, len, offset);
+ } else if (result == HBC_CHECKS_STAT_ERROR) {
+ msg_warn("%s: smtp body checks lookup error",
+ state->request->queue_id);
+ vstream_longjmp(state->session->stream, SMTP_ERR_APPL);
} else if (result != 0) {
smtp_text_out(state, type, result, strlen(result), offset);
myfree(result);
/* smtp_sasl_auth_cache_valid_value - validate auth failure cache value */
static int smtp_sasl_auth_cache_valid_value(SMTP_SASL_AUTH_CACHE *auth_cache,
- const char *entry,
- const char *password)
+ const char *entry,
+ const char *password)
{
ssize_t len = strlen(entry);
char *cache_hash = mymalloc(len);
if (dict_del(auth_cache->dict, key) != 0)
msg_warn("SASL auth failure map %s: entry not deleted: %s",
auth_cache->dict->name, key);
+ if (auth_cache->dict->error)
+ msg_warn("SASL auth failure map %s: lookup failed for %s",
+ auth_cache->dict->name, key);
myfree(key);
return (valid);
}
/*
/* smtp_sasl_passwd_lookup() looks up the username/password
/* for the current SMTP server. The result is zero in case
-/* of failure.
+/* of failure, a long jump in case of error.
/*
/* smtp_sasl_authenticate() implements the SASL authentication
/* dialog. The result is < 0 in case of protocol failure, zero in
#include <string_list.h>
#include <maps.h>
#include <mail_addr_find.h>
+#include <smtp_stream.h>
/*
* XSASL library.
* but didn't canonicalize the TCP port, and did not append the port to
* the MX hostname.
*/
+ smtp_sasl_passwd_map->error = 0;
if (((state->misc_flags & SMTP_MISC_FLAG_USE_LMTP) == 0
&& var_smtp_sender_auth && state->request->sender[0]
&& (value = mail_addr_find(smtp_sasl_passwd_map,
state->request->sender, (char **) 0)) != 0)
- || (value = maps_find(smtp_sasl_passwd_map, session->host, 0)) != 0
- || (value = maps_find(smtp_sasl_passwd_map, session->dest, 0)) != 0) {
+ || (smtp_sasl_passwd_map->error == 0
+ && (value = maps_find(smtp_sasl_passwd_map,
+ session->host, 0)) != 0)
+ || (smtp_sasl_passwd_map->error == 0
+ && (value = maps_find(smtp_sasl_passwd_map,
+ session->dest, 0)) != 0)) {
if (session->sasl_username)
myfree(session->sasl_username);
session->sasl_username = mystrdup(value);
myname, session->host,
session->sasl_username, session->sasl_passwd);
return (1);
+ } else if (smtp_sasl_passwd_map->error) {
+ msg_warn("%s: %s lookup error",
+ state->request->queue_id, smtp_sasl_passwd_map->title);
+ vstream_longjmp(session->stream, SMTP_ERR_APPL);
} else {
if (msg_verbose)
msg_info("%s: no auth info found (sender=`%s', host=`%s')",
#include <debug_peer.h>
#include <mail_params.h>
#include <maps.h>
+#include <smtp_stream.h>
/* Application-specific. */
msg_warn("Table %s: ignoring unknown TLS policy '%s' for %s %s",
var_smtp_tls_per_site, lookup, site_class, site_name);
}
+ } else if (tls_per_site->error) {
+ msg_fatal("%s lookup error for %s", tls_per_site->title, site_name);
}
}
if ((lookup = maps_find(tls_policy, site_name, 0)) == 0)
return (0);
+ if (tls_policy->error) {
+ msg_warn("%s: %s lookup error for %s",
+ session->state->request->queue_id,
+ tls_policy->title, site_name);
+ vstream_longjmp(session->stream, SMTP_ERR_APPL);
+ }
if (cbuf == 0)
cbuf = vstring_alloc(10);
dsb_simple(why, "4.4.2", "conversation with %s timed out while %s",
session->namaddr, description);
break;
+ case SMTP_ERR_APPL:
+ dsb_simple(why, "4.3.0", "local data error while talking to %s",
+ session->namaddr);
}
return (smtp_bulk_fail(state, SMTP_THROTTLE));
}
case SMTP_ERR_QUIET:
break;
+ case SMTP_ERR_APPL:
+ msg_info("%s: reject: %s from %s: "
+ "421 4.3.0 %s Server configuration error",
+ (state->queue_id ? state->queue_id : "NOQUEUE"),
+ state->where, state->namaddr, var_myhostname);
+ if (vstream_setjmp(state->client) == 0)
+ smtpd_chat_reply(state, "421 4.3.0 %s Server configuration error",
+ var_myhostname);
+ break;
+
case 0:
/*
break;
}
}
+
+ /*
+ * Determine what server ESMTP features to suppress, typically to
+ * avoid inter-operability problems. Moved up so we don't send 421
+ * immediately after sending the initial server response.
+ */
+ if (ehlo_discard_maps == 0
+ || (ehlo_words = maps_find(ehlo_discard_maps, state->addr, 0)) == 0)
+ ehlo_words = var_smtpd_ehlo_dis_words;
+ if (ehlo_discard_maps && ehlo_discard_maps->error)
+ vstream_longjmp(state->client, SMTP_ERR_APPL);
+ state->ehlo_discard_mask = ehlo_mask(ehlo_words);
+
/* XXX We use the real client for connect access control. */
if (SMTPD_STAND_ALONE(state) == 0
&& var_smtpd_delay_reject == 0
smtpd_chat_reply(state, "421 %s Service unavailable - try again later",
var_myhostname);
/* Not: state->error_count++; */
-#ifdef notdef
- } else if (strcmp(state->name, "unknown") == 0) {
- static char *greet_chunks[] = {
- "220 ", 0, " ESMTP ", 0, 0,
- };
- char **cpp;
- char *cp;
-
- greet_chunks[1] = var_myhostname;
- greet_chunks[3] = var_mail_name;
- for (cpp = greet_chunks; *cpp; cpp++) {
- for (cp = *cpp; *cp; cp++)
- smtp_fputc(*(unsigned char *) cp, state->client);
- smtp_flush(state->client);
- if (read_wait(vstream_fileno(state->client), 2) == 0) {
- smtpd_chat_query(state);
- msg_info("PREGREET from %s: %s",
- state->namaddr, vstring_str(state->buffer));
- state->error_mask |= MAIL_ERROR_POLICY;
- smtpd_chat_reply(state,
- "521 %s ESMTP not accepting connections",
- var_myhostname);
- /* Not: state->error_count++; */
- break;
- }
- }
- smtp_fputs("", 0, state->client);
- smtp_flush(state->client);
-#endif
} else {
smtpd_chat_reply(state, "220 %s", var_smtpd_banner);
}
}
- /*
- * Determine what server ESMTP features to suppress, typically to
- * avoid inter-operability problems.
- */
- if (ehlo_discard_maps == 0
- || (ehlo_words = maps_find(ehlo_discard_maps, state->addr, 0)) == 0)
- ehlo_words = var_smtpd_ehlo_dis_words;
- state->ehlo_discard_mask = ehlo_mask(ehlo_words);
-
/*
* SASL initialization for plaintext mode.
*
state->namaddr, STR(state->buffer), cp);
vstring_strcpy(state->buffer, cp);
} else if (smtpd_cmd_filter->error != 0) {
- /* XXX log something, even if regexps don't soft-fail. */
+ msg_warn("%s:%s lookup error for \"%.100s\"",
+ smtpd_cmd_filter->type, smtpd_cmd_filter->name,
+ printable(STR(state->buffer), '?'));
+ vstream_longjmp(state->client, SMTP_ERR_APPL);
}
}
if ((argc = smtpd_token(vstring_str(state->buffer), &argv)) == 0) {
*/
if (*var_rbl_reply_maps) {
template = maps_find(rbl_reply_maps, rbl_domain, DICT_FLAG_NONE);
+ if (rbl_reply_maps->error)
+ reject_server_error(state);
}
why = vstring_alloc(100);
rbl_exp.state = state;
for (i = 0; i < match_count; i++)
list->match_func[i] = va_arg(ap, MATCH_LIST_FN);
va_end(ap);
+ list->error = 0;
#define DO_MATCH 1