diff options
Diffstat (limited to 'mda_variables.c')
-rw-r--r-- | mda_variables.c | 372 |
1 files changed, 0 insertions, 372 deletions
diff --git a/mda_variables.c b/mda_variables.c deleted file mode 100644 index 4558305e..00000000 --- a/mda_variables.c +++ /dev/null @@ -1,372 +0,0 @@ -/* $OpenBSD: mda_variables.c,v 1.6 2019/09/19 07:35:36 gilles Exp $ */ - -/* - * Copyright (c) 2011-2017 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 <sys/types.h> -#include <sys/queue.h> -#include <sys/tree.h> -#include <sys/socket.h> - -#include <netinet/in.h> - -#include <imsg.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 - -ssize_t mda_expand_format(char *, size_t, const struct deliver *, - const struct userinfo *, const char *); -static ssize_t mda_expand_token(char *, size_t, const char *, - const struct deliver *, const struct userinfo *, const char *); -static int mod_lowercase(char *, size_t); -static int mod_uppercase(char *, size_t); -static int mod_strip(char *, size_t); - -static struct modifiers { - char *name; - int (*f)(char *buf, size_t len); -} token_modifiers[] = { - { "lowercase", mod_lowercase }, - { "uppercase", mod_uppercase }, - { "strip", mod_strip }, - { "raw", NULL }, /* special case, must stay last */ -}; - -#define MAXTOKENLEN 128 - -static ssize_t -mda_expand_token(char *dest, size_t len, const char *token, - const struct deliver *dlv, const struct userinfo *ui, const char *mda_command) -{ - char rtoken[MAXTOKENLEN]; - char tmp[EXPAND_BUFFER]; - const char *string; - char *lbracket, *rbracket, *content, *sep, *mods; - ssize_t i; - ssize_t begoff, endoff; - const char *errstr = NULL; - int replace = 1; - int raw = 0; - - begoff = 0; - endoff = EXPAND_BUFFER; - mods = NULL; - - if (strlcpy(rtoken, token, sizeof rtoken) >= sizeof rtoken) - return -1; - - /* token[x[:y]] -> extracts optional x and y, converts into offsets */ - if ((lbracket = strchr(rtoken, '[')) && - (rbracket = strchr(rtoken, ']'))) { - /* ] before [ ... or empty */ - if (rbracket < lbracket || rbracket - lbracket <= 1) - return -1; - - *lbracket = *rbracket = '\0'; - content = lbracket + 1; - - if ((sep = strchr(content, ':')) == NULL) - endoff = begoff = strtonum(content, -EXPAND_BUFFER, - EXPAND_BUFFER, &errstr); - else { - *sep = '\0'; - if (content != sep) - begoff = strtonum(content, -EXPAND_BUFFER, - EXPAND_BUFFER, &errstr); - if (*(++sep)) { - if (errstr == NULL) - endoff = strtonum(sep, -EXPAND_BUFFER, - EXPAND_BUFFER, &errstr); - } - } - if (errstr) - return -1; - - /* token:mod_1,mod_2,mod_n -> extract modifiers */ - mods = strchr(rbracket + 1, ':'); - } else { - if ((mods = strchr(rtoken, ':')) != NULL) - *mods++ = '\0'; - } - - /* token -> expanded token */ - if (!strcasecmp("sender", rtoken)) { - if (snprintf(tmp, sizeof tmp, "%s@%s", - dlv->sender.user, dlv->sender.domain) >= (int)sizeof tmp) - return -1; - if (strcmp(tmp, "@") == 0) - (void)strlcpy(tmp, "", sizeof tmp); - string = tmp; - } - else if (!strcasecmp("rcpt", rtoken)) { - if (snprintf(tmp, sizeof tmp, "%s@%s", - dlv->rcpt.user, dlv->rcpt.domain) >= (int)sizeof tmp) - return -1; - if (strcmp(tmp, "@") == 0) - (void)strlcpy(tmp, "", sizeof tmp); - string = tmp; - } - else if (!strcasecmp("dest", rtoken)) { - if (snprintf(tmp, sizeof tmp, "%s@%s", - dlv->dest.user, dlv->dest.domain) >= (int)sizeof tmp) - return -1; - if (strcmp(tmp, "@") == 0) - (void)strlcpy(tmp, "", sizeof tmp); - string = tmp; - } - else if (!strcasecmp("sender.user", rtoken)) - string = dlv->sender.user; - else if (!strcasecmp("sender.domain", rtoken)) - string = dlv->sender.domain; - else if (!strcasecmp("user.username", rtoken)) - string = ui->username; - else if (!strcasecmp("user.directory", rtoken)) { - string = ui->directory; - replace = 0; - } - else if (!strcasecmp("rcpt.user", rtoken)) - string = dlv->rcpt.user; - else if (!strcasecmp("rcpt.domain", rtoken)) - string = dlv->rcpt.domain; - else if (!strcasecmp("dest.user", rtoken)) - string = dlv->dest.user; - else if (!strcasecmp("dest.domain", rtoken)) - string = dlv->dest.domain; - else if (!strcasecmp("mda", rtoken)) { - string = mda_command; - replace = 0; - } - else if (!strcasecmp("mbox.from", rtoken)) { - if (snprintf(tmp, sizeof tmp, "%s@%s", - dlv->sender.user, dlv->sender.domain) >= (int)sizeof tmp) - return -1; - if (strcmp(tmp, "@") == 0) - (void)strlcpy(tmp, "MAILER-DAEMON", sizeof tmp); - string = tmp; - } - else - return -1; - - if (string != tmp) { - if (strlcpy(tmp, string, sizeof tmp) >= sizeof tmp) - return -1; - string = tmp; - } - - /* apply modifiers */ - if (mods != NULL) { - do { - if ((sep = strchr(mods, '|')) != NULL) - *sep++ = '\0'; - for (i = 0; (size_t)i < nitems(token_modifiers); ++i) { - if (!strcasecmp(token_modifiers[i].name, mods)) { - if (token_modifiers[i].f == NULL) { - raw = 1; - break; - } - if (!token_modifiers[i].f(tmp, sizeof tmp)) - return -1; /* modifier error */ - break; - } - } - if ((size_t)i == nitems(token_modifiers)) - return -1; /* modifier not found */ - } while ((mods = sep) != NULL); - } - - if (!raw && replace) - for (i = 0; (size_t)i < strlen(tmp); ++i) - if (strchr(MAILADDR_ESCAPE, tmp[i])) - tmp[i] = ':'; - - /* expanded string is empty */ - i = strlen(string); - if (i == 0) - return 0; - - /* begin offset beyond end of string */ - if (begoff >= i) - return -1; - - /* end offset beyond end of string, make it end of string */ - if (endoff >= i) - endoff = i - 1; - - /* negative begin offset, make it relative to end of string */ - if (begoff < 0) - begoff += i; - /* negative end offset, make it relative to end of string, - * note that end offset is inclusive. - */ - if (endoff < 0) - endoff += i - 1; - - /* check that final offsets are valid */ - if (begoff < 0 || endoff < 0 || endoff < begoff) - return -1; - endoff += 1; /* end offset is inclusive */ - - /* check that substring does not exceed destination buffer length */ - i = endoff - begoff; - if ((size_t)i + 1 >= len) - return -1; - - string += begoff; - for (; i; i--) { - *dest = *string; - dest++; - string++; - } - - return endoff - begoff; -} - - -ssize_t -mda_expand_format(char *buf, size_t len, const struct deliver *dlv, - const struct userinfo *ui, const char *mda_command) -{ - char tmpbuf[EXPAND_BUFFER], *ptmp, *pbuf, *ebuf; - char exptok[EXPAND_BUFFER]; - ssize_t exptoklen; - char token[MAXTOKENLEN]; - size_t ret, tmpret; - - if (len < sizeof tmpbuf) { - log_warnx("mda_expand_format: tmp buffer < rule buffer"); - return -1; - } - - memset(tmpbuf, 0, sizeof tmpbuf); - pbuf = buf; - ptmp = tmpbuf; - ret = tmpret = 0; - - /* special case: ~/ only allowed expanded at the beginning */ - if (strncmp(pbuf, "~/", 2) == 0) { - tmpret = snprintf(ptmp, sizeof tmpbuf, "%s/", ui->directory); - if (tmpret >= sizeof tmpbuf) { - log_warnx("warn: user directory for %s too large", - ui->directory); - return 0; - } - ret += tmpret; - ptmp += tmpret; - pbuf += 2; - } - - - /* expansion loop */ - for (; *pbuf && ret < sizeof tmpbuf; ret += tmpret) { - if (*pbuf == '%' && *(pbuf + 1) == '%') { - *ptmp++ = *pbuf++; - pbuf += 1; - tmpret = 1; - continue; - } - - if (*pbuf != '%' || *(pbuf + 1) != '{') { - *ptmp++ = *pbuf++; - tmpret = 1; - continue; - } - - /* %{...} otherwise fail */ - if (*(pbuf+1) != '{' || (ebuf = strchr(pbuf+1, '}')) == NULL) - return 0; - - /* extract token from %{token} */ - if ((size_t)(ebuf - pbuf) - 1 >= sizeof token) - return 0; - - memcpy(token, pbuf+2, ebuf-pbuf-1); - if (strchr(token, '}') == NULL) - return 0; - *strchr(token, '}') = '\0'; - - exptoklen = mda_expand_token(exptok, sizeof exptok, token, dlv, - ui, mda_command); - if (exptoklen == -1) - return -1; - - /* writing expanded token at ptmp will overflow tmpbuf */ - if (sizeof (tmpbuf) - (ptmp - tmpbuf) <= (size_t)exptoklen) - return -1; - - memcpy(ptmp, exptok, exptoklen); - pbuf = ebuf + 1; - ptmp += exptoklen; - tmpret = exptoklen; - } - if (ret >= sizeof tmpbuf) - return -1; - - if ((ret = strlcpy(buf, tmpbuf, len)) >= len) - return -1; - - return ret; -} - -static int -mod_lowercase(char *buf, size_t len) -{ - char tmp[EXPAND_BUFFER]; - - if (!lowercase(tmp, buf, sizeof tmp)) - return 0; - if (strlcpy(buf, tmp, len) >= len) - return 0; - return 1; -} - -static int -mod_uppercase(char *buf, size_t len) -{ - char tmp[EXPAND_BUFFER]; - - if (!uppercase(tmp, buf, sizeof tmp)) - return 0; - if (strlcpy(buf, tmp, len) >= len) - return 0; - return 1; -} - -static int -mod_strip(char *buf, size_t len) -{ - char *tag, *at; - unsigned int i; - - /* gilles+hackers -> gilles */ - if ((tag = strchr(buf, *env->sc_subaddressing_delim)) != NULL) { - /* gilles+hackers@poolp.org -> gilles@poolp.org */ - if ((at = strchr(tag, '@')) != NULL) { - for (i = 0; i <= strlen(at); ++i) - tag[i] = at[i]; - } else - *tag = '\0'; - } - return 1; -} |