aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGilles Chehade <gilles@poolp.org>2018-12-21 23:10:05 +0100
committerGilles Chehade <gilles@poolp.org>2018-12-21 23:10:05 +0100
commit6cb70e9ac0e3a295ac26d974b7850639140ee6b9 (patch)
tree1e69c83f5660949ff9f0ad4967286fa5526eff26
parentbleh (diff)
downloadOpenSMTPD-6cb70e9ac0e3a295ac26d974b7850639140ee6b9.tar.xz
OpenSMTPD-6cb70e9ac0e3a295ac26d974b7850639140ee6b9.zip
sync
-rw-r--r--smtpd/lka_filter.c11
-rw-r--r--smtpd/lka_proc.c2
-rw-r--r--smtpd/parse.y132
-rw-r--r--smtpd/ruleset.c38
-rw-r--r--smtpd/smtpd.conf.547
-rw-r--r--smtpd/smtpd.h12
-rw-r--r--smtpd/table.c10
7 files changed, 232 insertions, 20 deletions
diff --git a/smtpd/lka_filter.c b/smtpd/lka_filter.c
index 3481cf0d..f9e472df 100644
--- a/smtpd/lka_filter.c
+++ b/smtpd/lka_filter.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lka_filter.c,v 1.19 2018/12/21 17:31:57 gilles Exp $ */
+/* $OpenBSD: lka_filter.c,v 1.21 2018/12/21 20:38:42 gilles Exp $ */
/*
* Copyright (c) 2018 Gilles Chehade <gilles@poolp.org>
@@ -268,7 +268,6 @@ lka_filter_proc_in_session(uint64_t reqid, const char *proc)
return 0;
filter = dict_get(&filters, fs->filter_name);
-
if (filter->proc == NULL && filter->chain == NULL)
return 0;
@@ -533,9 +532,11 @@ filter_protocol_next(uint64_t token, uint64_t reqid, const char *param)
struct filter_entry *filter_entry;
struct filter *filter;
- fs = tree_xget(&sessions, reqid);
- filter_chain = dict_get(&filter_chains, fs->filter_name);
+ /* client session may have disappeared while we were in proc */
+ if ((fs = tree_xget(&sessions, reqid)) == NULL)
+ return;
+ filter_chain = dict_get(&filter_chains, fs->filter_name);
TAILQ_FOREACH(filter_entry, &filter_chain->chain[fs->phase], entries)
if (filter_entry->id == token)
break;
@@ -593,7 +594,7 @@ filter_data_next(uint64_t token, uint64_t reqid, const char *line)
struct filter_entry *filter_entry;
struct filter *filter;
- /* client session may have disappeared since we started streaming data */
+ /* client session may have disappeared while we were in proc */
if ((fs = tree_get(&sessions, reqid)) == NULL)
return;
diff --git a/smtpd/lka_proc.c b/smtpd/lka_proc.c
index 2b34e7a7..fb3a4137 100644
--- a/smtpd/lka_proc.c
+++ b/smtpd/lka_proc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lka_proc.c,v 1.5 2018/12/21 14:33:52 gilles Exp $ */
+/* $OpenBSD: lka_proc.c,v 1.6 2018/12/21 19:07:47 gilles Exp $ */
/*
* Copyright (c) 2018 Gilles Chehade <gilles@poolp.org>
diff --git a/smtpd/parse.y b/smtpd/parse.y
index 400afbf4..d0efed8b 100644
--- a/smtpd/parse.y
+++ b/smtpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.239 2018/12/21 17:04:46 gilles Exp $ */
+/* $OpenBSD: parse.y,v 1.241 2018/12/21 21:35:29 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -190,7 +190,7 @@ typedef struct {
%token ON
%token PKI PORT PROC PROC_EXEC
%token QUEUE QUIT
-%token RCPT_TO RECIPIENT RECEIVEDAUTH RELAY REJECT REPORT REWRITE RSET
+%token RCPT_TO RECIPIENT RECEIVEDAUTH REGEX RELAY REJECT REPORT REWRITE RSET
%token SCHEDULER SENDER SENDERS SMTP SMTP_IN SMTP_OUT SMTPS SOCKET SRC SUB_ADDR_DELIM
%token TABLE TAG TAGGED TLS TLS_REQUIRE TTL
%token USER USERBASE
@@ -908,6 +908,25 @@ negation TAG tables {
rule->flag_tag = $1 ? -1 : 1;
rule->table_tag = strdup(t->t_name);
}
+|
+negation TAG REGEX tables {
+ struct table *t = $4;
+
+ if (rule->flag_tag) {
+ yyerror("tag already specified for this rule");
+ YYERROR;
+ }
+
+ if (!table_check_use(t, T_DYNAMIC|T_LIST, K_REGEX)) {
+ yyerror("table \"%s\" may not be used for tag lookups",
+ t->t_name);
+ YYERROR;
+ }
+
+ rule->flag_tag = $1 ? -1 : 1;
+ rule->flag_tag_regex = 1;
+ rule->table_tag = strdup(t->t_name);
+}
| negation HELO tables {
struct table *t = $3;
@@ -925,6 +944,24 @@ negation TAG tables {
rule->flag_smtp_helo = $1 ? -1 : 1;
rule->table_smtp_helo = strdup(t->t_name);
}
+| negation HELO REGEX tables {
+ struct table *t = $4;
+
+ if (rule->flag_smtp_helo) {
+ yyerror("mail-helo already specified for this rule");
+ YYERROR;
+ }
+
+ if (!table_check_use(t, T_DYNAMIC|T_LIST, K_REGEX)) {
+ yyerror("table \"%s\" may not be used for helo lookups",
+ t->t_name);
+ YYERROR;
+ }
+
+ rule->flag_smtp_helo = $1 ? -1 : 1;
+ rule->flag_smtp_helo_regex = 1;
+ rule->table_smtp_helo = strdup(t->t_name);
+}
| negation TLS {
if (rule->flag_smtp_starttls) {
yyerror("tls already specified for this rule");
@@ -956,6 +993,24 @@ negation TAG tables {
rule->flag_smtp_auth = $1 ? -1 : 1;
rule->table_smtp_auth = strdup(t->t_name);
}
+| negation AUTH REGEX tables {
+ struct table *t = $4;
+
+ if (rule->flag_smtp_auth) {
+ yyerror("auth already specified for this rule");
+ YYERROR;
+ }
+
+ if (!table_check_use(t, T_DYNAMIC|T_LIST, K_REGEX)) {
+ yyerror("table \"%s\" may not be used for auth lookups",
+ t->t_name);
+ YYERROR;
+ }
+
+ rule->flag_smtp_auth = $1 ? -1 : 1;
+ rule->flag_smtp_auth_regex = 1;
+ rule->table_smtp_auth = strdup(t->t_name);
+}
| negation MAIL_FROM tables {
struct table *t = $3;
@@ -973,6 +1028,24 @@ negation TAG tables {
rule->flag_smtp_mail_from = $1 ? -1 : 1;
rule->table_smtp_mail_from = strdup(t->t_name);
}
+| negation MAIL_FROM REGEX tables {
+ struct table *t = $4;
+
+ if (rule->flag_smtp_mail_from) {
+ yyerror("mail-from already specified for this rule");
+ YYERROR;
+ }
+
+ if (!table_check_use(t, T_DYNAMIC|T_LIST, K_REGEX)) {
+ yyerror("table \"%s\" may not be used for mail-from lookups",
+ t->t_name);
+ YYERROR;
+ }
+
+ rule->flag_smtp_mail_from = $1 ? -1 : 1;
+ rule->flag_smtp_mail_from_regex = 1;
+ rule->table_smtp_mail_from = strdup(t->t_name);
+}
| negation RCPT_TO tables {
struct table *t = $3;
@@ -990,6 +1063,24 @@ negation TAG tables {
rule->flag_smtp_rcpt_to = $1 ? -1 : 1;
rule->table_smtp_rcpt_to = strdup(t->t_name);
}
+| negation RCPT_TO REGEX tables {
+ struct table *t = $4;
+
+ if (rule->flag_smtp_rcpt_to) {
+ yyerror("rcpt-to already specified for this rule");
+ YYERROR;
+ }
+
+ if (!table_check_use(t, T_DYNAMIC|T_LIST, K_REGEX)) {
+ yyerror("table \"%s\" may not be used for rcpt-to lookups",
+ t->t_name);
+ YYERROR;
+ }
+
+ rule->flag_smtp_rcpt_to = $1 ? -1 : 1;
+ rule->flag_smtp_rcpt_to_regex = 1;
+ rule->table_smtp_rcpt_to = strdup(t->t_name);
+}
| negation FROM SOCKET {
if (rule->flag_from) {
@@ -1036,6 +1127,24 @@ negation TAG tables {
rule->flag_from = $1 ? -1 : 1;
rule->table_from = strdup(t->t_name);
}
+| negation FROM SRC REGEX tables {
+ struct table *t = $5;
+
+ if (rule->flag_from) {
+ yyerror("from already specified for this rule");
+ YYERROR;
+ }
+
+ if (!table_check_use(t, T_DYNAMIC|T_LIST, K_REGEX)) {
+ yyerror("table \"%s\" may not be used for from lookups",
+ t->t_name);
+ YYERROR;
+ }
+
+ rule->flag_from = $1 ? -1 : 1;
+ rule->flag_from_regex = 1;
+ rule->table_from = strdup(t->t_name);
+}
| negation FOR LOCAL {
struct table *t = table_find(conf, "<localnames>", NULL);
@@ -1074,6 +1183,24 @@ negation TAG tables {
rule->flag_for = $1 ? -1 : 1;
rule->table_for = strdup(t->t_name);
}
+| negation FOR DOMAIN REGEX tables {
+ struct table *t = $5;
+
+ if (rule->flag_for) {
+ yyerror("for already specified for this rule");
+ YYERROR;
+ }
+
+ if (!table_check_use(t, T_DYNAMIC|T_LIST, K_REGEX)) {
+ yyerror("table \"%s\" may not be used for 'for' lookups",
+ t->t_name);
+ YYERROR;
+ }
+
+ rule->flag_for = $1 ? -1 : 1;
+ rule->flag_for_regex = 1;
+ rule->table_for = strdup(t->t_name);
+}
;
match_options:
@@ -2039,6 +2166,7 @@ lookup(char *s)
{ "rcpt-to", RCPT_TO },
{ "received-auth", RECEIVEDAUTH },
{ "recipient", RECIPIENT },
+ { "regex", REGEX },
{ "reject", REJECT },
{ "relay", RELAY },
{ "rset", RSET },
diff --git a/smtpd/ruleset.c b/smtpd/ruleset.c
index a2617a69..0aa9806c 100644
--- a/smtpd/ruleset.c
+++ b/smtpd/ruleset.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ruleset.c,v 1.36 2018/06/16 19:41:26 gilles Exp $ */
+/* $OpenBSD: ruleset.c,v 1.37 2018/12/21 21:35:29 gilles Exp $ */
/*
* Copyright (c) 2009 Gilles Chehade <gilles@poolp.org>
@@ -55,12 +55,16 @@ ruleset_match_tag(struct rule *r, const struct envelope *evp)
{
int ret;
struct table *table;
+ enum table_service service = K_STRING;
if (!r->flag_tag)
return 1;
+ if (r->flag_tag_regex)
+ service = K_REGEX;
+
table = table_find(env, r->table_tag, NULL);
- if ((ret = ruleset_match_table_lookup(table, evp->tag, K_STRING)) < 0)
+ if ((ret = ruleset_match_table_lookup(table, evp->tag, service)) < 0)
return ret;
return r->flag_tag < 0 ? !ret : ret;
@@ -72,6 +76,7 @@ ruleset_match_from(struct rule *r, const struct envelope *evp)
int ret;
const char *key;
struct table *table;
+ enum table_service service = K_NETADDR;
if (!r->flag_from)
return 1;
@@ -87,8 +92,11 @@ ruleset_match_from(struct rule *r, const struct envelope *evp)
else
key = ss_to_text(&evp->ss);
+ if (r->flag_from_regex)
+ service = K_REGEX;
+
table = table_find(env, r->table_from, NULL);
- if ((ret = ruleset_match_table_lookup(table, key, K_NETADDR)) < 0)
+ if ((ret = ruleset_match_table_lookup(table, key, service)) < 0)
return -1;
return r->flag_from < 0 ? !ret : ret;
@@ -99,13 +107,17 @@ ruleset_match_to(struct rule *r, const struct envelope *evp)
{
int ret;
struct table *table;
+ enum table_service service = K_DOMAIN;
if (!r->flag_for)
return 1;
+ if (r->flag_for_regex)
+ service = K_REGEX;
+
table = table_find(env, r->table_for, NULL);
if ((ret = ruleset_match_table_lookup(table, evp->dest.domain,
- K_DOMAIN)) < 0)
+ service)) < 0)
return -1;
return r->flag_for < 0 ? !ret : ret;
@@ -116,12 +128,16 @@ ruleset_match_smtp_helo(struct rule *r, const struct envelope *evp)
{
int ret;
struct table *table;
+ enum table_service service = K_DOMAIN;
if (!r->flag_smtp_helo)
return 1;
+ if (r->flag_smtp_helo_regex)
+ service = K_REGEX;
+
table = table_find(env, r->table_smtp_helo, NULL);
- if ((ret = ruleset_match_table_lookup(table, evp->helo, K_DOMAIN)) < 0)
+ if ((ret = ruleset_match_table_lookup(table, evp->helo, service)) < 0)
return -1;
return r->flag_smtp_helo < 0 ? !ret : ret;
@@ -169,15 +185,19 @@ ruleset_match_smtp_mail_from(struct rule *r, const struct envelope *evp)
int ret;
const char *key;
struct table *table;
+ enum table_service service = K_MAILADDR;
if (!r->flag_smtp_mail_from)
return 1;
+ if (r->flag_smtp_mail_from_regex)
+ service = K_REGEX;
+
if ((key = mailaddr_to_text(&evp->sender)) == NULL)
return -1;
table = table_find(env, r->table_smtp_mail_from, NULL);
- if ((ret = ruleset_match_table_lookup(table, key, K_MAILADDR)) < 0)
+ if ((ret = ruleset_match_table_lookup(table, key, service)) < 0)
return -1;
return r->flag_smtp_mail_from < 0 ? !ret : ret;
@@ -189,15 +209,19 @@ ruleset_match_smtp_rcpt_to(struct rule *r, const struct envelope *evp)
int ret;
const char *key;
struct table *table;
+ enum table_service service = K_MAILADDR;
if (!r->flag_smtp_rcpt_to)
return 1;
+ if (r->flag_smtp_rcpt_to_regex)
+ service = K_REGEX;
+
if ((key = mailaddr_to_text(&evp->dest)) == NULL)
return -1;
table = table_find(env, r->table_smtp_rcpt_to, NULL);
- if ((ret = ruleset_match_table_lookup(table, key, K_MAILADDR)) < 0)
+ if ((ret = ruleset_match_table_lookup(table, key, service)) < 0)
return -1;
return r->flag_smtp_rcpt_to < 0 ? !ret : ret;
diff --git a/smtpd/smtpd.conf.5 b/smtpd/smtpd.conf.5
index cb776224..8736d3db 100644
--- a/smtpd/smtpd.conf.5
+++ b/smtpd/smtpd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: smtpd.conf.5,v 1.207 2018/12/12 20:21:04 jmc Exp $
+.\" $OpenBSD: smtpd.conf.5,v 1.208 2018/12/21 21:35:29 gilles Exp $
.\"
.\" Copyright (c) 2008 Janne Johansson <jj@openbsd.org>
.\" Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net>
@@ -17,7 +17,7 @@
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.\"
-.Dd $Mdocdate: December 12 2018 $
+.Dd $Mdocdate: December 21 2018 $
.Dt SMTPD.CONF 5
.Os
.Sh NAME
@@ -485,6 +485,13 @@ Specify that session may address the string or list table
.Ar domain .
.It Xo
.Op Ic \&!
+.Cm for domain regex
+.Ar domain | Pf < Ar domain Ns >
+.Xc
+Specify that session may address the regex or regex table
+.Ar domain .
+.It Xo
+.Op Ic \&!
.Cm from any
.Xc
Specify that session may originate from any source.
@@ -508,6 +515,14 @@ Specify that session may only originate from the local enqueuer.
Specify that session may only originate from string or list table
.Ar address
which can be a specific address or a subnet expressed in CIDR-notation.
+.It Xo
+.Op Ic \&!
+.Cm from src regex
+.Ar address | Pf < Ar address Ns >
+.Xc
+Specify that session may only originate from regex or regex table
+.Ar address
+which can be a specific address or a subnet expressed in CIDR-notation.
.El
.Pp
In addition, the following transaction options:
@@ -526,6 +541,13 @@ Specify that session's HELO / EHLO should match the string or list table
.Ar helo-name .
.It Xo
.Op Ic \&!
+.Cm helo regex
+.Ar helo-name | Pf < Ar helo-name Ns >
+.Xc
+Specify that session's HELO / EHLO should match the regex or regex table
+.Ar helo-name .
+.It Xo
+.Op Ic \&!
.Cm mail\-from
.Ar sender | Pf < Ar sender Ns >
.Xc
@@ -533,6 +555,13 @@ Specify that transactions's MAIL FROM should match the string or list table
.Ar sender .
.It Xo
.Op Ic \&!
+.Cm mail\-from regex
+.Ar sender | Pf < Ar sender Ns >
+.Xc
+Specify that transactions's MAIL FROM should match the regex or regex table
+.Ar sender .
+.It Xo
+.Op Ic \&!
.Cm rcpt\-to
.Ar recipient | Pf < Ar recipient Ns >
.Xc
@@ -540,12 +569,26 @@ Specify that transaction's RCPT TO should match the string or list table
.Ar recipient .
.It Xo
.Op Ic \&!
+.Cm rcpt\-to regex
+.Ar recipient | Pf < Ar recipient Ns >
+.Xc
+Specify that transaction's RCPT TO should match the regex or regex table
+.Ar recipient .
+.It Xo
+.Op Ic \&!
.Cm tag Ar tag
.Xc
Matches transactions tagged with the given
.Ar tag .
.It Xo
.Op Ic \&!
+.Cm tag regex Ar tag
+.Xc
+Matches transactions tagged with the given
+.Ar tag
+regex .
+.It Xo
+.Op Ic \&!
.Cm tls
.Xc
Specify that transaction should take place in a TLS channel.
diff --git a/smtpd/smtpd.h b/smtpd/smtpd.h
index 070979a7..d3c7b4d9 100644
--- a/smtpd/smtpd.h
+++ b/smtpd/smtpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.h,v 1.596 2018/12/21 17:04:46 gilles Exp $ */
+/* $OpenBSD: smtpd.h,v 1.597 2018/12/21 21:35:29 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -1203,12 +1203,22 @@ struct rule {
int8_t flag_for;
int8_t flag_from_socket;
+ int8_t flag_tag_regex;
+ int8_t flag_for_regex;
+ int8_t flag_from_regex;
+
int8_t flag_smtp_helo;
int8_t flag_smtp_starttls;
int8_t flag_smtp_auth;
int8_t flag_smtp_mail_from;
int8_t flag_smtp_rcpt_to;
+ int8_t flag_smtp_helo_regex;
+ int8_t flag_smtp_starttls_regex;
+ int8_t flag_smtp_auth_regex;
+ int8_t flag_smtp_mail_from_regex;
+ int8_t flag_smtp_rcpt_to_regex;
+
char *table_tag;
char *table_from;
diff --git a/smtpd/table.c b/smtpd/table.c
index 7577193d..187cb0ed 100644
--- a/smtpd/table.c
+++ b/smtpd/table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: table.c,v 1.32 2018/11/02 13:45:59 gilles Exp $ */
+/* $OpenBSD: table.c,v 1.33 2018/12/21 21:35:29 gilles Exp $ */
/*
* Copyright (c) 2013 Eric Faurot <eric@openbsd.org>
@@ -463,8 +463,14 @@ int
table_regex_match(const char *string, const char *pattern)
{
regex_t preg;
+ int cflags = REG_EXTENDED|REG_NOSUB;
- if (regcomp(&preg, pattern, REG_EXTENDED|REG_NOSUB) != 0)
+ if (strncmp(pattern, "(?i)", 4) == 0) {
+ cflags |= REG_ICASE;
+ pattern += 4;
+ }
+
+ if (regcomp(&preg, pattern, cflags) != 0)
return (0);
if (regexec(&preg, string, 0, NULL, 0) != 0)