summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/smtpd/aliases.c51
-rw-r--r--usr.sbin/smtpd/lka.c57
-rw-r--r--usr.sbin/smtpd/makemap.816
-rw-r--r--usr.sbin/smtpd/parse.y24
-rw-r--r--usr.sbin/smtpd/ruleset.c15
-rw-r--r--usr.sbin/smtpd/smtpd.h11
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 */