diff options
-rw-r--r-- | usr.sbin/smtpd/aliases.c | 51 | ||||
-rw-r--r-- | usr.sbin/smtpd/lka.c | 57 | ||||
-rw-r--r-- | usr.sbin/smtpd/makemap.8 | 16 | ||||
-rw-r--r-- | usr.sbin/smtpd/parse.y | 24 | ||||
-rw-r--r-- | usr.sbin/smtpd/ruleset.c | 15 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 11 |
6 files changed, 123 insertions, 51 deletions
diff --git a/usr.sbin/smtpd/aliases.c b/usr.sbin/smtpd/aliases.c index 3427ce4bb2e..99aa40b03af 100644 --- a/usr.sbin/smtpd/aliases.c +++ b/usr.sbin/smtpd/aliases.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aliases.c,v 1.19 2009/08/08 00:02:22 gilles Exp $ */ +/* $OpenBSD: aliases.c,v 1.20 2009/10/11 17:40:49 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -136,19 +136,47 @@ aliases_get(struct smtpd *env, struct aliaseslist *aliases, char *username) } int -aliases_virtual_exist(struct smtpd *env, struct path *path) +aliases_vdomain_exists(struct smtpd *env, struct map *map, char *hostname) +{ + int ret; + DBT key; + DBT val; + DB *vtable; + char strkey[MAX_LINE_SIZE]; + + vtable = dbopen(map->m_config, O_RDONLY, 0600, DB_HASH, NULL); + if (vtable == NULL) { + log_warn("aliases_vdomain_exists: dbopen"); + return 0; + } + + if (! bsnprintf(strkey, sizeof(strkey), "%s", hostname)) { + vtable->close(vtable); + return 0; + } + lowercase(strkey, strkey, sizeof(strkey)); + + key.data = strkey; + key.size = strlen(key.data) + 1; + + ret = vtable->get(vtable, &key, &val, 0); + if (ret == -1) + log_warn("aliases_vdomain_exists"); + + vtable->close(vtable); + + return (ret == 0); +} + +int +aliases_virtual_exist(struct smtpd *env, struct map *map, struct path *path) { int ret; DBT key; DBT val; DB *aliasesdb; - struct map *map; char strkey[MAX_LINE_SIZE]; - map = map_findbyname(env, "virtual"); - if (map == NULL) - return 0; - aliasesdb = dbopen(map->m_config, O_RDONLY, 0600, DB_HASH, NULL); if (aliasesdb == NULL) { log_warn("aliases_virtual_exist: dbopen"); @@ -190,8 +218,8 @@ aliases_virtual_exist(struct smtpd *env, struct path *path) } int -aliases_virtual_get(struct smtpd *env, struct aliaseslist *aliases, - struct path *path) +aliases_virtual_get(struct smtpd *env, struct map *map, + struct aliaseslist *aliases, struct path *path) { int ret; DBT key; @@ -201,13 +229,8 @@ aliases_virtual_get(struct smtpd *env, struct aliaseslist *aliases, struct alias alias; struct alias *aliasp; struct alias *nextalias; - struct map *map; char strkey[MAX_LINE_SIZE]; - map = map_findbyname(env, "virtual"); - if (map == NULL) - return 0; - aliasesdb = dbopen(map->m_config, O_RDONLY, 0600, DB_HASH, NULL); if (aliasesdb == NULL) { log_warn("aliases_virtual_get: dbopen"); diff --git a/usr.sbin/smtpd/lka.c b/usr.sbin/smtpd/lka.c index a561a91b80e..8377e739e57 100644 --- a/usr.sbin/smtpd/lka.c +++ b/usr.sbin/smtpd/lka.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lka.c,v 1.65 2009/10/07 18:09:12 gilles Exp $ */ +/* $OpenBSD: lka.c,v 1.66 2009/10/11 17:40:49 gilles Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -61,8 +61,6 @@ int lka_resolve_alias(struct smtpd *, struct path *, struct alias *); int lka_parse_include(char *); int lka_check_source(struct smtpd *, struct map *, struct sockaddr_storage *); int lka_match_mask(struct sockaddr_storage *, struct netaddr *); -int aliases_virtual_get(struct smtpd *, struct aliaseslist *, struct path *); -int aliases_virtual_exist(struct smtpd *, struct path *); int lka_resolve_path(struct smtpd *, struct path *); void lka_expand_rcpt(struct smtpd *, struct aliaseslist *, struct lkasession *); int lka_expand_rcpt_iteration(struct smtpd *, struct aliaseslist *, struct lkasession *); @@ -420,7 +418,8 @@ lka_dispatch_mfa(int sig, short event, void *p) ret = aliases_get(env, &lkasession->aliaseslist, lkasession->path.user); } else if (lkasession->path.flags & F_PATH_VIRTUAL) { - ret = aliases_virtual_get(env, &lkasession->aliaseslist, &lkasession->path); + ret = aliases_virtual_get(env, lkasession->path.cond->c_match, + &lkasession->aliaseslist, &lkasession->path); } else fatal("lka_dispatch_mfa: path with illegal flag"); @@ -993,7 +992,9 @@ lka_expand_rcpt_iteration(struct smtpd *env, struct aliaseslist *aliases, struct struct alias *rmalias = NULL; struct alias *alias; struct forward_req fwreq; + struct path *lkasessionpath; + lkasessionpath = &lkasession->path; rmalias = NULL; TAILQ_FOREACH(alias, aliases, entry) { if (rmalias) { @@ -1003,7 +1004,7 @@ lka_expand_rcpt_iteration(struct smtpd *env, struct aliaseslist *aliases, struct } if (alias->type == ALIAS_ADDRESS) { - if (aliases_virtual_get(env, aliases, &alias->u.path)) { + if (aliases_virtual_get(env, lkasessionpath->cond->c_match, aliases, &alias->u.path)) { rmalias = alias; done = 0; } @@ -1043,34 +1044,44 @@ lka_expand_rcpt_iteration(struct smtpd *env, struct aliaseslist *aliases, struct int lka_resolve_path(struct smtpd *env, struct path *path) { - char username[MAXLOGNAME]; - struct passwd *pw; - char *p; - - (void)strlcpy(username, path->user, sizeof(username)); - - for (p = &username[0]; *p != '\0' && *p != '+'; ++p) - *p = tolower((int)*p); - *p = '\0'; + switch (path->cond->c_type) { + case C_DOM: { + char username[MAXLOGNAME]; + struct passwd *pw; + + lowercase(username, path->user, sizeof(username)); + if (aliases_exist(env, username)) { + path->flags |= F_PATH_ALIAS; + return 1; + } - if (aliases_virtual_exist(env, path)) - path->flags |= F_PATH_VIRTUAL; - else if (aliases_exist(env, username)) - path->flags |= F_PATH_ALIAS; - else { path->flags |= F_PATH_ACCOUNT; pw = getpwnam(username); if (pw == NULL) - return 0; + break; + (void)strlcpy(path->pw_name, pw->pw_name, sizeof(path->pw_name)); if (lka_expand(path->rule.r_value.path, - sizeof(path->rule.r_value.path), path) >= + sizeof(path->rule.r_value.path), path) >= sizeof(path->rule.r_value.path)) - return 0; + break; + + return 1; } + case C_VDOM: { - return 1; + if (aliases_virtual_exist(env, path->cond->c_match, path)) { + path->flags |= F_PATH_VIRTUAL; + return 1; + } + break; + } + default: + fatalx("lka_resolve_path: unexpected type"); + } + + return 0; } void diff --git a/usr.sbin/smtpd/makemap.8 b/usr.sbin/smtpd/makemap.8 index e3e22432b5e..791845d390a 100644 --- a/usr.sbin/smtpd/makemap.8 +++ b/usr.sbin/smtpd/makemap.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: makemap.8,v 1.9 2009/09/25 13:44:33 jmc Exp $ +.\" $OpenBSD: makemap.8,v 1.10 2009/10/11 17:40:49 gilles Exp $ .\" .\" Copyright (c) 2009 Jacek Masiulaniec <jacekm@openbsd.org> .\" Copyright (c) 2008-2009 Gilles Chechade <gilles@openbsd.org> @@ -15,7 +15,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: September 25 2009 $ +.Dd $Mdocdate: October 11 2009 $ .Dt MAKEMAP 8 .Os .Sh NAME @@ -74,19 +74,21 @@ virtual domains files. .El .Ex -std makemap .Sh VIRTUAL DOMAINS -Virtual domains are kept in the virtual map. +Virtual domains are kept in maps. To create single virtual address, add -.Dq user@example.com +.Dq user@example.com user to the virtual map. To handle all mail destined to any user at example.com, add -.Dq @example.com +.Dq @example.com user to the virtual map. .Pp In addition to adding an entry to the virtual map, -one must add a filter rule that accepts mail for the virtual domain, +one must add a filter rule that accepts mail for virtual domains, for example: .Bd -literal -offset indent -accept for domain "example.com" deliver to mbox +map "vdomains" { source db "/etc/mail/vdomains.db" } + +accept for virtual map "vdomains" deliver to mbox .Ed .Sh FILES .Bl -tag -width "/etc/mail/aliasesXXX" -compact diff --git a/usr.sbin/smtpd/parse.y b/usr.sbin/smtpd/parse.y index f60d4719bd4..f6eaeb5de33 100644 --- a/usr.sbin/smtpd/parse.y +++ b/usr.sbin/smtpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.39 2009/09/16 20:22:18 jacekm Exp $ */ +/* $OpenBSD: parse.y,v 1.40 2009/10/11 17:40:49 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -119,7 +119,7 @@ typedef struct { %token DNS DB TFILE EXTERNAL DOMAIN CONFIG SOURCE %token RELAY VIA DELIVER TO MAILDIR MBOX HOSTNAME %token ACCEPT REJECT INCLUDE NETWORK ERROR MDA FROM FOR -%token ARROW ENABLE AUTH TLS LOCAL +%token ARROW ENABLE AUTH TLS LOCAL VIRTUAL %token <v.string> STRING %token <v.number> NUMBER %type <v.map> map @@ -641,6 +641,25 @@ condition : NETWORK mapref { c->c_map = $2; $$ = c; } + | VIRTUAL MAP STRING { + struct cond *c; + struct map *m; + + if ((m = map_findbyname(conf, $3)) == NULL) { + yyerror("no such map: %s", $3); + free($3); + YYERROR; + } + free($3); + m->m_flags |= F_USED; + + + if ((c = calloc(1, sizeof *c)) == NULL) + fatal("out of memory"); + c->c_type = C_VDOM; + c->c_map = m->m_id; + $$ = c; + } | LOCAL { struct cond *c; struct map *m; @@ -934,6 +953,7 @@ lookup(char *s) { "to", TO }, { "type", TYPE }, { "via", VIA }, + { "virtual", VIRTUAL }, }; const struct keywords *p; diff --git a/usr.sbin/smtpd/ruleset.c b/usr.sbin/smtpd/ruleset.c index 53746ca1c1c..54cf904ecdb 100644 --- a/usr.sbin/smtpd/ruleset.c +++ b/usr.sbin/smtpd/ruleset.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ruleset.c,v 1.2 2009/10/07 13:29:40 jacekm Exp $ */ +/* $OpenBSD: ruleset.c,v 1.3 2009/10/11 17:40:49 gilles Exp $ */ /* * Copyright (c) 2009 Gilles Chehade <gilles@openbsd.org> @@ -67,10 +67,23 @@ ruleset_match(struct smtpd *env, struct path *path, struct sockaddr_storage *ss) map = cond->c_match; TAILQ_FOREACH(me, &map->m_contents, me_entry) { if (hostname_match(path->domain, me->me_key.med_string)) { + path->cond = cond; return r; } } } + + if (cond->c_type == C_VDOM) { + cond->c_match = map_find(env, cond->c_map); + if (cond->c_match == NULL) + fatal("failed to lookup map."); + + map = cond->c_match; + if (aliases_vdomain_exists(env, map, path->domain)) { + path->cond = cond; + return r; + } + } } } diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h index e3ff31ea65d..e4770bd45e9 100644 --- a/usr.sbin/smtpd/smtpd.h +++ b/usr.sbin/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.145 2009/10/07 18:09:12 gilles Exp $ */ +/* $OpenBSD: smtpd.h,v 1.146 2009/10/11 17:40:49 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -284,7 +284,8 @@ struct map { enum cond_type { C_ALL, C_NET, - C_DOM + C_DOM, + C_VDOM }; struct cond { @@ -345,6 +346,7 @@ enum path_flags { struct path { TAILQ_ENTRY(path) entry; struct rule rule; + struct cond *cond; enum path_flags flags; u_int8_t forwardcnt; char user[MAX_LOCALPART_SIZE]; @@ -765,8 +767,9 @@ struct mta_session { /* aliases.c */ int aliases_exist(struct smtpd *, char *); int aliases_get(struct smtpd *, struct aliaseslist *, char *); -int aliases_virtual_exist(struct smtpd *, struct path *); -int aliases_virtual_get(struct smtpd *, struct aliaseslist *, struct path *); +int aliases_vdomain_exists(struct smtpd *, struct map *, char *); +int aliases_virtual_exist(struct smtpd *, struct map *, struct path *); +int aliases_virtual_get(struct smtpd *, struct map *, struct aliaseslist *, struct path *); int alias_parse(struct alias *, char *); /* authenticate.c */ |