summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Faurot <eric@cvs.openbsd.org>2013-07-19 08:12:20 +0000
committerEric Faurot <eric@cvs.openbsd.org>2013-07-19 08:12:20 +0000
commit8a6e995d6c6cb7f0968a1203e816e5d8f4500931 (patch)
treefd9c106e0dbec67e8bfa738ebd5508caa05bb4a3
parent812724ba80ed5f0b9efd1b86ad3ac00072b96f02 (diff)
Introduce expand string modifiers
-rw-r--r--usr.sbin/smtpd/lka_session.c99
-rw-r--r--usr.sbin/smtpd/smtpd.conf.513
-rw-r--r--usr.sbin/smtpd/smtpd.h3
-rw-r--r--usr.sbin/smtpd/util.c19
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)
{