diff options
author | Gilles Chehade <gilles@cvs.openbsd.org> | 2013-01-26 09:37:25 +0000 |
---|---|---|
committer | Gilles Chehade <gilles@cvs.openbsd.org> | 2013-01-26 09:37:25 +0000 |
commit | 52e93b0e61fd0a116dbb373054e2cd0ea3bfcf39 (patch) | |
tree | 41934d0fc43bfebf55ba5a199e0d699adf24aff1 /usr.sbin/smtpd/aliases.c | |
parent | 3b78bd2481525635417ca0fc75396ef754c09171 (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.c | 326 |
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; -} |