diff options
author | Gilles Chehade <gilles@cvs.openbsd.org> | 2010-04-27 09:49:24 +0000 |
---|---|---|
committer | Gilles Chehade <gilles@cvs.openbsd.org> | 2010-04-27 09:49:24 +0000 |
commit | c5e412cc3c0ed99c754af772a1680a199acf72ab (patch) | |
tree | 9caebb17c70842a04fd146808e1bee7589b8fceb | |
parent | 7e32eeaab109e135c198149e47b67e1d07f69691 (diff) |
initial work at fixing aliases support:
- kill struct alias, struct expandnode is used instead
- introduce map_parse_alias() and map_parse_virtual()
- aliases and virtual code no longer assume db(3) but use the map API which
lets them become backend agnostic AND value-checked. this actually makes
the code simpler by removing all values parsing from aliases.c
- rename K_SECRETS -> K_SECRET, K_ALIASES -> K_ALIAS for consistency the
enum has singular names.
- aliases, virtual and forward now work with an expandtree and deal with
multiple levels of resolving by merging expandtree's
more coming soon ;)
-rw-r--r-- | usr.sbin/smtpd/aliases.c | 316 | ||||
-rw-r--r-- | usr.sbin/smtpd/expand.c | 39 | ||||
-rw-r--r-- | usr.sbin/smtpd/forward.c | 12 | ||||
-rw-r--r-- | usr.sbin/smtpd/lka.c | 12 | ||||
-rw-r--r-- | usr.sbin/smtpd/makemap.c | 38 | ||||
-rw-r--r-- | usr.sbin/smtpd/map.c | 4 | ||||
-rw-r--r-- | usr.sbin/smtpd/map_parser.c | 102 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 58 |
8 files changed, 282 insertions, 299 deletions
diff --git a/usr.sbin/smtpd/aliases.c b/usr.sbin/smtpd/aliases.c index c0b2fcb0c31..4ee42e8a1f9 100644 --- a/usr.sbin/smtpd/aliases.c +++ b/usr.sbin/smtpd/aliases.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aliases.c,v 1.31 2009/11/09 23:54:08 gilles Exp $ */ +/* $OpenBSD: aliases.c,v 1.32 2010/04/27 09:49:23 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -35,275 +35,175 @@ #include "smtpd.h" int aliases_expand_include(struct expandtree *, char *); -int alias_is_filter(struct alias *, char *, size_t); -int alias_is_username(struct alias *, char *, size_t); -int alias_is_address(struct alias *, char *, size_t); -int alias_is_filename(struct alias *, char *, size_t); -int alias_is_include(struct alias *, char *, size_t); +int alias_is_filter(struct expandnode *, char *, size_t); +int alias_is_username(struct expandnode *, char *, size_t); +int alias_is_address(struct expandnode *, char *, size_t); +int alias_is_filename(struct expandnode *, char *, size_t); +int alias_is_include(struct expandnode *, char *, size_t); int aliases_exist(struct smtpd *env, objid_t mapid, char *username) { - char buf[MAXLOGNAME]; - int ret; - DBT key; - DBT val; - DB *aliasesdb; struct map *map; + struct map_alias *map_alias; + char buf[MAXLOGNAME]; map = map_find(env, mapid); if (map == NULL) return 0; - aliasesdb = dbopen(map->m_config, O_RDONLY, 0600, DB_HASH, NULL); - if (aliasesdb == NULL) { - log_warn("aliases_exist: dbopen: %s", map->m_config); - return 0; - } - lowercase(buf, username, sizeof(buf)); + map_alias = map_lookup(env, mapid, buf, K_ALIAS); + if (map_alias == NULL) + return 0; - key.data = buf; - key.size = strlen(key.data) + 1; + /* XXX - for now the map API always allocate */ + log_debug("aliases_exist: '%s' exists with %zd expansion nodes", + username, map_alias->nbnodes); - ret = aliasesdb->get(aliasesdb, &key, &val, 0); - if (ret == -1) - log_warn("aliases_exist"); - aliasesdb->close(aliasesdb); + expandtree_free_nodes(&map_alias->expandtree); + free(map_alias); - return (ret == 0); + return 1; } int aliases_get(struct smtpd *env, objid_t mapid, struct expandtree *expandtree, char *username) { - char buf[MAXLOGNAME]; - int ret; - DBT key; - DBT val; - DB *aliasesdb; - size_t nbaliases, nbsave; - struct alias alias; - struct alias *nextalias; struct map *map; - struct expand_node expnode; + struct map_alias *map_alias; + struct expandnode *expnode; + char buf[MAXLOGNAME]; + size_t nbaliases; map = map_find(env, mapid); if (map == NULL) return 0; - aliasesdb = dbopen(map->m_config, O_RDONLY, 0600, DB_HASH, NULL); - if (aliasesdb == NULL) { - log_warn("aliases_get: dbopen: %s", map->m_config); - return 0; - } - lowercase(buf, username, sizeof(buf)); - - key.data = buf; - key.size = strlen(key.data) + 1; - - if ((ret = aliasesdb->get(aliasesdb, &key, &val, 0)) != 0) { - if (ret == -1) - log_warn("aliases_get"); - aliasesdb->close(aliasesdb); - return 0; - } - - nbsave = nbaliases = val.size / sizeof(struct alias); - if (nbaliases == 0) { - aliasesdb->close(aliasesdb); + map_alias = map_lookup(env, mapid, buf, K_ALIAS); + if (map_alias == NULL) return 0; - } - nextalias = (struct alias *)val.data; - do { - alias = *nextalias; - ++nextalias; - if (alias.type == EXPAND_INCLUDE) { - aliases_expand_include(expandtree, alias.u.filename); - } + /* foreach node in map_alias expandtree, we merge */ + nbaliases = 0; + RB_FOREACH(expnode, expandtree, &map_alias->expandtree) { + if (expnode->type == EXPAND_INCLUDE) + nbaliases += aliases_expand_include(expandtree, expnode->u.filename); else { - bzero(&expnode, sizeof(struct expand_node)); - alias_to_expand_node(&expnode, &alias); - expandtree_increment_node(expandtree, &expnode); + expandtree_increment_node(expandtree, expnode); + nbaliases++; } - } while (--nbaliases); - aliasesdb->close(aliasesdb); - return nbsave; + } + + expandtree_free_nodes(&map_alias->expandtree); + free(map_alias); + + log_debug("aliases_get: returned %zd aliases", nbaliases); + return nbaliases; } int aliases_vdomain_exists(struct smtpd *env, objid_t mapid, char *hostname) { - int ret; - DBT key; - DBT val; - DB *vtable; struct map *map; - char strkey[MAX_LINE_SIZE]; + struct map_virtual *map_virtual; + char buf[MAXHOSTNAMELEN]; map = map_find(env, mapid); if (map == NULL) return 0; - vtable = dbopen(map->m_config, O_RDONLY, 0600, DB_HASH, NULL); - if (vtable == NULL) { - log_warn("aliases_vdomain_exists: dbopen: %s", map->m_config); + lowercase(buf, hostname, sizeof(buf)); + map_virtual = map_lookup(env, mapid, buf, K_VIRTUAL); + if (map_virtual == NULL) return 0; - } - if (! bsnprintf(strkey, sizeof(strkey), "%s", hostname)) { - vtable->close(vtable); - return 0; - } - lowercase(strkey, strkey, sizeof(strkey)); + /* XXX - for now the map API always allocate */ + log_debug("aliases_vdomain_exist: '%s' exists", hostname); + expandtree_free_nodes(&map_virtual->expandtree); + free(map_virtual); - 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); + return 1; } int aliases_virtual_exist(struct smtpd *env, objid_t mapid, struct path *path) { - int ret; - DBT key; - DBT val; - DB *aliasesdb; struct map *map; - char strkey[MAX_LINE_SIZE]; + struct map_virtual *map_virtual; + char buf[MAX_LINE_SIZE]; + char *pbuf = buf; map = map_find(env, mapid); 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: %s", map->m_config); + if (! bsnprintf(buf, sizeof(buf), "%s@%s", path->user, + path->domain)) return 0; - } + lowercase(buf, buf, sizeof(buf)); - if (! bsnprintf(strkey, sizeof(strkey), "%s@%s", path->user, - path->domain)) { - aliasesdb->close(aliasesdb); - return 0; + map_virtual = map_lookup(env, mapid, buf, K_VIRTUAL); + if (map_virtual == NULL) { + pbuf = strchr(buf, '@'); + map_virtual = map_lookup(env, mapid, pbuf, K_VIRTUAL); } + if (map_virtual == NULL) + return 0; - lowercase(strkey, strkey, sizeof(strkey)); - - key.data = strkey; - key.size = strlen(key.data) + 1; - - if ((ret = aliasesdb->get(aliasesdb, &key, &val, 0)) != 0) { - if (ret == -1) - log_warn("aliases_virtual_exist"); - - if (! bsnprintf(strkey, sizeof(strkey), "@%s", path->domain)) { - aliasesdb->close(aliasesdb); - return 0; - } - - lowercase(strkey, strkey, sizeof(strkey)); - - key.data = strkey; - key.size = strlen(key.data) + 1; - - ret = aliasesdb->get(aliasesdb, &key, &val, 0); - } - if (ret == -1) - log_warn("aliases_virtual_exist"); - aliasesdb->close(aliasesdb); + log_debug("aliases_virtual_exist: '%s' exists", pbuf); + expandtree_free_nodes(&map_virtual->expandtree); + free(map_virtual); - return (ret == 0); + return 1; } int aliases_virtual_get(struct smtpd *env, objid_t mapid, struct expandtree *expandtree, struct path *path) { - int ret; - DBT key; - DBT val; - DB *aliasesdb; - size_t nbaliases, nbsave; - struct alias alias; - struct alias *nextalias; struct map *map; - char strkey[MAX_LINE_SIZE]; - struct expand_node expnode; + struct map_virtual *map_virtual; + struct expandnode *expnode; + char buf[MAX_LINE_SIZE]; + char *pbuf = buf; + int nbaliases; map = map_find(env, mapid); 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: %s", map->m_config); + if (! bsnprintf(buf, sizeof(buf), "%s@%s", path->user, + path->domain)) return 0; - } + lowercase(buf, buf, sizeof(buf)); - if (! bsnprintf(strkey, sizeof(strkey), "%s@%s", path->user, - path->domain)) { - aliasesdb->close(aliasesdb); - return 0; + map_virtual = map_lookup(env, mapid, buf, K_VIRTUAL); + if (map_virtual == NULL) { + pbuf = strchr(buf, '@'); + map_virtual = map_lookup(env, mapid, pbuf, K_VIRTUAL); } + if (map_virtual == NULL) + return 0; - lowercase(strkey, strkey, sizeof(strkey)); - - key.data = strkey; - key.size = strlen(key.data) + 1; - - if ((ret = aliasesdb->get(aliasesdb, &key, &val, 0)) != 0) { - if (ret == -1) - log_warn("aliases_virtual_get"); - - if (! bsnprintf(strkey, sizeof(strkey), "@%s", path->domain)) { - aliasesdb->close(aliasesdb); - return 0; - } - - lowercase(strkey, strkey, sizeof(strkey)); - - key.data = strkey; - key.size = strlen(key.data) + 1; - - if ((ret = aliasesdb->get(aliasesdb, &key, &val, 0)) != 0) { - if (ret == -1) - log_warn("aliases_virtual_get"); - aliasesdb->close(aliasesdb); - return 0; + /* foreach node in map_virtual expandtree, we merge */ + nbaliases = 0; + RB_FOREACH(expnode, expandtree, &map_virtual->expandtree) { + if (expnode->type == EXPAND_INCLUDE) + nbaliases += aliases_expand_include(expandtree, expnode->u.filename); + else { + expandtree_increment_node(expandtree, expnode); + nbaliases++; } } - nbsave = nbaliases = val.size / sizeof(struct alias); - if (nbaliases == 0) { - aliasesdb->close(aliasesdb); - return 0; - } + expandtree_free_nodes(&map_virtual->expandtree); + free(map_virtual); + log_debug("aliases_virtual_get: '%s' resolved to %d nodes", pbuf, nbaliases); - nextalias = (struct alias *)val.data; - do { - alias = *nextalias; - ++nextalias; - if (alias.type == EXPAND_INCLUDE) { - aliases_expand_include(expandtree, alias.u.filename); - } - else { - bzero(&expnode, sizeof(struct expand_node)); - alias_to_expand_node(&expnode, &alias); - expandtree_increment_node(expandtree, &expnode); - } - } while (--nbaliases); - aliasesdb->close(aliasesdb); - return nbsave; + return nbaliases; } int @@ -314,8 +214,7 @@ aliases_expand_include(struct expandtree *expandtree, char *filename) size_t len; size_t lineno = 0; char delim[] = { '\\', '#' }; - struct alias alias; - struct expand_node expnode; + struct expandnode expnode; fp = fopen(filename, "r"); if (fp == NULL) { @@ -328,18 +227,16 @@ aliases_expand_include(struct expandtree *expandtree, char *filename) free(line); continue; } - if (! alias_parse(&alias, line)) { + + bzero(&expnode, sizeof(struct expandnode)); + if (! alias_parse(&expnode, line)) { log_warnx("could not parse include entry \"%s\".", line); } - if (alias.type == EXPAND_INCLUDE) { + if (expnode.type == EXPAND_INCLUDE) log_warnx("nested inclusion is not supported."); - } - else { - bzero(&expnode, sizeof(struct expand_node)); - alias_to_expand_node(&expnode, &alias); + else expandtree_increment_node(expandtree, &expnode); - } free(line); } @@ -349,10 +246,10 @@ aliases_expand_include(struct expandtree *expandtree, char *filename) } int -alias_parse(struct alias *alias, char *line) +alias_parse(struct expandnode *alias, char *line) { size_t i; - int (*f[])(struct alias *, char *, size_t) = { + int (*f[])(struct expandnode *, char *, size_t) = { alias_is_include, alias_is_filter, alias_is_filename, @@ -370,7 +267,7 @@ alias_parse(struct alias *alias, char *line) } for (i = 0; i < sizeof(f) / sizeof(void *); ++i) { - bzero(alias, sizeof(struct alias)); + bzero(alias, sizeof(struct expandnode)); if (f[i](alias, line, strlen(line))) break; } @@ -382,7 +279,7 @@ alias_parse(struct alias *alias, char *line) int -alias_is_filter(struct alias *alias, char *line, size_t len) +alias_is_filter(struct expandnode *alias, char *line, size_t len) { if (strncmp(line, "\"|", 2) == 0 && line[len - 1] == '"') { @@ -396,7 +293,7 @@ alias_is_filter(struct alias *alias, char *line, size_t len) } int -alias_is_username(struct alias *alias, char *line, size_t len) +alias_is_username(struct expandnode *alias, char *line, size_t len) { if (strlcpy(alias->u.username, line, sizeof(alias->u.username)) >= sizeof(alias->u.username)) @@ -414,7 +311,7 @@ alias_is_username(struct alias *alias, char *line, size_t len) } int -alias_is_address(struct alias *alias, char *line, size_t len) +alias_is_address(struct expandnode *alias, char *line, size_t len) { char *domain; @@ -455,7 +352,7 @@ alias_is_address(struct alias *alias, char *line, size_t len) } int -alias_is_filename(struct alias *alias, char *line, size_t len) +alias_is_filename(struct expandnode *alias, char *line, size_t len) { if (*line != '/') return 0; @@ -468,7 +365,7 @@ alias_is_filename(struct alias *alias, char *line, size_t len) } int -alias_is_include(struct alias *alias, char *line, size_t len) +alias_is_include(struct expandnode *alias, char *line, size_t len) { if (strncasecmp(":include:", line, 9) != 0) return 0; @@ -479,10 +376,3 @@ alias_is_include(struct alias *alias, char *line, size_t len) alias->type = EXPAND_INCLUDE; return 1; } - -void -alias_to_expand_node(struct expand_node *expnode, struct alias *alias) -{ - expnode->type = alias->type; - expnode->u = alias->u; -} diff --git a/usr.sbin/smtpd/expand.c b/usr.sbin/smtpd/expand.c index 5786937018c..b3fbcdf54dd 100644 --- a/usr.sbin/smtpd/expand.c +++ b/usr.sbin/smtpd/expand.c @@ -1,4 +1,4 @@ -/* $OpenBSD: expand.c,v 1.3 2009/11/09 23:49:34 gilles Exp $ */ +/* $OpenBSD: expand.c,v 1.4 2010/04/27 09:49:23 gilles Exp $ */ /* * Copyright (c) 2009 Gilles Chehade <gilles@openbsd.org> @@ -33,23 +33,23 @@ #include "smtpd.h" -struct expand_node * -expandtree_lookup(struct expandtree *expandtree, struct expand_node *node) +struct expandnode * +expandtree_lookup(struct expandtree *expandtree, struct expandnode *node) { - struct expand_node key; + struct expandnode key; key = *node; return RB_FIND(expandtree, expandtree, &key); } void -expandtree_increment_node(struct expandtree *expandtree, struct expand_node *node) +expandtree_increment_node(struct expandtree *expandtree, struct expandnode *node) { - struct expand_node *p; + struct expandnode *p; p = expandtree_lookup(expandtree, node); if (p == NULL) { - p = calloc(1, sizeof(struct expand_node)); + p = calloc(1, sizeof(struct expandnode)); if (p == NULL) fatal("calloc"); *p = *node; @@ -60,9 +60,9 @@ expandtree_increment_node(struct expandtree *expandtree, struct expand_node *nod } void -expandtree_decrement_node(struct expandtree *expandtree, struct expand_node *node) +expandtree_decrement_node(struct expandtree *expandtree, struct expandnode *node) { - struct expand_node *p; + struct expandnode *p; p = expandtree_lookup(expandtree, node); if (p == NULL) @@ -72,9 +72,9 @@ expandtree_decrement_node(struct expandtree *expandtree, struct expand_node *nod } void -expandtree_remove_node(struct expandtree *expandtree, struct expand_node *node) +expandtree_remove_node(struct expandtree *expandtree, struct expandnode *node) { - struct expand_node *p; + struct expandnode *p; p = expandtree_lookup(expandtree, node); if (p == NULL) @@ -83,8 +83,21 @@ expandtree_remove_node(struct expandtree *expandtree, struct expand_node *node) RB_REMOVE(expandtree, expandtree, p); } +void +expandtree_free_nodes(struct expandtree *expandtree) +{ + struct expandnode *p; + struct expandnode *nxt; + + for (p = RB_MIN(expandtree, expandtree); p != NULL; p = nxt) { + nxt = RB_NEXT(expandtree, expandtree, p); + RB_REMOVE(expandtree, expandtree, p); + free(p); + } +} + int -expand_cmp(struct expand_node *e1, struct expand_node *e2) +expand_cmp(struct expandnode *e1, struct expandnode *e2) { if (e1->type < e2->type) return -1; @@ -95,4 +108,4 @@ expand_cmp(struct expand_node *e1, struct expand_node *e2) return memcmp(&e1->u, &e2->u, sizeof(e1->u)); } -RB_GENERATE(expandtree, expand_node, entry, expand_cmp); +RB_GENERATE(expandtree, expandnode, entry, expand_cmp); diff --git a/usr.sbin/smtpd/forward.c b/usr.sbin/smtpd/forward.c index f94a6921340..cc34ab08f14 100644 --- a/usr.sbin/smtpd/forward.c +++ b/usr.sbin/smtpd/forward.c @@ -1,4 +1,4 @@ -/* $OpenBSD: forward.c,v 1.20 2009/11/09 23:54:08 gilles Exp $ */ +/* $OpenBSD: forward.c,v 1.21 2010/04/27 09:49:23 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -38,12 +38,11 @@ int forwards_get(int fd, struct expandtree *expandtree) { FILE *fp; - struct alias alias; char *buf, *lbuf, *p, *cp; size_t len; size_t nbaliases = 0; int quoted; - struct expand_node expnode; + struct expandnode expnode; fp = fdopen(fd, "r"); if (fp == NULL) @@ -84,19 +83,18 @@ forwards_get(int fd, struct expandtree *expandtree) buf = cp; cp = p; - if (! alias_parse(&alias, buf)) { + bzero(&expnode, sizeof (struct expandnode)); + if (! alias_parse(&expnode, buf)) { log_debug("bad entry in ~/.forward"); continue; } - if (alias.type == EXPAND_INCLUDE) { + if (expnode.type == EXPAND_INCLUDE) { log_debug( "includes are forbidden in ~/.forward"); continue; } - bzero(&expnode, sizeof(struct expand_node)); - alias_to_expand_node(&expnode, &alias); expandtree_increment_node(expandtree, &expnode); nbaliases++; } while (*cp != '\0'); diff --git a/usr.sbin/smtpd/lka.c b/usr.sbin/smtpd/lka.c index 0dfdbe2990d..a17af939a2e 100644 --- a/usr.sbin/smtpd/lka.c +++ b/usr.sbin/smtpd/lka.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lka.c,v 1.106 2010/04/21 21:47:38 gilles Exp $ */ +/* $OpenBSD: lka.c,v 1.107 2010/04/27 09:49:23 gilles Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -48,7 +48,7 @@ void lka_setup_events(struct smtpd *); void lka_disable_events(struct smtpd *); void lka_expand_pickup(struct smtpd *, struct lkasession *); int lka_expand_resume(struct smtpd *, struct lkasession *); -int lka_resolve_node(struct smtpd *, char *tag, struct path *, struct expand_node *); +int lka_resolve_node(struct smtpd *, char *tag, struct path *, struct expandnode *); int lka_verify_mail(struct smtpd *, struct path *); struct rule *ruleset_match(struct smtpd *, char *, struct path *, struct sockaddr_storage *); int lka_resolve_path(struct smtpd *, struct lkasession *, struct path *); @@ -133,7 +133,7 @@ lka_imsg(struct smtpd *env, struct imsgev *iev, struct imsg *imsg) map = map_findbyname(env, "secrets"); if (map == NULL) fatalx("lka: secrets map not found"); - map_secret = map_lookup(env, map->m_id, secret->host, K_SECRETS); + map_secret = map_lookup(env, map->m_id, secret->host, K_SECRET); log_debug("lka: %s secret lookup (%d)", secret->host, map_secret != NULL); secret->secret[0] = '\0'; @@ -494,7 +494,7 @@ lka_expand(char *buf, size_t len, struct path *path) } int -lka_resolve_node(struct smtpd *env, char *tag, struct path *path, struct expand_node *expnode) +lka_resolve_node(struct smtpd *env, char *tag, struct path *path, struct expandnode *expnode) { struct path psave = *path; @@ -600,7 +600,7 @@ int lka_expand_resume(struct smtpd *env, struct lkasession *lkasession) { u_int8_t done = 1; - struct expand_node *expnode = NULL; + struct expandnode *expnode = NULL; struct path *lkasessionpath = NULL; struct path path, *pathp = NULL; @@ -777,7 +777,7 @@ lkasession_cmp(struct lkasession *s1, struct lkasession *s2) void lka_clear_expandtree(struct expandtree *expandtree) { - struct expand_node *expnode; + struct expandnode *expnode; while ((expnode = RB_ROOT(expandtree)) != NULL) { expandtree_remove_node(expandtree, expnode); diff --git a/usr.sbin/smtpd/makemap.c b/usr.sbin/smtpd/makemap.c index e3217833a4a..18677dc06cd 100644 --- a/usr.sbin/smtpd/makemap.c +++ b/usr.sbin/smtpd/makemap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: makemap.c,v 1.25 2010/04/21 21:40:56 gilles Exp $ */ +/* $OpenBSD: makemap.c,v 1.26 2010/04/27 09:49:23 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -239,11 +239,8 @@ parse_mapentry(char *line, size_t len, size_t lineno) { DBT key; DBT val; - DBT domkey; - DBT domval; char *keyp; char *valp; - char *domp; keyp = line; while (isspace((int)*keyp)) @@ -283,21 +280,6 @@ parse_mapentry(char *line, size_t len, size_t lineno) return 0; } - /* add key for domain */ - if ((domp = strrchr(key.data, '@')) != NULL) { - domkey.data = domp + 1; - domkey.size = strlen(domkey.data) + 1; - - domval.data = "<empty>"; - domval.size = strlen(domval.data) + 1; - - if (db->put(db, &domkey, &domval, 0) == -1) { - warn("dbput"); - return 0; - } - } - - dbputs++; free(val.data); @@ -358,13 +340,18 @@ make_plain(DBT *val, char *text) int make_aliases(DBT *val, char *text) { - struct alias a; + struct expandnode expnode; char *subrcpt; char *endp; + char *origtext; val->data = NULL; val->size = 0; + origtext = strdup(text); + if (origtext == NULL) + fatal("strdup"); + while ((subrcpt = strsep(&text, ",")) != NULL) { /* subrcpt: strip initial whitespace. */ while (isspace((int)*subrcpt)) @@ -377,16 +364,13 @@ make_aliases(DBT *val, char *text) while (subrcpt < endp && isspace((int)*endp)) *endp-- = '\0'; - if (! alias_parse(&a, subrcpt)) + bzero(&expnode, sizeof(struct expandnode)); + if (! alias_parse(&expnode, subrcpt)) goto error; - - val->data = realloc(val->data, val->size + sizeof(a)); - if (val->data == NULL) - err(1, "get_targets: realloc"); - memcpy((u_int8_t *)val->data + val->size, &a, sizeof(a)); - val->size += sizeof(a); } + val->data = origtext; + val->size = strlen(origtext) + 1; return (val->size); error: diff --git a/usr.sbin/smtpd/map.c b/usr.sbin/smtpd/map.c index 1586a0c1062..4dc3dfff778 100644 --- a/usr.sbin/smtpd/map.c +++ b/usr.sbin/smtpd/map.c @@ -1,4 +1,4 @@ -/* $OpenBSD: map.c,v 1.15 2010/04/21 21:47:38 gilles Exp $ */ +/* $OpenBSD: map.c,v 1.16 2010/04/27 09:49:23 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -90,7 +90,7 @@ map_lookup(struct smtpd *env, objid_t mapid, char *key, enum map_kind kind) goto end; if (parser->extract != NULL) { - ret = parser->extract(result, len); + ret = parser->extract(key, result, len); free(result); } diff --git a/usr.sbin/smtpd/map_parser.c b/usr.sbin/smtpd/map_parser.c index ca999a0a124..6ad702b6d0e 100644 --- a/usr.sbin/smtpd/map_parser.c +++ b/usr.sbin/smtpd/map_parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: map_parser.c,v 1.2 2010/04/21 21:47:38 gilles Exp $ */ +/* $OpenBSD: map_parser.c,v 1.3 2010/04/27 09:49:23 gilles Exp $ */ /* * Copyright (c) 2010 Gilles Chehade <gilles@openbsd.org> @@ -36,13 +36,15 @@ struct map_parser *map_parser_lookup(enum map_kind); -void *map_parse_secret(char *, size_t); +void *map_parse_secret(char *, char *, size_t); +void *map_parse_alias(char *, char *, size_t); +void *map_parse_virtual(char *, char *, size_t); struct map_parser map_parsers[] = { - { K_NONE, NULL }, - { K_ALIASES, NULL }, - { K_VIRTUAL, NULL }, - { K_SECRETS, map_parse_secret } + { K_NONE, NULL }, + { K_ALIAS, map_parse_alias }, + { K_VIRTUAL, map_parse_virtual }, + { K_SECRET, map_parse_secret } }; struct map_parser * @@ -61,7 +63,7 @@ map_parser_lookup(enum map_kind kind) } void * -map_parse_secret(char *line, size_t len) +map_parse_secret(char *key, char *line, size_t len) { struct map_secret *map_secret = NULL; char *p; @@ -102,3 +104,89 @@ err: free(map_secret); return NULL; } + +void * +map_parse_alias(char *key, char *line, size_t len) +{ + char *subrcpt; + char *endp; + struct map_alias *map_alias = NULL; + struct expandnode expnode; + + map_alias = calloc(1, sizeof(struct map_alias)); + if (map_alias == NULL) + fatalx("calloc"); + + while ((subrcpt = strsep(&line, ",")) != NULL) { + /* subrcpt: strip initial whitespace. */ + while (isspace((int)*subrcpt)) + ++subrcpt; + if (*subrcpt == '\0') + goto error; + + /* subrcpt: strip trailing whitespace. */ + endp = subrcpt + strlen(subrcpt) - 1; + while (subrcpt < endp && isspace((int)*endp)) + *endp-- = '\0'; + + bzero(&expnode, sizeof (struct expandnode)); + if (! alias_parse(&expnode, subrcpt)) + goto error; + + expandtree_increment_node(&map_alias->expandtree, &expnode); + map_alias->nbnodes++; + } + + return map_alias; + +error: + /* free elements in map_alias->expandtree */ + expandtree_free_nodes(&map_alias->expandtree); + free(map_alias); + return NULL; +} + +void * +map_parse_virtual(char *key, char *line, size_t len) +{ + char *subrcpt; + char *endp; + struct map_virtual *map_virtual = NULL; + struct expandnode expnode; + + map_virtual = calloc(1, sizeof(struct map_virtual)); + if (map_virtual == NULL) + fatalx("calloc"); + + /* domain key, discard value */ + if (strchr(key, '@') == NULL) + return map_virtual; + + while ((subrcpt = strsep(&line, ",")) != NULL) { + /* subrcpt: strip initial whitespace. */ + while (isspace((int)*subrcpt)) + ++subrcpt; + if (*subrcpt == '\0') + goto error; + + /* subrcpt: strip trailing whitespace. */ + endp = subrcpt + strlen(subrcpt) - 1; + while (subrcpt < endp && isspace((int)*endp)) + *endp-- = '\0'; + + bzero(&expnode, sizeof (struct expandnode)); + if (! alias_parse(&expnode, subrcpt)) + goto error; + + expandtree_increment_node(&map_virtual->expandtree, &expnode); + map_virtual->nbnodes++; + } + + return map_virtual; + +error: + /* free elements in map_virtual->expandtree */ + expandtree_free_nodes(&map_virtual->expandtree); + free(map_virtual); + return NULL; +} diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h index 3bced957a50..2be94da3244 100644 --- a/usr.sbin/smtpd/smtpd.h +++ b/usr.sbin/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.180 2010/04/22 12:56:33 jacekm Exp $ */ +/* $OpenBSD: smtpd.h,v 1.181 2010/04/27 09:49:23 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -251,9 +251,9 @@ enum map_src { enum map_kind { K_NONE, - K_ALIASES, + K_ALIAS, K_VIRTUAL, - K_SECRETS + K_SECRET }; enum mapel_type { @@ -295,12 +295,7 @@ struct map_backend { struct map_parser { enum map_kind kind; - void *(*extract)(char *, size_t); -}; - -struct map_secret { - char username[MAX_LINE_SIZE]; - char password[MAX_LINE_SIZE]; + void *(*extract)(char *, char *, size_t); }; enum cond_type { @@ -409,18 +404,15 @@ enum expand_flags { F_EXPAND_DONE }; -struct expand_node { - RB_ENTRY(expand_node) entry; +struct expandnode { + RB_ENTRY(expandnode) entry; size_t refcnt; enum expand_flags flags; enum expand_type type; union path_data u; }; -struct alias { - enum expand_type type; - union path_data u; -}; +RB_HEAD(expandtree, expandnode); enum message_type { T_MDA_MESSAGE = 0x1, @@ -787,7 +779,7 @@ struct lkasession { struct path path; struct deliverylist deliverylist; - RB_HEAD(expandtree, expand_node) expandtree; + struct expandtree expandtree; u_int8_t iterations; u_int32_t pending; @@ -840,6 +832,24 @@ struct mta_session { }; +/* maps return structures */ +struct map_secret { + char username[MAX_LINE_SIZE]; + char password[MAX_LINE_SIZE]; +}; + +struct map_alias { + size_t nbnodes; + struct expandtree expandtree; +}; + +struct map_virtual { + size_t nbnodes; + struct expandtree expandtree; +}; + + + extern void (*imsg_callback)(struct smtpd *, struct imsgev *, struct imsg *); /* aliases.c */ @@ -848,8 +858,7 @@ int aliases_get(struct smtpd *, objid_t, struct expandtree *, char *); int aliases_vdomain_exists(struct smtpd *, objid_t, char *); int aliases_virtual_exist(struct smtpd *, objid_t, struct path *); int aliases_virtual_get(struct smtpd *, objid_t, struct expandtree *, struct path *); -int alias_parse(struct alias *, char *); -void alias_to_expand_node(struct expand_node *, struct alias *); +int alias_parse(struct expandnode *, char *); /* authenticate.c */ int authenticate_user(char *, char *); @@ -882,12 +891,13 @@ void dns_query_ptr(struct smtpd *, struct sockaddr_storage *, void dns_async(struct smtpd *, struct imsgev *, int, struct dns *); /* expand.c */ -int expand_cmp(struct expand_node *, struct expand_node *); -void expandtree_increment_node(struct expandtree *, struct expand_node *); -void expandtree_decrement_node(struct expandtree *, struct expand_node *); -void expandtree_remove_node(struct expandtree *, struct expand_node *); -struct expand_node *expandtree_lookup(struct expandtree *, struct expand_node *); -RB_PROTOTYPE(expandtree, expand_node, nodes, expand_cmp); +int expand_cmp(struct expandnode *, struct expandnode *); +void expandtree_increment_node(struct expandtree *, struct expandnode *); +void expandtree_decrement_node(struct expandtree *, struct expandnode *); +void expandtree_remove_node(struct expandtree *, struct expandnode *); +struct expandnode *expandtree_lookup(struct expandtree *, struct expandnode *); +void expandtree_free_nodes(struct expandtree *); +RB_PROTOTYPE(expandtree, expandnode, nodes, expand_cmp); /* forward.c */ int forwards_get(int, struct expandtree *); |