summaryrefslogtreecommitdiff
path: root/usr.sbin/smtpd
diff options
context:
space:
mode:
authorGilles Chehade <gilles@cvs.openbsd.org>2018-11-03 13:47:47 +0000
committerGilles Chehade <gilles@cvs.openbsd.org>2018-11-03 13:47:47 +0000
commit44ebe2a59a3c8f1e765634d7d01587bac01bfcc8 (patch)
treef1678dd8174ef5f01188036e72d609705d77037e /usr.sbin/smtpd
parentc452475d031c4151fabfe3172dcfb16754a9f747 (diff)
bring plumbing for proc filters
ok millert@, eric@, jung@
Diffstat (limited to 'usr.sbin/smtpd')
-rw-r--r--usr.sbin/smtpd/lka_filter.c65
-rw-r--r--usr.sbin/smtpd/lka_proc.c58
-rw-r--r--usr.sbin/smtpd/parse.y25
-rw-r--r--usr.sbin/smtpd/smtp_session.c22
-rw-r--r--usr.sbin/smtpd/smtpd.h5
5 files changed, 124 insertions, 51 deletions
diff --git a/usr.sbin/smtpd/lka_filter.c b/usr.sbin/smtpd/lka_filter.c
index 7bbdddd0167..6d8048ec071 100644
--- a/usr.sbin/smtpd/lka_filter.c
+++ b/usr.sbin/smtpd/lka_filter.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lka_filter.c,v 1.1 2018/11/03 13:42:24 gilles Exp $ */
+/* $OpenBSD: lka_filter.c,v 1.2 2018/11/03 13:47:46 gilles Exp $ */
/*
* Copyright (c) 2018 Gilles Chehade <gilles@poolp.org>
@@ -35,10 +35,12 @@
#include "smtpd.h"
#include "log.h"
-static void filter_proceed(uint64_t, enum filter_phase, const char *);
-static void filter_rewrite(uint64_t, enum filter_phase, const char *);
-static void filter_reject(uint64_t, enum filter_phase, const char *);
-static void filter_disconnect(uint64_t, enum filter_phase, const char *);
+static void filter_proceed(uint64_t);
+static void filter_rewrite(uint64_t, const char *);
+static void filter_reject(uint64_t, const char *);
+static void filter_disconnect(uint64_t, const char *);
+
+static void filter_write(const char *, uint64_t, const char *, const char *);
static int filter_exec_notimpl(uint64_t, struct filter_rule *, const char *);
static int filter_exec_connected(uint64_t, struct filter_rule *, const char *);
@@ -78,60 +80,87 @@ lka_filter(uint64_t reqid, enum filter_phase phase, const char *param)
goto proceed;
TAILQ_FOREACH(rule, &env->sc_filter_rules[phase], entry) {
+ if (rule->proc) {
+ filter_write(rule->proc, reqid,
+ filter_execs[i].phase_name, param);
+ return; /* deferred */
+ }
+
if (! filter_execs[i].func(reqid, rule, param)) {
if (rule->rewrite)
- filter_rewrite(reqid, phase, rule->rewrite);
+ filter_rewrite(reqid, rule->rewrite);
else if (rule->disconnect)
- filter_disconnect(reqid, phase, rule->disconnect);
+ filter_disconnect(reqid, rule->disconnect);
else
- filter_reject(reqid, phase, rule->reject);
+ filter_reject(reqid, rule->reject);
return;
}
}
proceed:
- filter_proceed(reqid, phase, param);
+ filter_proceed(reqid);
+}
+
+
+int
+lka_filter_response(uint64_t reqid, const char *response, const char *param)
+{
+ if (strcmp(response, "proceed") == 0)
+ filter_proceed(reqid);
+ else if (strcmp(response, "rewrite") == 0)
+ filter_rewrite(reqid, param);
+ else if (strcmp(response, "reject") == 0)
+ filter_reject(reqid, param);
+ else if (strcmp(response, "disconnect") == 0)
+ filter_disconnect(reqid, param);
+ else
+ return 0;
+ return 1;
}
static void
-filter_proceed(uint64_t reqid, enum filter_phase phase, const char *param)
+filter_write(const char *name, uint64_t reqid, const char *phase, const char *param)
+{
+ if (io_printf(lka_proc_get_io(name),
+ "filter-request|in-smtp-%s|%016"PRIx64"|%s\n",
+ phase, reqid, param) == -1)
+ fatalx("failed to write to processor");
+}
+
+static void
+filter_proceed(uint64_t reqid)
{
m_create(p_pony, IMSG_SMTP_FILTER, 0, 0, -1);
m_add_id(p_pony, reqid);
- m_add_int(p_pony, phase);
m_add_int(p_pony, FILTER_PROCEED);
- m_add_string(p_pony, param);
m_close(p_pony);
}
static void
-filter_rewrite(uint64_t reqid, enum filter_phase phase, const char *param)
+filter_rewrite(uint64_t reqid, const char *param)
{
m_create(p_pony, IMSG_SMTP_FILTER, 0, 0, -1);
m_add_id(p_pony, reqid);
- m_add_int(p_pony, phase);
m_add_int(p_pony, FILTER_REWRITE);
m_add_string(p_pony, param);
m_close(p_pony);
}
static void
-filter_reject(uint64_t reqid, enum filter_phase phase, const char *message)
+filter_reject(uint64_t reqid, const char *message)
{
m_create(p_pony, IMSG_SMTP_FILTER, 0, 0, -1);
m_add_id(p_pony, reqid);
- m_add_int(p_pony, phase);
m_add_int(p_pony, FILTER_REJECT);
m_add_string(p_pony, message);
m_close(p_pony);
}
static void
-filter_disconnect(uint64_t reqid, enum filter_phase phase, const char *message)
+filter_disconnect(uint64_t reqid, const char *message)
{
m_create(p_pony, IMSG_SMTP_FILTER, 0, 0, -1);
m_add_id(p_pony, reqid);
- m_add_int(p_pony, phase);
m_add_int(p_pony, FILTER_DISCONNECT);
m_add_string(p_pony, message);
m_close(p_pony);
diff --git a/usr.sbin/smtpd/lka_proc.c b/usr.sbin/smtpd/lka_proc.c
index 1e7d20b9ab4..693173d8836 100644
--- a/usr.sbin/smtpd/lka_proc.c
+++ b/usr.sbin/smtpd/lka_proc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lka_proc.c,v 1.2 2018/11/01 14:48:49 gilles Exp $ */
+/* $OpenBSD: lka_proc.c,v 1.3 2018/11/03 13:47:46 gilles Exp $ */
/*
* Copyright (c) 2018 Gilles Chehade <gilles@poolp.org>
@@ -45,6 +45,7 @@ struct processor_instance {
};
static void processor_io(struct io *, int, void *);
+static int processor_response(const char *);
void
lka_proc_forked(const char *name, int fd)
@@ -90,6 +91,61 @@ processor_io(struct io *io, int evt, void *arg)
if (line == NULL)
return;
+ if (! processor_response(line))
+ fatalx("misbehaving filter");
+
goto nextline;
}
}
+
+static int
+processor_response(const char *line)
+{
+ uint64_t reqid;
+ char buffer[LINE_MAX];
+ char *ep = NULL;
+ char *qid = NULL;
+ char *response = NULL;
+ char *parameter = NULL;
+
+ (void)strlcpy(buffer, line, sizeof buffer);
+ if ((ep = strchr(buffer, '|')) == NULL)
+ return 0;
+ *ep = 0;
+
+ if (strcmp(buffer, "filter-response") != 0)
+ return 1;
+
+ qid = ep+1;
+ if ((ep = strchr(qid, '|')) == NULL)
+ return 0;
+ *ep = 0;
+
+ reqid = strtoull(qid, &ep, 16);
+ if (qid[0] == '\0' || *ep != '\0')
+ return 0;
+ if (errno == ERANGE && reqid == ULONG_MAX)
+ return 0;
+
+ response = ep+1;
+ if ((ep = strchr(response, '|'))) {
+ parameter = ep + 1;
+ *ep = 0;
+ }
+
+ if (strcmp(response, "proceed") != 0 &&
+ strcmp(response, "reject") != 0 &&
+ strcmp(response, "disconnect") != 0 &&
+ strcmp(response, "rewrite") != 0)
+ return 0;
+
+ if (strcmp(response, "proceed") == 0 &&
+ parameter)
+ return 0;
+
+ if (strcmp(response, "proceed") != 0 &&
+ parameter == NULL)
+ return 0;
+
+ return lka_filter_response(reqid, response, parameter);
+}
diff --git a/usr.sbin/smtpd/parse.y b/usr.sbin/smtpd/parse.y
index e5b4a8c2582..59615fbe7cb 100644
--- a/usr.sbin/smtpd/parse.y
+++ b/usr.sbin/smtpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.226 2018/11/03 13:42:24 gilles Exp $ */
+/* $OpenBSD: parse.y,v 1.227 2018/11/03 13:47:46 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -1133,13 +1133,11 @@ MATCH {
}
;
-/*
filter_action_proc:
ON STRING {
- filter_rule->filter = $2;
+ filter_rule->proc = $2;
}
;
-*/
filter_action_builtin:
REJECT STRING {
@@ -1176,11 +1174,9 @@ filter_phase_connect:
CONNECT {
filter_rule->phase = FILTER_CONNECTED;
} filter_phase_connect_options filter_action_builtin
- /*
| CONNECT {
filter_rule->phase = FILTER_CONNECTED;
} filter_action_proc
- */
;
filter_phase_helo_options:
@@ -1190,22 +1186,18 @@ filter_phase_helo:
HELO {
filter_rule->phase = FILTER_HELO;
} filter_phase_helo_options filter_action_builtin
- /*
| HELO {
filter_rule->phase = FILTER_HELO;
} filter_action_proc
- */
;
filter_phase_ehlo:
EHLO {
filter_rule->phase = FILTER_EHLO;
} filter_phase_helo_options filter_action_builtin
- /*
| EHLO {
filter_rule->phase = FILTER_EHLO;
} filter_action_proc
- */
;
filter_phase_mail_from_options:
@@ -1215,11 +1207,9 @@ filter_phase_mail_from:
MAIL_FROM {
filter_rule->phase = FILTER_MAIL_FROM;
} filter_phase_mail_from_options filter_action_builtin
- /*
| MAIL_FROM {
filter_rule->phase = FILTER_MAIL_FROM;
} filter_action_proc
- */
;
filter_phase_rcpt_to_options:
@@ -1229,59 +1219,48 @@ filter_phase_rcpt_to:
RCPT_TO {
filter_rule->phase = FILTER_RCPT_TO;
} filter_phase_rcpt_to_options filter_action_builtin
- /*
| RCPT_TO {
filter_rule->phase = FILTER_RCPT_TO;
} filter_action_proc
- */
;
filter_phase_data:
DATA {
filter_rule->phase = FILTER_DATA;
} filter_action_builtin
- /*
| DATA {
filter_rule->phase = FILTER_DATA;
} filter_action_proc
- */
;
filter_phase_quit:
QUIT {
filter_rule->phase = FILTER_QUIT;
} filter_action_builtin
- /*
| QUIT {
filter_rule->phase = FILTER_QUIT;
} filter_action_proc
- */
;
filter_phase_rset:
RSET {
filter_rule->phase = FILTER_RSET;
} filter_action_builtin
- /*
| RSET {
filter_rule->phase = FILTER_RSET;
} filter_action_proc
- */
;
filter_phase_noop:
NOOP {
filter_rule->phase = FILTER_NOOP;
} filter_action_builtin
- /*
| NOOP {
filter_rule->phase = FILTER_NOOP;
} filter_action_proc
- */
;
-
filter_phase:
filter_phase_connect
| filter_phase_helo
diff --git a/usr.sbin/smtpd/smtp_session.c b/usr.sbin/smtpd/smtp_session.c
index 1c165e09aad..6ff46d8a1fa 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.346 2018/11/03 13:42:24 gilles Exp $ */
+/* $OpenBSD: smtp_session.c,v 1.347 2018/11/03 13:47:46 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -146,6 +146,9 @@ struct smtp_session {
struct event pause;
struct smtp_tx *tx;
+
+ enum filter_phase filter_phase;
+ const char *filter_param;
};
#define ADVERTISE_TLS(s) \
@@ -616,7 +619,6 @@ smtp_session_imsg(struct mproc *p, struct imsg *imsg)
uint32_t msgid;
int status, success;
void *ssl_ctx;
- enum filter_phase filter_phase;
int filter_response;
const char *filter_param;
uint8_t i;
@@ -887,9 +889,9 @@ smtp_session_imsg(struct mproc *p, struct imsg *imsg)
case IMSG_SMTP_FILTER:
m_msg(&m, imsg);
m_get_id(&m, &reqid);
- m_get_int(&m, (int *)&filter_phase);
m_get_int(&m, &filter_response);
- m_get_string(&m, &filter_param);
+ if (filter_response != FILTER_PROCEED)
+ m_get_string(&m, &filter_param);
m_end(&m);
s = tree_xpop(&wait_filters, reqid);
@@ -910,13 +912,16 @@ smtp_session_imsg(struct mproc *p, struct imsg *imsg)
break;
case FILTER_PROCEED:
+ filter_param = s->filter_param;
+ /* fallthrough*/
+
case FILTER_REWRITE:
- if (filter_phase == FILTER_CONNECTED) {
+ if (s->filter_phase == FILTER_CONNECTED) {
smtp_proceed_connected(s);
return;
}
for (i = 0; i < nitems(commands); ++i)
- if (commands[i].filter_phase == filter_phase) {
+ if (commands[i].filter_phase == s->filter_phase) {
if (filter_response == FILTER_REWRITE)
if (!commands[i].check(s, filter_param))
break;
@@ -1168,7 +1173,7 @@ smtp_command(struct smtp_session *s, char *line)
case CMD_AUTH:
if (!smtp_check_auth(s, args))
break;
- smtp_filter_phase(FILTER_AUTH, s, NULL);
+ smtp_filter_phase(FILTER_AUTH, s, args);
break;
case CMD_MAIL_FROM:
@@ -1463,6 +1468,9 @@ smtp_query_filters(enum filter_phase phase, struct smtp_session *s, const char *
{
uint8_t i;
+ s->filter_phase = phase;
+ s->filter_param = args;
+
if (TAILQ_FIRST(&env->sc_filter_rules[phase])) {
m_create(p_lka, IMSG_SMTP_FILTER, 0, 0, -1);
m_add_id(p_lka, s->id);
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
index e59dd9ac311..175fe8e4784 100644
--- a/usr.sbin/smtpd/smtpd.h
+++ b/usr.sbin/smtpd/smtpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.h,v 1.569 2018/11/03 13:42:24 gilles Exp $ */
+/* $OpenBSD: smtpd.h,v 1.570 2018/11/03 13:47:46 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -1027,7 +1027,7 @@ struct filter_rule {
char *reject;
char *disconnect;
char *rewrite;
- char *filter;
+ char *proc;
int8_t not_table;
struct table *table;
@@ -1305,6 +1305,7 @@ void lka_report_smtp_protocol_server(time_t, uint64_t, const char *);
/* lka_filter.c */
void lka_filter(uint64_t, enum filter_phase, const char *);
+int lka_filter_response(uint64_t, const char *, const char *);
/* lka_session.c */