aboutsummaryrefslogtreecommitdiffstats
path: root/smtpd/lka_session.c
diff options
context:
space:
mode:
Diffstat (limited to 'smtpd/lka_session.c')
-rw-r--r--smtpd/lka_session.c556
1 files changed, 0 insertions, 556 deletions
diff --git a/smtpd/lka_session.c b/smtpd/lka_session.c
deleted file mode 100644
index 999e01d6..00000000
--- a/smtpd/lka_session.c
+++ /dev/null
@@ -1,556 +0,0 @@
-/* $OpenBSD: lka_session.c,v 1.93 2019/09/20 17:46:05 gilles Exp $ */
-
-/*
- * Copyright (c) 2011 Gilles Chehade <gilles@poolp.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
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/tree.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-
-#include <netinet/in.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <event.h>
-#include <imsg.h>
-#include <resolv.h>
-#include <pwd.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <limits.h>
-
-#include "smtpd.h"
-#include "log.h"
-
-#define EXPAND_DEPTH 10
-
-#define F_WAITING 0x01
-
-struct lka_session {
- uint64_t id; /* given by smtp */
-
- TAILQ_HEAD(, envelope) deliverylist;
- struct expand expand;
-
- int flags;
- int error;
- const char *errormsg;
- struct envelope envelope;
- struct xnodes nodes;
- /* waiting for fwdrq */
- struct rule *rule;
- struct expandnode *node;
-};
-
-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 int init;
-static struct tree sessions;
-
-void
-lka_session(uint64_t id, struct envelope *envelope)
-{
- struct lka_session *lks;
- struct expandnode xn;
-
- if (init == 0) {
- init = 1;
- tree_init(&sessions);
- }
-
- lks = xcalloc(1, sizeof(*lks));
- lks->id = id;
- RB_INIT(&lks->expand.tree);
- TAILQ_INIT(&lks->deliverylist);
- tree_xset(&sessions, lks->id, lks);
-
- lks->envelope = *envelope;
-
- TAILQ_INIT(&lks->nodes);
- memset(&xn, 0, sizeof xn);
- xn.type = EXPAND_ADDRESS;
- xn.u.mailaddr = lks->envelope.rcpt;
- lks->expand.parent = NULL;
- 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 dispatcher *dsp;
- struct rule *rule;
- struct expandnode *xn;
- int ret;
-
- lks = tree_xget(&sessions, fwreq->id);
- xn = lks->node;
- rule = lks->rule;
-
- lks->flags &= ~F_WAITING;
-
- switch (fwreq->status) {
- case 0:
- /* permanent failure while lookup ~/.forward */
- log_trace(TRACE_EXPAND, "expand: ~/.forward failed for user %s",
- fwreq->user);
- lks->error = LKA_PERMFAIL;
- break;
- case 1:
- if (fd == -1) {
- dsp = dict_get(env->sc_dispatchers, lks->rule->dispatcher);
- if (dsp->u.local.forward_only) {
- log_trace(TRACE_EXPAND, "expand: no .forward "
- "for user %s on forward-only rule", fwreq->user);
- lks->error = LKA_TEMPFAIL;
- }
- else if (dsp->u.local.expand_only) {
- log_trace(TRACE_EXPAND, "expand: no .forward "
- "for user %s and no default action on rule", fwreq->user);
- lks->error = LKA_PERMFAIL;
- }
- else {
- log_trace(TRACE_EXPAND, "expand: no .forward for "
- "user %s, just deliver", fwreq->user);
- lka_submit(lks, rule, xn);
- }
- }
- else {
- dsp = dict_get(env->sc_dispatchers, rule->dispatcher);
-
- /* expand for the current user and rule */
- lks->expand.rule = rule;
- lks->expand.parent = xn;
-
- /* forwards_get() will close the descriptor no matter what */
- ret = forwards_get(fd, &lks->expand);
- if (ret == -1) {
- log_trace(TRACE_EXPAND, "expand: temporary "
- "forward error for user %s", fwreq->user);
- lks->error = LKA_TEMPFAIL;
- }
- else if (ret == 0) {
- if (dsp->u.local.forward_only) {
- log_trace(TRACE_EXPAND, "expand: empty .forward "
- "for user %s on forward-only rule", fwreq->user);
- lks->error = LKA_TEMPFAIL;
- }
- else if (dsp->u.local.expand_only) {
- log_trace(TRACE_EXPAND, "expand: empty .forward "
- "for user %s and no default action on rule", fwreq->user);
- lks->error = LKA_PERMFAIL;
- }
- else {
- log_trace(TRACE_EXPAND, "expand: empty .forward "
- "for user %s, just deliver", fwreq->user);
- lka_submit(lks, rule, xn);
- }
- }
- }
- break;
- default:
- /* temporary failure while looking up ~/.forward */
- lks->error = LKA_TEMPFAIL;
- }
-
- if (lks->error == LKA_TEMPFAIL && lks->errormsg == NULL)
- lks->errormsg = "424 4.2.4 Mailing list expansion problem";
- if (lks->error == LKA_PERMFAIL && lks->errormsg == NULL)
- lks->errormsg = "524 5.2.4 Mailing list expansion problem";
-
- lka_resume(lks);
-}
-
-static void
-lka_resume(struct lka_session *lks)
-{
- struct envelope *ep;
- struct expandnode *xn;
-
- if (lks->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->error)
- goto error;
- }
-
- /* delivery list is empty, reject */
- if (TAILQ_FIRST(&lks->deliverylist) == NULL) {
- log_trace(TRACE_EXPAND, "expand: lka_done: expanded to empty "
- "delivery list");
- lks->error = LKA_PERMFAIL;
- lks->errormsg = "524 5.2.4 Mailing list expansion problem";
- }
- error:
- if (lks->error) {
- m_create(p_pony, IMSG_SMTP_EXPAND_RCPT, 0, 0, -1);
- m_add_id(p_pony, lks->id);
- m_add_int(p_pony, lks->error);
-
- if (lks->errormsg)
- m_add_string(p_pony, lks->errormsg);
- else {
- if (lks->error == LKA_PERMFAIL)
- m_add_string(p_pony, "550 Invalid recipient");
- else if (lks->error == LKA_TEMPFAIL)
- m_add_string(p_pony, "451 Temporary failure");
- }
-
- m_close(p_pony);
- 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);
- m_create(p_queue, IMSG_LKA_ENVELOPE_SUBMIT, 0, 0, -1);
- m_add_id(p_queue, lks->id);
- m_add_envelope(p_queue, ep);
- m_close(p_queue);
- free(ep);
- }
-
- m_create(p_queue, IMSG_LKA_ENVELOPE_COMMIT, 0, 0, -1);
- m_add_id(p_queue, lks->id);
- m_close(p_queue);
- }
-
- expand_clear(&lks->expand);
- tree_xpop(&sessions, lks->id);
- free(lks);
-}
-
-static void
-lka_expand(struct lka_session *lks, struct rule *rule, struct expandnode *xn)
-{
- struct forward_req fwreq;
- struct envelope ep;
- struct expandnode node;
- struct mailaddr maddr;
- struct dispatcher *dsp;
- struct table *userbase;
- int r;
- union lookup lk;
- char *tag;
- const char *srs_decoded;
-
- if (xn->depth >= EXPAND_DEPTH) {
- log_trace(TRACE_EXPAND, "expand: lka_expand: node too deep.");
- lks->error = LKA_PERMFAIL;
- lks->errormsg = "524 5.2.4 Mailing list expansion problem";
- return;
- }
-
- switch (xn->type) {
- case EXPAND_INVALID:
- case EXPAND_INCLUDE:
- fatalx("lka_expand: unexpected type");
- break;
-
- case EXPAND_ADDRESS:
-
- log_trace(TRACE_EXPAND, "expand: lka_expand: address: %s@%s "
- "[depth=%d]",
- xn->u.mailaddr.user, xn->u.mailaddr.domain, xn->depth);
-
-
- ep = lks->envelope;
- ep.dest = xn->u.mailaddr;
- if (xn->parent) /* nodes with parent are forward addresses */
- ep.flags |= EF_INTERNAL;
-
- /* handle SRS */
- if (env->sc_srs_key != NULL &&
- ep.sender.user[0] == '\0' &&
- (strncasecmp(ep.rcpt.user, "SRS0=", 5) == 0 ||
- strncasecmp(ep.rcpt.user, "SRS1=", 5) == 0)) {
- srs_decoded = srs_decode(mailaddr_to_text(&ep.rcpt));
- if (srs_decoded &&
- text_to_mailaddr(&ep.rcpt, srs_decoded)) {
- /* flag envelope internal and override rcpt */
- ep.flags |= EF_INTERNAL;
- xn->u.mailaddr = ep.rcpt;
- lks->envelope = ep;
- }
- else {
- log_warn("SRS failed to decode: %s",
- mailaddr_to_text(&ep.rcpt));
- }
- }
-
- /* Pass the node through the ruleset */
- rule = ruleset_match(&ep);
- if (rule == NULL || rule->reject) {
- lks->error = (errno == EAGAIN) ?
- LKA_TEMPFAIL : LKA_PERMFAIL;
- break;
- }
-
- dsp = dict_xget(env->sc_dispatchers, rule->dispatcher);
- if (dsp->type == DISPATCHER_REMOTE) {
- lka_submit(lks, rule, xn);
- }
- else if (dsp->u.local.table_virtual) {
- /* expand */
- lks->expand.rule = rule;
- lks->expand.parent = xn;
-
- /* temporary replace the mailaddr with a copy where
- * we eventually strip the '+'-part before lookup.
- */
- maddr = xn->u.mailaddr;
- xlowercase(maddr.user, xn->u.mailaddr.user,
- sizeof maddr.user);
- r = aliases_virtual_get(&lks->expand, &maddr);
- if (r == -1) {
- lks->error = LKA_TEMPFAIL;
- log_trace(TRACE_EXPAND, "expand: lka_expand: "
- "error in virtual alias lookup");
- }
- else if (r == 0) {
- lks->error = LKA_PERMFAIL;
- log_trace(TRACE_EXPAND, "expand: lka_expand: "
- "no aliases for virtual");
- }
- if (lks->error == LKA_TEMPFAIL && lks->errormsg == NULL)
- lks->errormsg = "424 4.2.4 Mailing list expansion problem";
- if (lks->error == LKA_PERMFAIL && lks->errormsg == NULL)
- lks->errormsg = "524 5.2.4 Mailing list expansion problem";
- }
- else {
- lks->expand.rule = rule;
- lks->expand.parent = xn;
- xn->rule = rule;
-
- memset(&node, 0, sizeof node);
- node.type = EXPAND_USERNAME;
- xlowercase(node.u.user, xn->u.mailaddr.user,
- sizeof node.u.user);
- expand_insert(&lks->expand, &node);
- }
- break;
-
- case EXPAND_USERNAME:
- log_trace(TRACE_EXPAND, "expand: lka_expand: username: %s "
- "[depth=%d, sameuser=%d]",
- xn->u.user, xn->depth, xn->sameuser);
-
- /* expand aliases with the given rule */
- dsp = dict_xget(env->sc_dispatchers, rule->dispatcher);
-
- lks->expand.rule = rule;
- lks->expand.parent = xn;
-
- if (!xn->sameuser &&
- (dsp->u.local.table_alias || dsp->u.local.table_virtual)) {
- if (dsp->u.local.table_alias)
- r = aliases_get(&lks->expand, xn->u.user);
- if (dsp->u.local.table_virtual)
- r = aliases_virtual_get(&lks->expand, &xn->u.mailaddr);
- if (r == -1) {
- log_trace(TRACE_EXPAND, "expand: lka_expand: "
- "error in alias lookup");
- lks->error = LKA_TEMPFAIL;
- if (lks->errormsg == NULL)
- lks->errormsg = "424 4.2.4 Mailing list expansion problem";
- }
- if (r)
- break;
- }
-
- /* gilles+hackers@ -> gilles@ */
- if ((tag = strchr(xn->u.user, *env->sc_subaddressing_delim)) != NULL) {
- *tag++ = '\0';
- (void)strlcpy(xn->subaddress, tag, sizeof xn->subaddress);
- }
-
- userbase = table_find(env, dsp->u.local.table_userbase);
- r = table_lookup(userbase, K_USERINFO, xn->u.user, &lk);
- if (r == -1) {
- log_trace(TRACE_EXPAND, "expand: lka_expand: "
- "backend error while searching user");
- lks->error = LKA_TEMPFAIL;
- break;
- }
- if (r == 0) {
- log_trace(TRACE_EXPAND, "expand: lka_expand: "
- "user-part does not match system user");
- lks->error = LKA_PERMFAIL;
- break;
- }
- xn->realuser = 1;
-
- if (xn->sameuser && xn->parent->forwarded) {
- log_trace(TRACE_EXPAND, "expand: lka_expand: same "
- "user, submitting");
- lka_submit(lks, rule, xn);
- break;
- }
-
- /* no aliases found, query forward file */
- lks->rule = rule;
- lks->node = xn;
- xn->forwarded = 1;
-
- memset(&fwreq, 0, sizeof(fwreq));
- fwreq.id = lks->id;
- (void)strlcpy(fwreq.user, lk.userinfo.username, sizeof(fwreq.user));
- (void)strlcpy(fwreq.directory, lk.userinfo.directory, sizeof(fwreq.directory));
- fwreq.uid = lk.userinfo.uid;
- fwreq.gid = lk.userinfo.gid;
-
- m_compose(p_parent, IMSG_LKA_OPEN_FORWARD, 0, 0, -1,
- &fwreq, sizeof(fwreq));
- lks->flags |= F_WAITING;
- break;
-
- case EXPAND_FILENAME:
- dsp = dict_xget(env->sc_dispatchers, rule->dispatcher);
- if (dsp->u.local.forward_only) {
- log_trace(TRACE_EXPAND, "expand: filename matched on forward-only rule");
- lks->error = LKA_TEMPFAIL;
- break;
- }
- log_trace(TRACE_EXPAND, "expand: lka_expand: filename: %s "
- "[depth=%d]", xn->u.buffer, xn->depth);
- lka_submit(lks, rule, xn);
- break;
-
- case EXPAND_ERROR:
- dsp = dict_xget(env->sc_dispatchers, rule->dispatcher);
- if (dsp->u.local.forward_only) {
- log_trace(TRACE_EXPAND, "expand: error matched on forward-only rule");
- lks->error = LKA_TEMPFAIL;
- break;
- }
- log_trace(TRACE_EXPAND, "expand: lka_expand: error: %s "
- "[depth=%d]", xn->u.buffer, xn->depth);
- if (xn->u.buffer[0] == '4')
- lks->error = LKA_TEMPFAIL;
- else if (xn->u.buffer[0] == '5')
- lks->error = LKA_PERMFAIL;
- lks->errormsg = xn->u.buffer;
- break;
-
- case EXPAND_FILTER:
- dsp = dict_xget(env->sc_dispatchers, rule->dispatcher);
- if (dsp->u.local.forward_only) {
- log_trace(TRACE_EXPAND, "expand: filter matched on forward-only rule");
- lks->error = LKA_TEMPFAIL;
- break;
- }
- log_trace(TRACE_EXPAND, "expand: lka_expand: filter: %s "
- "[depth=%d]", xn->u.buffer, xn->depth);
- lka_submit(lks, rule, xn);
- break;
- }
-}
-
-static struct expandnode *
-lka_find_ancestor(struct expandnode *xn, enum expand_type type)
-{
- while (xn && (xn->type != type))
- xn = xn->parent;
- if (xn == NULL) {
- log_warnx("warn: lka_find_ancestor: no ancestors of type %d",
- type);
- fatalx(NULL);
- }
- return (xn);
-}
-
-static void
-lka_submit(struct lka_session *lks, struct rule *rule, struct expandnode *xn)
-{
- struct envelope *ep;
- struct dispatcher *dsp;
- const char *user;
- const char *format;
-
- ep = xmemdup(&lks->envelope, sizeof *ep);
- (void)strlcpy(ep->dispatcher, rule->dispatcher, sizeof ep->dispatcher);
-
- dsp = dict_xget(env->sc_dispatchers, ep->dispatcher);
-
- switch (dsp->type) {
- case DISPATCHER_REMOTE:
- if (xn->type != EXPAND_ADDRESS)
- fatalx("lka_deliver: expect address");
- ep->type = D_MTA;
- ep->dest = xn->u.mailaddr;
- break;
-
- case DISPATCHER_BOUNCE:
- case DISPATCHER_LOCAL:
- if (xn->type != EXPAND_USERNAME &&
- xn->type != EXPAND_FILENAME &&
- xn->type != EXPAND_FILTER)
- fatalx("lka_deliver: wrong type: %d", xn->type);
-
- ep->type = D_MDA;
- ep->dest = lka_find_ancestor(xn, EXPAND_ADDRESS)->u.mailaddr;
- if (xn->type == EXPAND_USERNAME) {
- (void)strlcpy(ep->mda_user, xn->u.user, sizeof(ep->mda_user));
- (void)strlcpy(ep->mda_subaddress, xn->subaddress, sizeof(ep->mda_subaddress));
- }
- else {
- user = !xn->parent->realuser ?
- SMTPD_USER :
- xn->parent->u.user;
- (void)strlcpy(ep->mda_user, user, sizeof (ep->mda_user));
-
- /* this battle needs to be fought ... */
- if (xn->type == EXPAND_FILTER &&
- strcmp(ep->mda_user, SMTPD_USER) == 0)
- log_warnx("commands executed from aliases "
- "run with %s privileges", SMTPD_USER);
-
- if (xn->type == EXPAND_FILENAME)
- format = PATH_LIBEXEC"/mail.mboxfile -f %%{mbox.from} %s";
- else if (xn->type == EXPAND_FILTER)
- format = "%s";
- (void)snprintf(ep->mda_exec, sizeof(ep->mda_exec),
- format, xn->u.buffer);
- }
- break;
- }
-
- TAILQ_INSERT_TAIL(&lks->deliverylist, ep, entry);
-}