diff options
author | Eric Faurot <eric@cvs.openbsd.org> | 2013-07-19 08:12:20 +0000 |
---|---|---|
committer | Eric Faurot <eric@cvs.openbsd.org> | 2013-07-19 08:12:20 +0000 |
commit | 8a6e995d6c6cb7f0968a1203e816e5d8f4500931 (patch) | |
tree | fd9c106e0dbec67e8bfa738ebd5508caa05bb4a3 | |
parent | 812724ba80ed5f0b9efd1b86ad3ac00072b96f02 (diff) |
Introduce expand string modifiers
-rw-r--r-- | usr.sbin/smtpd/lka_session.c | 99 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.conf.5 | 13 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 3 | ||||
-rw-r--r-- | usr.sbin/smtpd/util.c | 19 |
4 files changed, 123 insertions, 11 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; +} diff --git a/usr.sbin/smtpd/smtpd.conf.5 b/usr.sbin/smtpd/smtpd.conf.5 index 427ab497634..aa8fbacc50e 100644 --- a/usr.sbin/smtpd/smtpd.conf.5 +++ b/usr.sbin/smtpd/smtpd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: smtpd.conf.5,v 1.97 2013/06/26 07:22:20 gilles Exp $ +.\" $OpenBSD: smtpd.conf.5,v 1.98 2013/07/19 08:12:19 eric Exp $ .\" .\" Copyright (c) 2008 Janne Johansson <jj@openbsd.org> .\" Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net> @@ -17,7 +17,7 @@ .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .\" -.Dd $Mdocdate: June 26 2013 $ +.Dd $Mdocdate: July 19 2013 $ .Dt SMTPD.CONF 5 .Os .Sh NAME @@ -90,6 +90,15 @@ For example, with recipient domain "example.org": %{rcpt.domain[0:-4]} expands to "example" .Ed .Pp +In addition, modifiers may be applied to the token. +For example, with recipient "User+Tag@Example.org": +.Bd -literal -offset indent +%{rcpt:lowercase} expands to "user+tag@example.org" +%{rcpt:uppercase} expands to "USER+TAG@EXAMPLE.ORG" +%{rcpt:strip} expands to "User@Example.org" +%{rcpt:lowercase|strip} expands to "user@example.org" +.Ed +.Pp Additional configuration files can be included with the .Ic include keyword, for example: diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h index 10afc9a3e27..48289ad8faa 100644 --- a/usr.sbin/smtpd/smtpd.h +++ b/usr.sbin/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.413 2013/07/19 07:49:08 eric Exp $ */ +/* $OpenBSD: smtpd.h,v 1.414 2013/07/19 08:12:19 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org> @@ -1362,6 +1362,7 @@ int valid_domainpart(const char *); int secure_file(int, char *, char *, uid_t, int); int lowercase(char *, const char *, size_t); void xlowercase(char *, const char *, size_t); +int uppercase(char *, const char *, size_t); uint64_t generate_uid(void); void fdlimit(double); int availdesc(void); diff --git a/usr.sbin/smtpd/util.c b/usr.sbin/smtpd/util.c index 453706821ea..02c0055a0c1 100644 --- a/usr.sbin/smtpd/util.c +++ b/usr.sbin/smtpd/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.95 2013/07/19 07:37:29 eric Exp $ */ +/* $OpenBSD: util.c,v 1.96 2013/07/19 08:12:19 eric Exp $ */ /* * Copyright (c) 2000,2001 Markus Friedl. All rights reserved. @@ -596,6 +596,23 @@ lowercase(char *buf, const char *s, size_t len) return 1; } +int +uppercase(char *buf, const char *s, size_t len) +{ + if (len == 0) + return 0; + + if (strlcpy(buf, s, len) >= len) + return 0; + + while (*buf != '\0') { + *buf = toupper((int)*buf); + buf++; + } + + return 1; +} + void xlowercase(char *buf, const char *s, size_t len) { |