diff options
-rw-r--r-- | usr.sbin/smtpd/expand.c | 30 | ||||
-rw-r--r-- | usr.sbin/smtpd/lka_session.c | 628 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 30 |
3 files changed, 298 insertions, 390 deletions
diff --git a/usr.sbin/smtpd/expand.c b/usr.sbin/smtpd/expand.c index c7798e08bdf..4900157be70 100644 --- a/usr.sbin/smtpd/expand.c +++ b/usr.sbin/smtpd/expand.c @@ -1,7 +1,8 @@ -/* $OpenBSD: expand.c,v 1.16 2012/09/21 19:37:08 eric Exp $ */ +/* $OpenBSD: expand.c,v 1.17 2012/09/27 18:57:25 eric Exp $ */ /* * Copyright (c) 2009 Gilles Chehade <gilles@openbsd.org> + * Copyright (c) 2012 Eric Faurot <eric@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -42,15 +43,25 @@ expand_insert(struct expand *expand, struct expandnode *node) { struct expandnode *xn; + if (node->type == EXPAND_USERNAME && + expand->parent && + expand->parent->type == EXPAND_USERNAME && + !strcmp(expand->parent->u.user, node->u.user)) + node->sameuser = 1; + if (expand_lookup(expand, node)) return; xn = xmemdup(node, sizeof *xn, "expand_insert"); - - /* copy expansion context on node */ - strlcpy(xn->as_user, expand->user, sizeof xn->as_user); - + xn->rule = expand->rule; + xn->parent = expand->parent; + if (xn->parent) + xn->depth = xn->parent->depth + 1; + else + xn->depth = 0; RB_INSERT(expandtree, &expand->tree, xn); + if (expand->queue) + TAILQ_INSERT_TAIL(expand->queue, xn, tq_entry); } void @@ -58,6 +69,10 @@ expand_free(struct expand *expand) { struct expandnode *xn; + if (expand->queue) + while ((xn = TAILQ_FIRST(expand->queue))) + TAILQ_REMOVE(expand->queue, xn, tq_entry); + while ((xn = RB_ROOT(&expand->tree)) != NULL) { RB_REMOVE(expandtree, &expand->tree, xn); free(xn); @@ -69,9 +84,12 @@ expand_cmp(struct expandnode *e1, struct expandnode *e2) { if (e1->type < e2->type) return -1; - if (e1->type > e2->type) return 1; + if (e1->sameuser < e2->sameuser) + return -1; + if (e1->sameuser > e2->sameuser) + return 1; return memcmp(&e1->u, &e2->u, sizeof(e1->u)); } diff --git a/usr.sbin/smtpd/lka_session.c b/usr.sbin/smtpd/lka_session.c index 2b5cf095a82..9afa1bb731f 100644 --- a/usr.sbin/smtpd/lka_session.c +++ b/usr.sbin/smtpd/lka_session.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lka_session.c,v 1.35 2012/09/26 19:52:20 eric Exp $ */ +/* $OpenBSD: lka_session.c,v 1.36 2012/09/27 18:57:25 eric Exp $ */ /* * Copyright (c) 2011 Gilles Chehade <gilles@openbsd.org> + * Copyright (c) 2012 Eric Faurot <eric@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -39,42 +40,40 @@ #include "smtpd.h" #include "log.h" -enum lka_session_flags { - F_ERROR = 0x1 -}; +#define F_ERROR 0x01 +#define F_WAITING 0x02 struct lka_session { - SPLAY_ENTRY(lka_session) nodes; - uint64_t id; + uint64_t id; + + TAILQ_HEAD(, envelope) deliverylist; + struct expand expand; + + int flags; + struct submit_status ss; - TAILQ_HEAD(, envelope) deliverylist; - struct expand expand; + struct envelope envelope; - uint8_t iterations; - uint32_t pending; - enum lka_session_flags flags; - struct submit_status ss; + struct xnodes nodes; + /* waiting for fwdrq */ + struct rule *rule; + struct expandnode *node; }; -static void lka_session_fail(struct lka_session *); -static void lka_session_destroy(struct lka_session *); -static void lka_session_pickup(struct lka_session *, struct envelope *); -static int lka_session_envelope_expand(struct lka_session *, struct envelope *); -static int lka_session_resume(struct lka_session *, struct envelope *); -static void lka_session_done(struct lka_session *); -static size_t lka_session_expand_format(char *, size_t, struct envelope *); -static void lka_session_request_forwardfile(struct lka_session *, - struct envelope *, char *); -static void lka_session_deliver(struct lka_session *, struct envelope *); -static int lka_session_resolve_node(struct envelope *, struct expandnode *); -static int lka_session_rcpt_action(struct envelope *); +static void lka_expand(struct lka_session *, struct rule *, struct expandnode *); +static void lka_submit(struct lka_session *, struct rule *, struct expandnode *); +static void lka_resume(struct lka_session *); +static size_t lka_expand_format(char *, size_t, const struct envelope *); +static void mailaddr_to_username(const struct mailaddr *, char *, size_t); +static const char * mailaddr_tag(const struct mailaddr *); static struct tree sessions = SPLAY_INITIALIZER(&sessions); void lka_session(struct submit_status *ss) { - struct lka_session *lks; + struct lka_session *lks; + struct expandnode xn; lks = xcalloc(1, sizeof(*lks), "lka_session"); lks->id = generate_uid(); @@ -84,256 +83,103 @@ lka_session(struct submit_status *ss) TAILQ_INIT(&lks->deliverylist); tree_xset(&sessions, lks->id, lks); - if (! lka_session_envelope_expand(lks, &ss->envelope)) - lka_session_fail(lks); - else - lka_session_pickup(lks, &ss->envelope); -} - -static int -lka_session_envelope_expand(struct lka_session *lks, struct envelope *ep) -{ - char *user; - char *tag; - struct user_backend *ub; - struct mta_user u; - char username[MAX_LOCALPART_SIZE]; - - /* remote delivery, no need to process further */ - if (ep->type == D_MTA) { - lka_session_deliver(lks, ep); - return 1; - } - - switch (ep->rule.r_condition.c_type) { - case C_ALL: - case C_DOM: - if (ep->agent.mda.user[0] == '\0') - user = ep->dest.user; - else - user = ep->agent.mda.user; - xlowercase(username, user, sizeof(username)); - - /* gilles+hackers@ -> gilles@ */ - if ((tag = strchr(username, '+')) != NULL) { - *tag++ = '\0'; - - /* skip dots after the '+' */ - while (*tag == '.') - tag++; - } - - if (aliases_get(ep->rule.r_amap, &lks->expand, username)) - return 1; - - bzero(&u, sizeof (u)); - ub = user_backend_lookup(USER_PWD); - if (! ub->getbyname(&u, username)) - return 0; - - (void)strlcpy(ep->agent.mda.user, u.username, - sizeof (ep->agent.mda.user)); - - ep->type = D_MDA; - switch (ep->rule.r_action) { - case A_MBOX: - ep->agent.mda.method = A_MBOX; - (void)strlcpy(ep->agent.mda.user, - u.username, - sizeof (ep->agent.mda.user)); - break; - case A_MAILDIR: - case A_FILENAME: - case A_MDA: - ep->agent.mda.method = ep->rule.r_action; - (void)strlcpy(ep->agent.mda.buffer, - ep->rule.r_value.buffer, - sizeof (ep->agent.mda.buffer)); - - if (tag && *tag) { - (void)strlcat(ep->agent.mda.buffer, "/.", - sizeof (ep->agent.mda.buffer)); - (void)strlcat(ep->agent.mda.buffer, tag, - sizeof (ep->agent.mda.buffer)); - } - break; - default: - fatalx("lka_session_envelope_expand: unexpected rule action"); - return 0; - } - - lka_session_request_forwardfile(lks, ep, u.username); - return 1; - - case C_VDOM: - if (aliases_virtual_get(ep->rule.r_condition.c_map, - &lks->expand, &ep->dest)) - return 1; - - return 0; - - default: - fatalx("lka_session_envelope_expand: unexpected type"); - return 0; - } + lks->envelope = ss->envelope; - return 0; + TAILQ_INIT(&lks->nodes); + bzero(&xn, sizeof xn); + xn.type = EXPAND_ADDRESS; + xn.u.mailaddr = lks->envelope.dest; /* XXX we should only have rcpt */ + lks->expand.rule = NULL; + lks->expand.queue = &lks->nodes; + expand_insert(&lks->expand, &xn); + lka_resume(lks); } void lka_session_forward_reply(struct forward_req *fwreq, int fd) { - struct lka_session *lks; - struct envelope *ep; + struct lka_session *lks; + struct rule *rule; + struct expandnode *xn; lks = tree_xget(&sessions, fwreq->id); - lks->pending--; - - ep = &fwreq->envelope; + xn = lks->node; + rule = lks->rule; - if (fd != -1) { - /* opened .forward okay */ - strlcpy(lks->expand.user, fwreq->as_user, - sizeof lks->expand.user); - if (! forwards_get(fd, &lks->expand)) { - lks->ss.code = 530; - lks->flags |= F_ERROR; - } - close(fd); - lka_session_pickup(lks, ep); - return; - } + lks->flags &= ~F_WAITING; - if (fwreq->status) { - /* .forward not present */ - lka_session_deliver(lks, ep); - lka_session_pickup(lks, ep); - return; + if (fd == -1 && fwreq->status) { + /* no .forward, just deliver to local user */ + log_debug("lka: no .forward for user %s, just deliver", + fwreq->as_user), + lka_submit(lks, rule, xn); } - - /* opening .forward failed */ - lks->ss.code = 530; - lks->flags |= F_ERROR; - lka_session_pickup(lks, ep); -} - -static void -lka_session_pickup(struct lka_session *lks, struct envelope *ep) -{ - int ret; - - /* we want to do five iterations of lka_session_resume() but - * we need to be interruptible in case lka_session_resume() - * has sent an imsg and expects an answer. - */ - while (! (lks->flags & F_ERROR) && - ! lks->pending && lks->iterations < 5) { - ++lks->iterations; - ret = lka_session_resume(lks, ep); - if (ret == -1) { + else if (fd == -1) { + log_debug("lka: opening .forward failed for user %s", + fwreq->as_user), + lks->ss.code = 530; + lks->flags |= F_ERROR; + } + else { + /* expand for the current user and rule */ + lks->expand.rule = rule; + lks->expand.parent = xn; + if (forwards_get(fd, &lks->expand) == 0) { + /* no aliases */ lks->ss.code = 530; lks->flags |= F_ERROR; } - - if (lks->pending || ret <= 0) - break; + close(fd); } - - if (lks->pending) - return; - - lka_session_done(lks); + lka_resume(lks); } -static int -lka_session_resume(struct lka_session *lks, struct envelope *ep) +static void +lka_resume(struct lka_session *lks) { - struct expandnode *xn; - uint8_t done = 1; - - RB_FOREACH(xn, expandtree, &lks->expand.tree) { - - /* this node has already been expanded, skip */ - if (xn->done) - continue; - done = 0; - - switch (lka_session_resolve_node(ep, xn)) { - case 0: - if (! lka_session_envelope_expand(lks, ep)) - return -1; - break; - case 1: - lka_session_deliver(lks, ep); - break; - default: - return -1; - } + struct envelope *ep; + struct expandnode *xn; - xn->done = 1; + if (lks->flags & F_ERROR) + goto error; + + /* pop next node and expand it */ + while((xn = TAILQ_FIRST(&lks->nodes))) { + TAILQ_REMOVE(&lks->nodes, xn, tq_entry); + lka_expand(lks, xn->rule, xn); + if (lks->flags & F_WAITING) + return; + if (lks->flags & F_ERROR) + goto error; } - /* still not done after 5 iterations ? loop detected ... reject */ - if (!done && lks->iterations == 5) - return -1; - - /* we're done expanding, no need for another iteration */ - if (RB_ROOT(&lks->expand.tree) == NULL || done) - return 0; - - return 1; -} - -static void -lka_session_done(struct lka_session *lks) -{ - struct envelope *ep; - - /* delivery list is empty OR expansion led to an error, reject */ + /* delivery list is empty, reject */ if (TAILQ_FIRST(&lks->deliverylist) == NULL) { - log_info("lka_session_done: expansion led to empty delivery list"); + log_info("lka_done: expansion led to empty delivery list"); lks->flags |= F_ERROR; } - if (lks->flags & F_ERROR) - goto done; - - /* process the delivery list and submit envelopes to queue */ - while ((ep = TAILQ_FIRST(&lks->deliverylist)) != NULL) { - imsg_compose_event(env->sc_ievs[PROC_QUEUE], - IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1, ep, sizeof *ep); - TAILQ_REMOVE(&lks->deliverylist, ep, entry); - free(ep); - } - ep = &lks->ss.envelope; - imsg_compose_event(env->sc_ievs[PROC_QUEUE], - IMSG_QUEUE_COMMIT_ENVELOPES, 0, 0, -1, ep, sizeof *ep); - -done: + 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) { + TAILQ_REMOVE(&lks->deliverylist, ep, entry); + free(ep); + } } - lka_session_destroy(lks); -} - -static void -lka_session_fail(struct lka_session *lks) -{ - lks->ss.code = 530; - imsg_compose_event(env->sc_ievs[PROC_MFA], IMSG_LKA_RCPT, 0, 0, -1, - &lks->ss, sizeof(lks->ss)); - lka_session_destroy(lks); -} - -static void -lka_session_destroy(struct lka_session *lks) -{ - struct envelope *ep; - - while ((ep = TAILQ_FIRST(&lks->deliverylist)) != NULL) { - TAILQ_REMOVE(&lks->deliverylist, ep, entry); - free(ep); + else { + /* process the delivery list and submit envelopes to queue */ + while ((ep = TAILQ_FIRST(&lks->deliverylist)) != NULL) { + TAILQ_REMOVE(&lks->deliverylist, ep, entry); + imsg_compose_event(env->sc_ievs[PROC_QUEUE], + IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1, + ep, sizeof *ep); + free(ep); + } + ep = &lks->ss.envelope; + imsg_compose_event(env->sc_ievs[PROC_QUEUE], + IMSG_QUEUE_COMMIT_ENVELOPES, 0, 0, -1, ep, sizeof *ep); } expand_free(&lks->expand); @@ -342,126 +188,180 @@ lka_session_destroy(struct lka_session *lks) } static void -lka_session_deliver(struct lka_session *lks, struct envelope *ep) -{ - struct envelope *new_ep; - - new_ep = xmemdup(ep, sizeof *ep, "lka_session_deliver"); - if (new_ep->type == D_MDA) { - switch (new_ep->agent.mda.method) { - case A_MAILDIR: - case A_FILENAME: - case A_MDA: - if (! lka_session_expand_format( - new_ep->agent.mda.buffer, - sizeof(new_ep->agent.mda.buffer), new_ep)) - lks->flags |= F_ERROR; - default: - break; - } - } - else if (new_ep->type == D_MTA) { - new_ep->agent.mta.relay = ep->rule.r_value.relayhost; - if (ep->rule.r_as) { - if (ep->rule.r_as->user[0]) { - strlcpy(new_ep->sender.user, - ep->rule.r_as->user, - sizeof new_ep->sender.user); - } - if (ep->rule.r_as->domain[0]) { - strlcpy(new_ep->sender.domain, - ep->rule.r_as->domain, - sizeof new_ep->sender.domain); - } - } - } - TAILQ_INSERT_TAIL(&lks->deliverylist, new_ep, entry); -} - -static int -lka_session_resolve_node(struct envelope *ep, struct expandnode *xn) +lka_expand(struct lka_session *lks, struct rule *rule, struct expandnode *xn) { - struct envelope oldep; + struct forward_req fwreq; + struct envelope ep; + struct expandnode node; - memcpy(&oldep, ep, sizeof (*ep)); - bzero(&ep->agent, sizeof (ep->agent)); + if (xn->depth >= 5) { + log_debug("lka_expand: node too deep."); + lks->flags |= F_ERROR; + lks->ss.code = 530; + return; + } switch (xn->type) { case EXPAND_INVALID: case EXPAND_INCLUDE: - fatalx("lka_session_resolve_node: unexpected type"); + fatalx("lka_expand: unexpected type"); break; case EXPAND_ADDRESS: - log_debug("lka_resolve_node: node is address: %s@%s", + log_debug("lka_expand: expanding address: %s@%s", xn->u.mailaddr.user, xn->u.mailaddr.domain); - ep->dest = xn->u.mailaddr; - /* evaluation of ruleset assumes local source - * since we're expanding on already accepted - * source. - */ - ep->flags |= DF_INTERNAL; - if (! lka_session_rcpt_action(ep)) - return -1; - return 0; + /* Pass the node through the ruleset */ + ep = lks->envelope; + ep.dest = xn->u.mailaddr; + if (xn->parent) /* nodes with parent are forward addresses */ + ep.flags |= DF_INTERNAL; + rule = ruleset_match(&ep); + if (rule == NULL) { + lks->flags |= F_ERROR; + lks->ss.code = 530; + break; /* no rule for address */ + } + if (rule->r_action == A_RELAY || rule->r_action == A_RELAYVIA) { + lka_submit(lks, rule, xn); + } + else if (rule->r_condition.c_type == C_VDOM) { + /* expand */ + lks->expand.rule = rule; + lks->expand.parent = xn; + if (aliases_virtual_get(rule->r_condition.c_map, + &lks->expand, &xn->u.mailaddr) == 0) { + log_debug("lka_expand: no aliases for virtual"); + lks->flags |= F_ERROR; + lks->ss.code = 530; + } + } + else { + lks->expand.rule = rule; + lks->expand.parent = xn; + node.type = EXPAND_USERNAME; + mailaddr_to_username(&xn->u.mailaddr, node.u.user, + sizeof node.u.user); + expand_insert(&lks->expand, &node); + } + break; case EXPAND_USERNAME: - log_debug("lka_resolve_node: node is local username: %s", - xn->u.user); - ep->type = D_MDA; - strlcpy(ep->agent.mda.user, xn->u.user, - sizeof ep->agent.mda.user); - - /* overwrite the initial condition before we expand the - * envelope again. if we came from a C_VDOM, not doing - * so would lead to a VDOM loop causing recipient to be - * rejected. - * - * i'll find a more elegant solution later, for now it - * fixes an annoying bug. - */ - ep->rule.r_condition.c_type = C_DOM; - - /* if expansion of a user results in same user ... deliver */ - if (strcmp(xn->u.user, xn->as_user) == 0) { - ep->agent.mda.method = oldep.agent.mda.method; + log_debug("lka_expand: expanding username: %s", xn->u.user); + + if (xn->sameuser) { + log_debug("lka_expand: same user, submitting"); + lka_submit(lks, rule, xn); break; } - /* otherwise rewrite delivery user with expansion result */ - (void)strlcpy(ep->agent.mda.user, xn->u.user, - sizeof (ep->agent.mda.user)); - return 0; + /* expand aliases with the given rule */ + + lks->expand.rule = rule; + lks->expand.parent = xn; + if (rule->r_amap && + aliases_get(rule->r_amap, &lks->expand, xn->u.user)) + break; + + /* no aliases found, query forward file */ + lks->rule = rule; + lks->node = xn; + fwreq.id = lks->id; + (void)strlcpy(fwreq.as_user, xn->u.user, sizeof(fwreq.as_user)); + imsg_compose_event(env->sc_ievs[PROC_PARENT], + IMSG_PARENT_FORWARD_OPEN, 0, 0, -1, &fwreq, sizeof(fwreq)); + lks->flags |= F_WAITING; + break; case EXPAND_FILENAME: - log_debug("lka_resolve_node: node is filename: %s", - xn->u.buffer); - ep->type = D_MDA; - ep->agent.mda.method = A_FILENAME; - (void)strlcpy(ep->agent.mda.buffer, xn->u.buffer, - sizeof (ep->agent.mda.buffer)); - (void)strlcpy(ep->agent.mda.user, xn->as_user, - sizeof (ep->agent.mda.user)); + log_debug("lka_expand: expanding filename: %s", xn->u.buffer); + lka_submit(lks, rule, xn); break; case EXPAND_FILTER: - log_debug("lka_resolve_node: node is filter: %s", - xn->u.buffer); - ep->type = D_MDA; - ep->agent.mda.method = A_MDA; - (void)strlcpy(ep->agent.mda.buffer, xn->u.buffer, - sizeof (ep->agent.mda.buffer)); - (void)strlcpy(ep->agent.mda.user, xn->as_user, + log_debug("lka_expand: expanding filter: %s", xn->u.buffer); + lka_submit(lks, rule, xn); + break; + } +} + +static void +lka_submit(struct lka_session *lks, struct rule *rule, struct expandnode *xn) +{ + struct envelope *ep; + struct expandnode *xn2; + const char *tag; + + ep = xmemdup(&lks->envelope, sizeof *ep, "lka_submit"); + + switch (rule->r_action) { + case A_RELAY: + case A_RELAYVIA: + ep->type = D_MTA; + ep->agent.mta.relay = rule->r_value.relayhost; + if (xn->type != EXPAND_ADDRESS) + fatalx("lka_deliver: expect address"); + ep->dest = xn->u.mailaddr; + break; + case A_MBOX: + case A_MAILDIR: + case A_FILENAME: + case A_MDA: + ep->type = D_MDA; + + /* set username */ + xn2 = xn; + while(xn2 && (xn2->type != EXPAND_USERNAME)) + xn2 = xn2->parent; + if (xn2 == NULL) + fatalx("no user in node ancestry"); + (void)strlcpy(ep->agent.mda.user, xn2->u.user, sizeof (ep->agent.mda.user)); + + /* set dest */ + xn2 = xn; + while(xn2 && (xn2->type != EXPAND_ADDRESS)) + xn2 = xn2->parent; + if (xn2 == NULL) + fatalx("no address in node ancestry"); + ep->dest = xn2->u.mailaddr; + + if (xn->type == EXPAND_FILENAME) { + ep->agent.mda.method = A_FILENAME; + strlcpy(ep->agent.mda.buffer, xn->u.buffer, + sizeof ep->agent.mda.buffer); + } + else if (xn->type == EXPAND_FILTER) { + ep->agent.mda.method = A_MDA; + strlcpy(ep->agent.mda.buffer, xn->u.buffer, + sizeof ep->agent.mda.buffer); + } + else if (xn->type == EXPAND_USERNAME) { + ep->agent.mda.method = rule->r_action; + strlcpy(ep->agent.mda.buffer, rule->r_value.buffer, + sizeof ep->agent.mda.buffer); + tag = mailaddr_tag(&ep->dest); + if (rule->r_action == A_MAILDIR && tag && tag[0]) { + strlcat(ep->agent.mda.buffer, "/.", + sizeof (ep->agent.mda.buffer)); + strlcat(ep->agent.mda.buffer, tag, + sizeof (ep->agent.mda.buffer)); + } + } else + fatalx("lka_deliver: bad node type"); + + lka_expand_format(ep->agent.mda.buffer, + sizeof(ep->agent.mda.buffer), ep); break; + default: + fatalx("lka_submit: bad rule action"); } - return 1; + TAILQ_INSERT_TAIL(&lks->deliverylist, ep, entry); } static size_t -lka_session_expand_format(char *buf, size_t len, struct envelope *ep) +lka_expand_format(char *buf, size_t len, const struct envelope *ep) { char *p, *pbuf; size_t ret, lret = 0; @@ -517,7 +417,7 @@ lka_session_expand_format(char *buf, size_t len, struct envelope *ep) } } if (*p == '%') { - char *string, *tmp = p + 1; + const char *string, *tmp = p + 1; int digit = 0; if (isdigit((int)*tmp)) { @@ -578,42 +478,28 @@ copy: return ret; } -static int -lka_session_rcpt_action(struct envelope *ep) +static void +mailaddr_to_username(const struct mailaddr *maddr, char *dst, size_t len) { - struct rule *r; - - r = ruleset_match(ep); - if (r == NULL) { - ep->type = D_MTA; - return 0; - } + char *tag; - ep->rule = *r; - switch (ep->rule.r_action) { - case A_MBOX: - case A_MAILDIR: - case A_FILENAME: - case A_MDA: - ep->type = D_MDA; - break; - default: - ep->type = D_MTA; - } + xlowercase(dst, maddr->user, len); - return 1; + /* gilles+hackers@ -> gilles@ */ + if ((tag = strchr(dst, '+')) != NULL) + *tag++ = '\0'; } -static void -lka_session_request_forwardfile(struct lka_session *lks, - struct envelope *ep, char *as_user) +static const char * +mailaddr_tag(const struct mailaddr *maddr) { - struct forward_req fwreq; - - fwreq.id = lks->id; - fwreq.envelope = *ep; - (void)strlcpy(fwreq.as_user, as_user, sizeof(fwreq.as_user)); - imsg_compose_event(env->sc_ievs[PROC_PARENT], - IMSG_PARENT_FORWARD_OPEN, 0, 0, -1, &fwreq, sizeof(fwreq)); - ++lks->pending; + const char *tag; + + if ((tag = strchr(maddr->user, '+'))) { + tag++; + while (*tag == '.') + tag++; + } + + return (tag); } diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h index 390bf7b88c5..c4a82b32f87 100644 --- a/usr.sbin/smtpd/smtpd.h +++ b/usr.sbin/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.368 2012/09/26 19:52:20 eric Exp $ */ +/* $OpenBSD: smtpd.h,v 1.369 2012/09/27 18:57:25 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -350,7 +350,7 @@ struct delivery_mda { }; struct delivery_mta { - struct relayhost relay; + struct relayhost relay; }; enum expand_type { @@ -363,20 +363,25 @@ enum expand_type { }; struct expandnode { - RB_ENTRY(expandnode) entry; - int done; - enum expand_type type; - char as_user[MAXLOGNAME]; + RB_ENTRY(expandnode) entry; + TAILQ_ENTRY(expandnode) tq_entry; + enum expand_type type; + int sameuser; + struct rule *rule; + struct expandnode *parent; + unsigned int depth; union { - char user[MAXLOGNAME]; - char buffer[MAX_RULEBUFFER_LEN]; - struct mailaddr mailaddr; - } u; + char user[MAXLOGNAME]; + char buffer[MAX_RULEBUFFER_LEN]; + struct mailaddr mailaddr; + } u; }; struct expand { - RB_HEAD(expandtree, expandnode) tree; - char user[MAXLOGNAME]; + RB_HEAD(expandtree, expandnode) tree; + TAILQ_HEAD(xnodes, expandnode) *queue; + struct rule *rule; + struct expandnode *parent; }; #define SMTPD_ENVELOPE_VERSION 1 @@ -637,7 +642,6 @@ struct forward_req { uint64_t id; uint8_t status; char as_user[MAXLOGNAME]; - struct envelope envelope; }; enum dns_status { |