diff options
author | Gilles Chehade <gilles@cvs.openbsd.org> | 2018-11-03 13:47:47 +0000 |
---|---|---|
committer | Gilles Chehade <gilles@cvs.openbsd.org> | 2018-11-03 13:47:47 +0000 |
commit | 44ebe2a59a3c8f1e765634d7d01587bac01bfcc8 (patch) | |
tree | f1678dd8174ef5f01188036e72d609705d77037e /usr.sbin/smtpd | |
parent | c452475d031c4151fabfe3172dcfb16754a9f747 (diff) |
bring plumbing for proc filters
ok millert@, eric@, jung@
Diffstat (limited to 'usr.sbin/smtpd')
-rw-r--r-- | usr.sbin/smtpd/lka_filter.c | 65 | ||||
-rw-r--r-- | usr.sbin/smtpd/lka_proc.c | 58 | ||||
-rw-r--r-- | usr.sbin/smtpd/parse.y | 25 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtp_session.c | 22 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 5 |
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 */ |