diff options
author | Eric Faurot <eric@cvs.openbsd.org> | 2012-10-13 08:01:48 +0000 |
---|---|---|
committer | Eric Faurot <eric@cvs.openbsd.org> | 2012-10-13 08:01:48 +0000 |
commit | 2a3cfe2b5dd297f5d3114dae73ae8d06c9399dda (patch) | |
tree | cda6378acd893178ea4ce44b1e58cac059cfdff3 /usr.sbin/smtpd | |
parent | 87f0135c1dc614a6bca5cf29e81c71d45b1cc29e (diff) |
Make map_lookup() and make_compare() set errno on failure to distinguish
between "no match" and "internal error" (e.g. missing or broken db file).
Adapt alias expansion and ruleset matching code to check for such errors,
in which case the current processing is aborted, and a temporary failure
is reported to the smtp session.
ok gilles@
Diffstat (limited to 'usr.sbin/smtpd')
-rw-r--r-- | usr.sbin/smtpd/aliases.c | 11 | ||||
-rw-r--r-- | usr.sbin/smtpd/lka.c | 10 | ||||
-rw-r--r-- | usr.sbin/smtpd/lka_session.c | 32 | ||||
-rw-r--r-- | usr.sbin/smtpd/map.c | 19 | ||||
-rw-r--r-- | usr.sbin/smtpd/ruleset.c | 52 |
5 files changed, 86 insertions, 38 deletions
diff --git a/usr.sbin/smtpd/aliases.c b/usr.sbin/smtpd/aliases.c index 59bf4c4206b..5c7d8420ad2 100644 --- a/usr.sbin/smtpd/aliases.c +++ b/usr.sbin/smtpd/aliases.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aliases.c,v 1.56 2012/09/21 19:37:08 eric Exp $ */ +/* $OpenBSD: aliases.c,v 1.57 2012/10/13 08:01:47 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -23,6 +23,7 @@ #include <sys/socket.h> #include <ctype.h> +#include <errno.h> #include <event.h> #include <imsg.h> #include <stdio.h> @@ -51,7 +52,7 @@ aliases_get(objid_t mapid, struct expand *expand, const char *username) xlowercase(buf, username, sizeof(buf)); map_alias = map_lookup(mapid, buf, K_ALIAS); if (map_alias == NULL) - return 0; + return (errno ? -1 : 0); /* foreach node in map_alias expandtree, we merge */ nbaliases = 0; @@ -88,11 +89,13 @@ aliases_virtual_get(objid_t mapid, struct expand *expand, map_virtual = map_lookup(mapid, buf, K_VIRTUAL); if (map_virtual == NULL) { + if (errno) + return (-1); pbuf = strchr(buf, '@'); map_virtual = map_lookup(mapid, pbuf, K_VIRTUAL); } if (map_virtual == NULL) - return 0; + return (errno ? -1 : 0); /* foreach node in map_virtual expand, we merge */ nbaliases = 0; @@ -121,7 +124,7 @@ aliases_vdomain_exists(objid_t mapid, const char *hostname) xlowercase(buf, hostname, sizeof(buf)); map_virtual = map_lookup(mapid, buf, K_VIRTUAL); if (map_virtual == NULL) - return 0; + return (errno ? -1 : 0); /* XXX - for now the map API always allocate */ log_debug("aliases_vdomain_exist: '%s' exists", hostname); diff --git a/usr.sbin/smtpd/lka.c b/usr.sbin/smtpd/lka.c index dcc0893b8d1..247619daaf4 100644 --- a/usr.sbin/smtpd/lka.c +++ b/usr.sbin/smtpd/lka.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lka.c,v 1.143 2012/09/30 14:28:15 gilles Exp $ */ +/* $OpenBSD: lka.c,v 1.144 2012/10/13 08:01:47 eric Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -82,10 +82,12 @@ lka_imsg(struct imsgev *iev, struct imsg *imsg) case IMSG_LKA_RULEMATCH: ss = imsg->data; - ss->code = 530; rule = ruleset_match(&ss->envelope); - if (rule && rule->r_decision == R_ACCEPT) - ss->code = 250; + if (rule == NULL) + ss->code = (errno == EAGAIN) ? 451 : 530; + else + ss->code = (rule->r_decision == R_ACCEPT) ? + 250 : 530; imsg_compose_event(iev, IMSG_LKA_RULEMATCH, 0, 0, -1, ss, sizeof *ss); return; diff --git a/usr.sbin/smtpd/lka_session.c b/usr.sbin/smtpd/lka_session.c index a030ede1a35..488d6c062a5 100644 --- a/usr.sbin/smtpd/lka_session.c +++ b/usr.sbin/smtpd/lka_session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lka_session.c,v 1.43 2012/10/11 21:14:32 gilles Exp $ */ +/* $OpenBSD: lka_session.c,v 1.44 2012/10/13 08:01:47 eric Exp $ */ /* * Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org> @@ -163,7 +163,6 @@ lka_resume(struct lka_session *lks) } error: if (lks->flags & F_ERROR) { - lks->ss.code = 530; imsg_compose_event(env->sc_ievs[PROC_MFA], IMSG_LKA_RCPT, 0, 0, -1, &lks->ss, sizeof(struct submit_status)); while ((ep = TAILQ_FIRST(&lks->deliverylist)) != NULL) { @@ -196,6 +195,7 @@ lka_expand(struct lka_session *lks, struct rule *rule, struct expandnode *xn) struct forward_req fwreq; struct envelope ep; struct expandnode node; + int r; if (xn->depth >= EXPAND_DEPTH) { log_debug("lka_expand: node too deep."); @@ -222,7 +222,7 @@ lka_expand(struct lka_session *lks, struct rule *rule, struct expandnode *xn) rule = ruleset_match(&ep); if (rule == NULL || rule->r_decision == R_REJECT) { lks->flags |= F_ERROR; - lks->ss.code = 530; + lks->ss.code = (errno == EAGAIN ? 451 : 530); break; /* no rule for address or REJECT match */ } if (rule->r_action == A_RELAY || rule->r_action == A_RELAYVIA) { @@ -233,11 +233,18 @@ lka_expand(struct lka_session *lks, struct rule *rule, struct expandnode *xn) lks->expand.rule = rule; lks->expand.parent = xn; lks->expand.alias = 1; - if (aliases_virtual_get(rule->r_condition.c_map, - &lks->expand, &xn->u.mailaddr) == 0) { - log_debug("lka_expand: no aliases for virtual"); + r = aliases_virtual_get(rule->r_condition.c_map, + &lks->expand, &xn->u.mailaddr); + if (r == -1) { + lks->flags |= F_ERROR; + lks->ss.code = 451; + log_debug( + "lka_expand: error in virtual alias lookup"); + } + else if (r == 0) { lks->flags |= F_ERROR; lks->ss.code = 530; + log_debug("lka_expand: no aliases for virtual"); } } else { @@ -264,9 +271,16 @@ lka_expand(struct lka_session *lks, struct rule *rule, struct expandnode *xn) lks->expand.rule = rule; lks->expand.parent = xn; lks->expand.alias = 1; - if (rule->r_amap && - aliases_get(rule->r_amap, &lks->expand, xn->u.user)) - break; + if (rule->r_amap) { + r = aliases_get(rule->r_amap, &lks->expand, xn->u.user); + if (r == -1) { + log_debug("lka_expand: error in alias lookup"); + lks->flags |= F_ERROR; + lks->ss.code = 451; + } + if (r) + break; + } /* a username should not exceed the size of a system user */ if (strlen(xn->u.user) >= sizeof fwreq.as_user) { diff --git a/usr.sbin/smtpd/map.c b/usr.sbin/smtpd/map.c index ddbf1982afc..71e082c2225 100644 --- a/usr.sbin/smtpd/map.c +++ b/usr.sbin/smtpd/map.c @@ -1,4 +1,4 @@ -/* $OpenBSD: map.c,v 1.32 2012/10/11 21:43:11 gilles Exp $ */ +/* $OpenBSD: map.c,v 1.33 2012/10/13 08:01:47 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -23,6 +23,7 @@ #include <sys/socket.h> #include <err.h> +#include <errno.h> #include <event.h> #include <imsg.h> #include <stdio.h> @@ -97,19 +98,24 @@ map_lookup(objid_t mapid, const char *key, enum map_kind kind) struct map_backend *backend = NULL; map = map_find(mapid); - if (map == NULL) + if (map == NULL) { + errno = EINVAL; return NULL; + } backend = map_backend_lookup(map->m_src); hdl = backend->open(map); if (hdl == NULL) { log_warn("map_lookup: can't open %s", map->m_config); + if (errno == 0) + errno = ENOTSUP; return NULL; } ret = backend->lookup(hdl, key, kind); backend->close(hdl); + errno = 0; return ret; } @@ -123,19 +129,24 @@ map_compare(objid_t mapid, const char *key, enum map_kind kind, int ret; map = map_find(mapid); - if (map == NULL) + if (map == NULL) { + errno = EINVAL; return 0; + } backend = map_backend_lookup(map->m_src); hdl = backend->open(map); if (hdl == NULL) { - log_warn("map_lookup: can't open %s", map->m_config); + log_warn("map_compare: can't open %s", map->m_config); + if (errno == 0) + errno = ENOTSUP; return 0; } ret = backend->compare(hdl, key, kind, func); backend->close(hdl); + errno = 0; return ret; } diff --git a/usr.sbin/smtpd/ruleset.c b/usr.sbin/smtpd/ruleset.c index 2e9161bc38b..259d021bfff 100644 --- a/usr.sbin/smtpd/ruleset.c +++ b/usr.sbin/smtpd/ruleset.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ruleset.c,v 1.24 2012/10/11 21:14:32 gilles Exp $ */ +/* $OpenBSD: ruleset.c,v 1.25 2012/10/13 08:01:47 eric Exp $ */ /* * Copyright (c) 2009 Gilles Chehade <gilles@openbsd.org> @@ -24,6 +24,7 @@ #include <netinet/in.h> +#include <errno.h> #include <event.h> #include <imsg.h> #include <stdio.h> @@ -42,11 +43,12 @@ static int ruleset_inet6_match(struct sockaddr_in6 *, struct netaddr *); struct rule * ruleset_match(const struct envelope *evp) { - struct rule *r; - struct map *map; - struct mapel *me; const struct mailaddr *maddr = &evp->dest; const struct sockaddr_storage *ss = &evp->ss; + struct rule *r; + struct map *map; + struct mapel *me; + int v; if (evp->flags & DF_INTERNAL) ss = NULL; @@ -56,10 +58,15 @@ ruleset_match(const struct envelope *evp) if (r->r_tag[0] != '\0' && strcmp(r->r_tag, evp->tag) != 0) continue; - if (ss != NULL && - (!(evp->flags & DF_AUTHENTICATED) && - ! ruleset_check_source(r->r_sources, ss))) - continue; + if (ss != NULL && !(evp->flags & DF_AUTHENTICATED)) { + v = ruleset_check_source(r->r_sources, ss); + if (v == -1) { + errno = EAGAIN; + return (NULL); + } + if (v == 0) + continue; + } if (r->r_condition.c_type == COND_ANY) return r; @@ -72,24 +79,33 @@ ruleset_match(const struct envelope *evp) if (map->m_src == S_NONE) { TAILQ_FOREACH(me, &map->m_contents, me_entry) { if (hostname_match(maddr->domain, - me->me_key.med_string)) + me->me_key.med_string)) return r; } } else if (map_lookup(map->m_id, maddr->domain, - K_VIRTUAL) != NULL) { - return r; + K_VIRTUAL) != NULL) { + return (r); + } else if (errno) { + errno = EAGAIN; + return (NULL); } } if (r->r_condition.c_type == COND_VDOM) { - if (aliases_vdomain_exists(r->r_condition.c_map, - maddr->domain)) - return r; + v = aliases_vdomain_exists(r->r_condition.c_map, + maddr->domain); + if (v == -1) { + errno = EAGAIN; + return (NULL); + } + if (v) + return (r); } } - return NULL; + errno = 0; + return (NULL); } static int @@ -138,8 +154,10 @@ ruleset_check_source(struct map *map, const struct sockaddr_storage *ss) } else { if (map_compare(map->m_id, ss_to_text(ss), K_NETADDR, - ruleset_cmp_source)) - return 1; + ruleset_cmp_source)) + return (1); + if (errno) + return (-1); } return 0; |