summaryrefslogtreecommitdiff
path: root/usr.sbin/smtpd/aliases.c
diff options
context:
space:
mode:
authorGilles Chehade <gilles@cvs.openbsd.org>2013-01-26 09:37:25 +0000
committerGilles Chehade <gilles@cvs.openbsd.org>2013-01-26 09:37:25 +0000
commit52e93b0e61fd0a116dbb373054e2cd0ea3bfcf39 (patch)
tree41934d0fc43bfebf55ba5a199e0d699adf24aff1 /usr.sbin/smtpd/aliases.c
parent3b78bd2481525635417ca0fc75396ef754c09171 (diff)
Sync with our smtpd repo:
* first bricks of ldap and sqlite support (not finished but both working) * new table API to replace map API, all lookups are done through tables * improved handling of temporary errors throughout the daemon * improved scheduler and mta logic: connection reuse, optimizes batches * improved queue: more tolerant to admin errors, new layout, less disk-IO * improved memory usage under high load * SSL certs/keys isolated to lookup process to avoid facing network * VIRTUAL support improved, fully virtual setups possible now * runtime tracing of processes through smtpctl trace * ssl_privsep.c sync-ed with relayd * ssl.c no longer contains smtpd specific interfaces * smtpd-specific ssl bits moved to ssl_smtpd.c * update mail address in copyright FLUSH YOUR QUEUE. FLUSH YOUR QUEUE. FLUSH YOUR QUEUE. FLUSH YOUR QUEUE. smtpd.conf(5) simplified, it will require adaptations ok eric@
Diffstat (limited to 'usr.sbin/smtpd/aliases.c')
-rw-r--r--usr.sbin/smtpd/aliases.c326
1 files changed, 109 insertions, 217 deletions
diff --git a/usr.sbin/smtpd/aliases.c b/usr.sbin/smtpd/aliases.c
index 4827c8d34d3..c2502fa4c8f 100644
--- a/usr.sbin/smtpd/aliases.c
+++ b/usr.sbin/smtpd/aliases.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: aliases.c,v 1.58 2012/11/12 14:58:53 eric Exp $ */
+/* $OpenBSD: aliases.c,v 1.59 2013/01/26 09:37:23 gilles Exp $ */
/*
- * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
+ * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -35,103 +35,148 @@
#include "log.h"
static int aliases_expand_include(struct expand *, const char *);
-static int alias_is_filter(struct expandnode *, const char *, size_t);
-static int alias_is_username(struct expandnode *, const char *, size_t);
-static int alias_is_address(struct expandnode *, const char *, size_t);
-static int alias_is_filename(struct expandnode *, const char *, size_t);
-static int alias_is_include(struct expandnode *, const char *, size_t);
int
-aliases_get(objid_t mapid, struct expand *expand, const char *username)
+aliases_get(struct table *table, struct expand *expand, const char *username)
{
- struct map_alias *map_alias;
- struct expandnode *xn;
- char buf[MAX_LOCALPART_SIZE];
- size_t nbaliases;
+ struct expandnode *xn;
+ char buf[MAX_LOCALPART_SIZE];
+ size_t nbaliases;
+ int ret;
+ struct expand *xp = NULL;
+
xlowercase(buf, username, sizeof(buf));
- map_alias = map_lookup(mapid, buf, K_ALIAS);
- if (map_alias == NULL)
- return (errno ? -1 : 0);
+ ret = table_lookup(table, buf, K_ALIAS, (void **)&xp);
+ if (ret <= 0)
+ return ret;
- /* foreach node in map_alias expandtree, we merge */
+ /* foreach node in table_alias expandtree, we merge */
nbaliases = 0;
- RB_FOREACH(xn, expandtree, &map_alias->expand.tree) {
+ RB_FOREACH(xn, expandtree, &xp->tree) {
if (xn->type == EXPAND_INCLUDE)
- nbaliases += aliases_expand_include(expand, xn->u.buffer);
+ nbaliases += aliases_expand_include(expand,
+ xn->u.buffer);
else {
expand_insert(expand, xn);
nbaliases++;
}
}
- expand_free(&map_alias->expand);
- free(map_alias);
+ expand_free(xp);
log_debug("debug: aliases_get: returned %zd aliases", nbaliases);
return nbaliases;
}
int
-aliases_virtual_get(objid_t mapid, struct expand *expand,
- const struct mailaddr *maddr)
+aliases_virtual_check(struct table *table, const struct mailaddr *maddr)
{
- struct map_virtual *map_virtual;
- struct expandnode *xn;
- char buf[MAX_LINE_SIZE];
- char *pbuf = buf;
- int nbaliases;
+ char buf[MAX_LINE_SIZE];
+ char *pbuf;
+ int ret;
if (! bsnprintf(buf, sizeof(buf), "%s@%s", maddr->user,
maddr->domain))
- return 0;
+ return 0;
xlowercase(buf, buf, sizeof(buf));
- map_virtual = map_lookup(mapid, buf, K_VIRTUAL);
- if (map_virtual == NULL) {
- if (errno)
- return (-1);
- pbuf = strchr(buf, '@');
- map_virtual = map_lookup(mapid, pbuf, K_VIRTUAL);
- }
- if (map_virtual == NULL)
- return (errno ? -1 : 0);
+ /* First, we lookup for full entry: user@domain */
+ ret = table_lookup(table, buf, K_ALIAS, NULL);
+ if (ret < 0)
+ return (-1);
+ if (ret)
+ return 1;
- /* foreach node in map_virtual expand, we merge */
+ /* Failed ? We lookup for username only */
+ pbuf = strchr(buf, '@');
+ *pbuf = '\0';
+ ret = table_lookup(table, buf, K_ALIAS, NULL);
+ if (ret < 0)
+ return (-1);
+ if (ret)
+ return 1;
+
+ *pbuf = '@';
+ /* Failed ? We lookup for catch all for virtual domain */
+ ret = table_lookup(table, pbuf, K_ALIAS, NULL);
+ if (ret < 0)
+ return (-1);
+ if (ret)
+ return 1;
+
+ /* Failed ? We lookup for a *global* catch all */
+ ret = table_lookup(table, "@", K_ALIAS, NULL);
+ if (ret <= 0)
+ return (ret);
+
+ return 1;
+}
+
+int
+aliases_virtual_get(struct table *table, struct expand *expand,
+ const struct mailaddr *maddr)
+{
+ struct expandnode *xn;
+ struct expand *xp;
+ char buf[MAX_LINE_SIZE];
+ char *pbuf;
+ int nbaliases;
+ int ret;
+
+ if (! bsnprintf(buf, sizeof(buf), "%s@%s", maddr->user,
+ maddr->domain))
+ return 0;
+ xlowercase(buf, buf, sizeof(buf));
+
+ /* First, we lookup for full entry: user@domain */
+ ret = table_lookup(table, buf, K_ALIAS, (void **)&xp);
+ if (ret < 0)
+ return (-1);
+ if (ret)
+ goto expand;
+
+ /* Failed ? We lookup for username only */
+ pbuf = strchr(buf, '@');
+ *pbuf = '\0';
+ ret = table_lookup(table, buf, K_ALIAS, (void **)&xp);
+ if (ret < 0)
+ return (-1);
+ if (ret)
+ goto expand;
+
+ *pbuf = '@';
+ /* Failed ? We lookup for catch all for virtual domain */
+ ret = table_lookup(table, pbuf, K_ALIAS, (void **)&xp);
+ if (ret < 0)
+ return (-1);
+ if (ret)
+ goto expand;
+
+ /* Failed ? We lookup for a *global* catch all */
+ ret = table_lookup(table, "@", K_ALIAS, (void **)&xp);
+ if (ret <= 0)
+ return (ret);
+
+expand:
+ /* foreach node in table_virtual expand, we merge */
nbaliases = 0;
- RB_FOREACH(xn, expandtree, &map_virtual->expand.tree) {
+ RB_FOREACH(xn, expandtree, &xp->tree) {
if (xn->type == EXPAND_INCLUDE)
- nbaliases += aliases_expand_include(expand, xn->u.buffer);
+ nbaliases += aliases_expand_include(expand,
+ xn->u.buffer);
else {
expand_insert(expand, xn);
nbaliases++;
}
}
- expand_free(&map_virtual->expand);
- free(map_virtual);
- log_debug("debug: aliases_virtual_get: '%s' resolved to %d nodes", pbuf, nbaliases);
-
- return nbaliases;
-}
+ expand_free(xp);
-int
-aliases_vdomain_exists(objid_t mapid, const char *hostname)
-{
- struct map_virtual *map_virtual;
- char buf[MAXHOSTNAMELEN];
+ log_debug("debug: aliases_virtual_get: '%s' resolved to %d nodes",
+ buf, nbaliases);
- xlowercase(buf, hostname, sizeof(buf));
- map_virtual = map_lookup(mapid, buf, K_VIRTUAL);
- if (map_virtual == NULL)
- return (errno ? -1 : 0);
-
- /* XXX - for now the map API always allocate */
- log_debug("debug: aliases_vdomain_exist: '%s' exists", hostname);
- expand_free(&map_virtual->expand);
- free(map_virtual);
-
- return 1;
+ return nbaliases;
}
static int
@@ -139,10 +184,8 @@ aliases_expand_include(struct expand *expand, const char *filename)
{
FILE *fp;
char *line;
- size_t len;
- size_t lineno = 0;
+ size_t len, lineno = 0;
char delim[] = { '\\', '#' };
- struct expandnode xn;
fp = fopen(filename, "r");
if (fp == NULL) {
@@ -151,161 +194,10 @@ aliases_expand_include(struct expand *expand, const char *filename)
}
while ((line = fparseln(fp, &len, &lineno, delim, 0)) != NULL) {
- if (len == 0) {
- free(line);
- continue;
- }
-
- if (! alias_parse(&xn, line)) {
- log_warnx("warn: could not parse include entry \"%s\".", line);
- }
-
- if (xn.type == EXPAND_INCLUDE)
- log_warnx("warn: nested inclusion is not supported.");
- else
- expand_insert(expand, &xn);
-
+ expand_line(expand, line, 0);
free(line);
}
fclose(fp);
return 1;
}
-
-int
-alias_parse(struct expandnode *alias, char *line)
-{
- size_t l;
- char *wsp;
-
- /* remove ending whitespaces */
- wsp = line + strlen(line);
- while (wsp != line) {
- if (*wsp != '\0' && !isspace((int)*wsp))
- break;
- *wsp-- = '\0';
- }
-
- l = strlen(line);
- if (alias_is_include(alias, line, l) ||
- alias_is_filter(alias, line, l) ||
- alias_is_filename(alias, line, l) ||
- alias_is_address(alias, line, l) ||
- alias_is_username(alias, line, l))
- return (1);
-
- return (0);
-}
-
-
-static int
-alias_is_filter(struct expandnode *alias, const char *line, size_t len)
-{
- if (*line == '|') {
- if (strlcpy(alias->u.buffer, line + 1,
- sizeof(alias->u.buffer)) >= sizeof(alias->u.buffer))
- return 0;
- alias->type = EXPAND_FILTER;
- return 1;
- }
- return 0;
-}
-
-static int
-alias_is_username(struct expandnode *alias, const char *line, size_t len)
-{
- bzero(alias, sizeof *alias);
-
- if (strlcpy(alias->u.user, line,
- sizeof(alias->u.user)) >= sizeof(alias->u.user))
- return 0;
-
- while (*line) {
- if (!isalnum((int)*line) &&
- *line != '_' && *line != '.' && *line != '-')
- return 0;
- ++line;
- }
-
- alias->type = EXPAND_USERNAME;
- return 1;
-}
-
-static int
-alias_is_address(struct expandnode *alias, const char *line, size_t len)
-{
- char *domain;
-
- bzero(alias, sizeof *alias);
-
- if (len < 3) /* x@y */
- return 0;
-
- domain = strchr(line, '@');
- if (domain == NULL)
- return 0;
-
- /* @ cannot start or end an address */
- if (domain == line || domain == line + len - 1)
- return 0;
-
- /* scan pre @ for disallowed chars */
- *domain++ = '\0';
- strlcpy(alias->u.mailaddr.user, line, sizeof(alias->u.mailaddr.user));
- strlcpy(alias->u.mailaddr.domain, domain, sizeof(alias->u.mailaddr.domain));
-
- while (*line) {
- char allowedset[] = "!#$%*/?|^{}`~&'+-=_.";
- if (!isalnum((int)*line) &&
- strchr(allowedset, *line) == NULL)
- return 0;
- ++line;
- }
-
- while (*domain) {
- char allowedset[] = "-.";
- if (!isalnum((int)*domain) &&
- strchr(allowedset, *domain) == NULL)
- return 0;
- ++domain;
- }
-
- alias->type = EXPAND_ADDRESS;
- return 1;
-}
-
-static int
-alias_is_filename(struct expandnode *alias, const char *line, size_t len)
-{
- bzero(alias, sizeof *alias);
-
- if (*line != '/')
- return 0;
-
- if (strlcpy(alias->u.buffer, line,
- sizeof(alias->u.buffer)) >= sizeof(alias->u.buffer))
- return 0;
- alias->type = EXPAND_FILENAME;
- return 1;
-}
-
-static int
-alias_is_include(struct expandnode *alias, const char *line, size_t len)
-{
- size_t skip;
-
- bzero(alias, sizeof *alias);
-
- if (strncasecmp(":include:", line, 9) == 0)
- skip = 9;
- else if (strncasecmp("include:", line, 8) == 0)
- skip = 8;
- else
- return 0;
-
- if (! alias_is_filename(alias, line + skip, len - skip))
- return 0;
-
- alias->type = EXPAND_INCLUDE;
- return 1;
-}