diff options
Diffstat (limited to 'usr.sbin/smtpd/lka_session.c')
-rw-r--r-- | usr.sbin/smtpd/lka_session.c | 99 |
1 files changed, 92 insertions, 7 deletions
diff --git a/usr.sbin/smtpd/lka_session.c b/usr.sbin/smtpd/lka_session.c index 3d79254fc7c..95aaa3f4a60 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.56 2013/05/24 17:03:14 eric Exp $ */ +/* $OpenBSD: lka_session.c,v 1.57 2013/07/19 08:12:19 eric Exp $ */ /* * Copyright (c) 2011 Gilles Chehade <gilles@poolp.org> @@ -40,6 +40,8 @@ #include "smtpd.h" #include "log.h" +#define TAG_CHAR '+' /* gilles+tag@ */ + #define EXPAND_DEPTH 10 #define F_WAITING 0x01 @@ -70,6 +72,19 @@ 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 int mod_lowercase(char *, size_t); +static int mod_uppercase(char *, size_t); +static int mod_strip(char *, size_t); + +struct modifiers { + char *name; + int (*f)(char *buf, size_t len); +} token_modifiers[] = { + { "lowercase", mod_lowercase }, + { "uppercase", mod_uppercase }, + { "strip", mod_strip }, +}; + static int init; static struct tree sessions; @@ -523,7 +538,7 @@ lka_expand_token(char *dest, size_t len, const char *token, char rtoken[MAXTOKENLEN]; char tmp[EXPAND_BUFFER]; const char *string; - char *lbracket, *rbracket, *content, *sep; + char *lbracket, *rbracket, *content, *sep, *mods; ssize_t i; ssize_t begoff, endoff; const char *errstr = NULL; @@ -531,6 +546,7 @@ lka_expand_token(char *dest, size_t len, const char *token, begoff = 0; endoff = EXPAND_BUFFER; + mods = NULL; if (strlcpy(rtoken, token, sizeof rtoken) >= sizeof rtoken) return 0; @@ -561,6 +577,12 @@ lka_expand_token(char *dest, size_t len, const char *token, } if (errstr) return 0; + + /* token:mod_1,mod_2,mod_n -> extract modifiers */ + mods = strchr(rbracket + 1, ':'); + } else { + if ((mods = strchr(rtoken, ':')) != NULL) + *mods++ = '\0'; } /* token -> expanded token */ @@ -603,6 +625,30 @@ lka_expand_token(char *dest, size_t len, const char *token, else return 0; + /* apply modifiers */ + if (mods != NULL) { + /* make sure we are working on tmp */ + if (string != tmp) { + if (strlcpy(tmp, string, sizeof tmp) >= sizeof tmp) + return 0; + string = tmp; + } + + do { + if ((sep = strchr(mods, '|')) != NULL) + *sep++ = '\0'; + for (i = 0; (size_t)i < nitems(token_modifiers); ++i) { + if (! strcmp(token_modifiers[i].name, mods)) { + if (! token_modifiers[i].f(tmp, sizeof tmp)) + return 0; /* modifier error */ + break; + } + } + if ((size_t)i == nitems(token_modifiers)) + return 0; /* modifier not found */ + } while ((mods = sep) != NULL); + } + /* expanded string is empty */ i = strlen(string); if (i == 0) @@ -711,9 +757,6 @@ lka_expand_format(char *buf, size_t len, const struct envelope *ep, if (exptoklen == 0) return 0; - if (! lowercase(exptok, exptok, sizeof exptok)) - return 0; - memcpy(ptmp, exptok, exptoklen); pbuf = ebuf + 1; ptmp += exptoklen; @@ -736,7 +779,7 @@ mailaddr_to_username(const struct mailaddr *maddr, char *dst, size_t len) xlowercase(dst, maddr->user, len); /* gilles+hackers@ -> gilles@ */ - if ((tag = strchr(dst, '+')) != NULL) + if ((tag = strchr(dst, TAG_CHAR)) != NULL) *tag++ = '\0'; } @@ -745,7 +788,7 @@ mailaddr_tag(const struct mailaddr *maddr) { const char *tag; - if ((tag = strchr(maddr->user, '+'))) { + if ((tag = strchr(maddr->user, TAG_CHAR))) { tag++; while (*tag == '.') tag++; @@ -753,3 +796,45 @@ mailaddr_tag(const struct mailaddr *maddr) return (tag); } + +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, TAG_CHAR)) != 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; +} |