summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/smtpd/lka.c26
-rw-r--r--usr.sbin/smtpd/parse.y92
-rw-r--r--usr.sbin/smtpd/ruleset.c12
-rw-r--r--usr.sbin/smtpd/smtp_session.c3
-rw-r--r--usr.sbin/smtpd/smtpd.h7
5 files changed, 99 insertions, 41 deletions
diff --git a/usr.sbin/smtpd/lka.c b/usr.sbin/smtpd/lka.c
index edbcb5869c2..4f77df73dd0 100644
--- a/usr.sbin/smtpd/lka.c
+++ b/usr.sbin/smtpd/lka.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lka.c,v 1.70 2009/10/18 21:45:47 gilles Exp $ */
+/* $OpenBSD: lka.c,v 1.71 2009/10/19 20:48:13 gilles Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -57,19 +57,19 @@ int lka_forward_file(struct passwd *);
size_t lka_expand(char *, size_t, struct path *);
int aliases_exist(struct smtpd *, char *);
int aliases_get(struct smtpd *, struct aliaseslist *, char *);
-int lka_resolve_alias(struct smtpd *, struct path *, struct alias *);
+int lka_resolve_alias(struct smtpd *, char *tag, 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 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 *);
-void lka_rcpt_action(struct smtpd *, struct path *);
+void lka_rcpt_action(struct smtpd *, char *, struct path *);
void lka_clear_aliaseslist(struct aliaseslist *);
int lka_encode_credentials(char *, size_t, char *);
struct lkasession *lka_session_init(struct smtpd *, struct submit_status *);
void lka_request_forwardfile(struct smtpd *, struct lkasession *, char *);
-struct rule *ruleset_match(struct smtpd *, struct path *, struct sockaddr_storage *);
+struct rule *ruleset_match(struct smtpd *, char *, struct path *, struct sockaddr_storage *);
void queue_submit_envelope(struct smtpd *, struct message *);
void queue_commit_envelopes(struct smtpd *, struct message*);
@@ -255,7 +255,7 @@ lka_dispatch_parent(int sig, short event, void *p)
alias_parse(&alias, fwreq->pw_name);
/* then resolve alias and get back to expanding the aliases list */
- lka_resolve_alias(env, &lkasession->message.recipient, &alias);
+ lka_resolve_alias(env, lkasession->message.tag, &lkasession->message.recipient, &alias);
lka_expand_rcpt(env, &lkasession->aliaseslist, lkasession);
break;
}
@@ -330,7 +330,7 @@ lka_dispatch_mfa(int sig, short event, void *p)
ss->code = 530;
- r = ruleset_match(env, &ss->u.path, &ss->ss);
+ r = ruleset_match(env, ss->msg.tag, &ss->u.path, &ss->ss);
if (r != NULL) {
ss->code = 250;
ss->u.path.rule = *r;
@@ -833,7 +833,7 @@ lka_expand(char *buf, size_t len, struct path *path)
}
int
-lka_resolve_alias(struct smtpd *env, struct path *path, struct alias *alias)
+lka_resolve_alias(struct smtpd *env, char *tag, struct path *path, struct alias *alias)
{
bzero(path, sizeof(struct path));
@@ -854,7 +854,7 @@ lka_resolve_alias(struct smtpd *env, struct path *path, struct alias *alias)
return 0;
}
log_debug("RESOLVED TO %s@%s", path->user, path->domain);
- lka_rcpt_action(env, path);
+ lka_rcpt_action(env, tag, path);
break;
case ALIAS_FILENAME:
@@ -876,7 +876,7 @@ lka_resolve_alias(struct smtpd *env, struct path *path, struct alias *alias)
log_debug("ADDRESS: %s@%s", alias->u.path.user, alias->u.path.domain);
*path = alias->u.path;
- lka_rcpt_action(env, path);
+ lka_rcpt_action(env, tag, path);
break;
case ALIAS_INCLUDE:
fatalx("lka_resolve_alias: unexpected type");
@@ -929,7 +929,7 @@ lka_expand_rcpt(struct smtpd *env, struct aliaseslist *aliases, struct lkasessio
message = lkasession->message;
while ((alias = TAILQ_FIRST(&lkasession->aliaseslist)) != NULL) {
- lka_resolve_alias(env, &message.recipient, alias);
+ lka_resolve_alias(env, message.tag, &message.recipient, alias);
queue_submit_envelope(env, &message);
TAILQ_REMOVE(&lkasession->aliaseslist, alias, entry);
@@ -959,7 +959,7 @@ lka_expand_rcpt_iteration(struct smtpd *env, struct aliaseslist *aliases, struct
}
if (alias->type == ALIAS_ADDRESS) {
- lka_rcpt_action(env, &alias->u.path);
+ lka_rcpt_action(env, lkasession->message.tag, &alias->u.path);
if (aliases_virtual_get(env, alias->u.path.cond->c_match, aliases, &alias->u.path)) {
rmalias = alias;
done = 0;
@@ -1041,7 +1041,7 @@ lka_resolve_path(struct smtpd *env, struct path *path){
}
void
-lka_rcpt_action(struct smtpd *env, struct path *path)
+lka_rcpt_action(struct smtpd *env, char *tag, struct path *path)
{
struct rule *r;
@@ -1049,7 +1049,7 @@ lka_rcpt_action(struct smtpd *env, struct path *path)
(void)strlcpy(path->domain, env->sc_hostname,
sizeof (path->domain));
- r = ruleset_match(env, path, NULL);
+ r = ruleset_match(env, tag, path, NULL);
if (r == NULL) {
path->rule.r_action = A_RELAY;
return;
diff --git a/usr.sbin/smtpd/parse.y b/usr.sbin/smtpd/parse.y
index f92e7178e73..182ff251089 100644
--- a/usr.sbin/smtpd/parse.y
+++ b/usr.sbin/smtpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.41 2009/10/19 20:00:46 gilles Exp $ */
+/* $OpenBSD: parse.y,v 1.42 2009/10/19 20:48:13 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -92,12 +92,12 @@ struct mapel_list *contents = NULL;
struct listener *host_v4(const char *, in_port_t);
struct listener *host_v6(const char *, in_port_t);
-int host_dns(const char *, const char *, struct listenerlist *,
- int, in_port_t, u_int8_t);
-int host(const char *, const char *, struct listenerlist *,
- int, in_port_t, u_int8_t);
-int interface(const char *, const char *, struct listenerlist *,
- int, in_port_t, u_int8_t);
+int host_dns(const char *, const char *, const char *,
+ struct listenerlist *, int, in_port_t, u_int8_t);
+int host(const char *, const char *, const char *,
+ struct listenerlist *, int, in_port_t, u_int8_t);
+int interface(const char *, const char *, const char *,
+ struct listenerlist *, int, in_port_t, u_int8_t);
void set_localaddrs(void);
typedef struct {
@@ -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 VIRTUAL USER
+%token ARROW ENABLE AUTH TLS LOCAL VIRTUAL USER TAG
%token <v.string> STRING
%token <v.number> NUMBER
%type <v.map> map
@@ -127,7 +127,7 @@ typedef struct {
%type <v.cond> condition
%type <v.tv> interval
%type <v.object> mapref
-%type <v.string> certname user
+%type <v.string> certname user tag on
%%
@@ -232,15 +232,29 @@ auth : ENABLE AUTH { $$ = 1; }
| /* empty */ { $$ = 0; }
;
+tag : TAG STRING {
+ if (strlen($2) >= MAX_TAG_SIZE) {
+ yyerror("tag name too long");
+ free($2);
+ YYERROR;
+ }
+
+ $$ = $2;
+ }
+ | /* empty */ { $$ = NULL; }
+ ;
+
main : QUEUE INTERVAL interval {
conf->sc_qintval = $3;
}
- | LISTEN ON STRING port ssl certname auth {
+ | LISTEN ON STRING port ssl certname auth tag {
char *cert;
+ char *tag;
u_int8_t flags;
if ($5 == F_SSL) {
yyerror("syntax error");
+ free($8);
free($6);
free($3);
YYERROR;
@@ -248,6 +262,7 @@ main : QUEUE INTERVAL interval {
if ($5 == 0 && ($6 != NULL || $7)) {
yyerror("error: must specify tls or smtps");
+ free($8);
free($6);
free($3);
YYERROR;
@@ -268,21 +283,28 @@ main : QUEUE INTERVAL interval {
if ($5 && ssl_load_certfile(conf, cert, F_SCERT) < 0) {
yyerror("cannot load certificate: %s", cert);
+ free($8);
free($6);
free($3);
YYERROR;
}
- if (! interface($3, cert, conf->sc_listeners,
+ tag = $3;
+ if ($8 != NULL)
+ tag = $8;
+
+ if (! interface($3, tag, cert, conf->sc_listeners,
MAX_LISTEN, $4, flags)) {
- if (host($3, cert, conf->sc_listeners,
+ if (host($3, tag, cert, conf->sc_listeners,
MAX_LISTEN, $4, flags) <= 0) {
yyerror("invalid virtual ip or interface: %s", $3);
+ free($8);
free($6);
free($3);
YYERROR;
}
}
+ free($8);
free($6);
free($3);
}
@@ -885,17 +907,33 @@ from : FROM mapref {
}
;
-rule : decision from {
+on : ON STRING {
+ if (strlen($2) >= MAX_TAG_SIZE) {
+ yyerror("interface, address or tag name too long");
+ free($2);
+ YYERROR;
+ }
+
+ $$ = $2;
+ }
+ | /* empty */ { $$ = NULL; }
+
+rule : decision on from {
struct rule *r;
if ((r = calloc(1, sizeof(*r))) == NULL)
fatal("out of memory");
rule = r;
- rule->r_sources = map_find(conf, $2);
+ rule->r_sources = map_find(conf, $3);
+
+ if ($2)
+ (void)strlcpy(rule->r_tag, $2, sizeof(rule->r_tag));
+ free($2);
+
TAILQ_INIT(&rule->r_conditions);
TAILQ_INIT(&rule->r_options);
- } FOR conditions action {
+ } FOR conditions action tag {
TAILQ_INSERT_TAIL(conf->sc_rules, rule, r_entry);
}
;
@@ -966,6 +1004,7 @@ lookup(char *s)
{ "smtps", SMTPS },
{ "source", SOURCE },
{ "ssl", SSL },
+ { "tag", TAG },
{ "tls", TLS },
{ "to", TO },
{ "type", TYPE },
@@ -1531,8 +1570,8 @@ host_v6(const char *s, in_port_t port)
}
int
-host_dns(const char *s, const char *cert, struct listenerlist *al, int max, in_port_t port,
- u_int8_t flags)
+host_dns(const char *s, const char *tag, const char *cert,
+ struct listenerlist *al, int max, in_port_t port, u_int8_t flags)
{
struct addrinfo hints, *res0, *res;
int error, cnt = 0;
@@ -1566,6 +1605,8 @@ host_dns(const char *s, const char *cert, struct listenerlist *al, int max, in_p
h->ssl_cert_name[0] = '\0';
if (cert != NULL)
(void)strlcpy(h->ssl_cert_name, cert, sizeof(h->ssl_cert_name));
+ if (tag != NULL)
+ (void)strlcpy(h->tag, tag, sizeof(h->tag));
if (res->ai_family == AF_INET) {
sain = (struct sockaddr_in *)&h->ss;
@@ -1593,8 +1634,8 @@ host_dns(const char *s, const char *cert, struct listenerlist *al, int max, in_p
}
int
-host(const char *s, const char *cert, struct listenerlist *al, int max, in_port_t port,
- u_int8_t flags)
+host(const char *s, const char *tag, const char *cert, struct listenerlist *al,
+ int max, in_port_t port, u_int8_t flags)
{
struct listener *h;
@@ -1611,18 +1652,19 @@ host(const char *s, const char *cert, struct listenerlist *al, int max, in_port_
h->ssl_cert_name[0] = '\0';
if (cert != NULL)
(void)strlcpy(h->ssl_cert_name, cert, sizeof(h->ssl_cert_name));
-
+ if (tag != NULL)
+ (void)strlcpy(h->tag, tag, sizeof(h->tag));
TAILQ_INSERT_HEAD(al, h, entry);
return (1);
}
- return (host_dns(s, cert, al, max, port, flags));
+ return (host_dns(s, tag, cert, al, max, port, flags));
}
int
-interface(const char *s, const char *cert, struct listenerlist *al, int max, in_port_t port,
- u_int8_t flags)
+interface(const char *s, const char *tag, const char *cert,
+ struct listenerlist *al, int max, in_port_t port, u_int8_t flags)
{
struct ifaddrs *ifap, *p;
struct sockaddr_in *sain;
@@ -1653,6 +1695,10 @@ interface(const char *s, const char *cert, struct listenerlist *al, int max, in_
h->ssl_cert_name[0] = '\0';
if (cert != NULL)
(void)strlcpy(h->ssl_cert_name, cert, sizeof(h->ssl_cert_name));
+ if (tag != NULL)
+ (void)strlcpy(h->tag, tag, sizeof(h->tag));
+ if (tag != NULL)
+ (void)strlcpy(h->tag, tag, sizeof(h->tag));
ret = 1;
TAILQ_INSERT_HEAD(al, h, entry);
diff --git a/usr.sbin/smtpd/ruleset.c b/usr.sbin/smtpd/ruleset.c
index 9162de7a7fc..2974c28161f 100644
--- a/usr.sbin/smtpd/ruleset.c
+++ b/usr.sbin/smtpd/ruleset.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ruleset.c,v 1.4 2009/10/12 18:14:51 gilles Exp $ */
+/* $OpenBSD: ruleset.c,v 1.5 2009/10/19 20:48:13 gilles Exp $ */
/*
* Copyright (c) 2009 Gilles Chehade <gilles@openbsd.org>
@@ -35,21 +35,27 @@
#include "smtpd.h"
-struct rule *ruleset_match(struct smtpd *, struct path *, struct sockaddr_storage *);
+struct rule *ruleset_match(struct smtpd *, char *tag, struct path *, struct sockaddr_storage *);
int ruleset_check_source(struct map *, struct sockaddr_storage *);
int ruleset_match_mask(struct sockaddr_storage *, struct netaddr *);
struct rule *
-ruleset_match(struct smtpd *env, struct path *path, struct sockaddr_storage *ss)
+ruleset_match(struct smtpd *env, char *tag, struct path *path, struct sockaddr_storage *ss)
{
struct rule *r;
struct cond *cond;
struct map *map;
struct mapel *me;
+ if (tag)
+ log_debug("tag: %s", tag);
+
TAILQ_FOREACH(r, env->sc_rules, r_entry) {
+ if (r->r_tag[0] != '\0' && strcmp(r->r_tag, tag) != 0)
+ continue;
+
if (ss != NULL &&
(!(path->flags & F_PATH_AUTHENTICATED) &&
! ruleset_check_source(r->r_sources, ss)))
diff --git a/usr.sbin/smtpd/smtp_session.c b/usr.sbin/smtpd/smtp_session.c
index 2f94ff80f3e..928041e2650 100644
--- a/usr.sbin/smtpd/smtp_session.c
+++ b/usr.sbin/smtpd/smtp_session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtp_session.c,v 1.121 2009/10/06 18:20:44 gilles Exp $ */
+/* $OpenBSD: smtp_session.c,v 1.122 2009/10/19 20:48:13 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -417,6 +417,7 @@ session_rfc5321_mail_handler(struct session *s, char *args)
s->s_msg.id = s->s_id;
s->s_msg.session_id = s->s_id;
s->s_msg.session_ss = s->s_ss;
+ (void)strlcpy(s->s_msg.tag, s->s_l->tag, sizeof(s->s_msg.tag));
log_debug("session_rfc5321_mail_handler: sending notification to mfa");
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
index 2b7920f9b24..90d517e9122 100644
--- a/usr.sbin/smtpd/smtpd.h
+++ b/usr.sbin/smtpd/smtpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.h,v 1.148 2009/10/19 20:00:46 gilles Exp $ */
+/* $OpenBSD: smtpd.h,v 1.149 2009/10/19 20:48:13 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -41,6 +41,7 @@
#define MAX_LOCALPART_SIZE 65
#define MAX_DOMAINPART_SIZE MAXHOSTNAMELEN
#define MAX_ID_SIZE 64
+#define MAX_TAG_SIZE 32
/* return and forward path size */
#define MAX_PATH_SIZE 256
@@ -321,6 +322,7 @@ enum action_type {
struct rule {
TAILQ_ENTRY(rule) r_entry;
+ char r_tag[MAX_TAG_SIZE];
int r_accept;
struct map *r_sources;
TAILQ_HEAD(condlist, cond) r_conditions;
@@ -417,6 +419,8 @@ struct message {
u_int64_t session_id;
u_int64_t batch_id;
+ char tag[MAX_TAG_SIZE];
+
char message_id[MAX_ID_SIZE];
char message_uid[MAX_ID_SIZE];
@@ -522,6 +526,7 @@ struct listener {
char ssl_cert_name[PATH_MAX];
struct ssl *ssl;
void *ssl_ctx;
+ char tag[MAX_TAG_SIZE];
TAILQ_ENTRY(listener) entry;
};