summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGilles Chehade <gilles@cvs.openbsd.org>2019-09-04 07:28:28 +0000
committerGilles Chehade <gilles@cvs.openbsd.org>2019-09-04 07:28:28 +0000
commit25ec6d31a0c94482a4417c028f52b1ee69b34eff (patch)
tree500f3027b1d6f99936ff0e05b8839f2902fcc908
parent7c604d467f13611322a8f9ce40c3e41fd2d71d71 (diff)
introduce the 'junk' builtin filter action which marks a session or
transaction as junked when a filter matches. this with the maildir junk option allows classifying messages in Spam folder instead of rejecting/disconnecting. ok semarie@, eric@, martijn@
-rw-r--r--usr.sbin/smtpd/lka_filter.c26
-rw-r--r--usr.sbin/smtpd/lka_report.c5
-rw-r--r--usr.sbin/smtpd/parse.y19
-rw-r--r--usr.sbin/smtpd/smtp_session.c22
-rw-r--r--usr.sbin/smtpd/smtpd.conf.518
-rw-r--r--usr.sbin/smtpd/smtpd.h4
6 files changed, 83 insertions, 11 deletions
diff --git a/usr.sbin/smtpd/lka_filter.c b/usr.sbin/smtpd/lka_filter.c
index 42f469f7eb0..e18fecc1d66 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.44 2019/08/29 08:49:55 gilles Exp $ */
+/* $OpenBSD: lka_filter.c,v 1.45 2019/09/04 07:28:27 gilles Exp $ */
/*
* Copyright (c) 2018 Gilles Chehade <gilles@poolp.org>
@@ -56,6 +56,7 @@ static int filter_builtins_mail_from(struct filter_session *, struct filter *, u
static int filter_builtins_rcpt_to(struct filter_session *, struct filter *, uint64_t, const char *);
static void filter_result_proceed(uint64_t);
+static void filter_result_junk(uint64_t);
static void filter_result_rewrite(uint64_t, const char *);
static void filter_result_reject(uint64_t, const char *);
static void filter_result_disconnect(uint64_t, const char *);
@@ -479,6 +480,11 @@ lka_filter_process_response(const char *name, const char *line)
fatalx("Unexpected parameter after proceed: %s", line);
filter_protocol_next(token, reqid, 0);
return;
+ } else if (strcmp(response, "junk") == 0) {
+ if (parameter != NULL)
+ fatalx("Unexpected parameter after junk: %s", line);
+ filter_result_junk(reqid);
+ return;
} else {
if (parameter == NULL)
fatalx("Missing parameter: %s", line);
@@ -574,6 +580,15 @@ filter_protocol_internal(struct filter_session *fs, uint64_t *token, uint64_t re
filter_result_disconnect(reqid, filter->config->disconnect);
return;
}
+ else if (filter->config->junk) {
+ log_trace(TRACE_FILTERS, "%016"PRIx64" filters protocol phase=%s, "
+ "resume=%s, action=junk, filter=%s, query=%s",
+ fs->id, phase_name, resume ? "y" : "n",
+ filter->name,
+ param);
+ filter_result_junk(reqid);
+ return;
+ }
else {
log_trace(TRACE_FILTERS, "%016"PRIx64" filters protocol phase=%s, "
"resume=%s, action=reject, filter=%s, query=%s, response=%s",
@@ -763,6 +778,15 @@ filter_result_proceed(uint64_t reqid)
}
static void
+filter_result_junk(uint64_t reqid)
+{
+ m_create(p_pony, IMSG_FILTER_SMTP_PROTOCOL, 0, 0, -1);
+ m_add_id(p_pony, reqid);
+ m_add_int(p_pony, FILTER_JUNK);
+ m_close(p_pony);
+}
+
+static void
filter_result_rewrite(uint64_t reqid, const char *param)
{
m_create(p_pony, IMSG_FILTER_SMTP_PROTOCOL, 0, 0, -1);
diff --git a/usr.sbin/smtpd/lka_report.c b/usr.sbin/smtpd/lka_report.c
index 1acaff8107c..1b760ced07c 100644
--- a/usr.sbin/smtpd/lka_report.c
+++ b/usr.sbin/smtpd/lka_report.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lka_report.c,v 1.27 2019/08/29 07:23:18 martijn Exp $ */
+/* $OpenBSD: lka_report.c,v 1.28 2019/09/04 07:28:27 gilles Exp $ */
/*
* Copyright (c) 2018 Gilles Chehade <gilles@poolp.org>
@@ -428,6 +428,9 @@ lka_report_smtp_filter_response(const char *direction, struct timeval *tv, uint6
case FILTER_PROCEED:
response_name = "proceed";
break;
+ case FILTER_JUNK:
+ response_name = "junk";
+ break;
case FILTER_REWRITE:
response_name = "rewrite";
break;
diff --git a/usr.sbin/smtpd/parse.y b/usr.sbin/smtpd/parse.y
index 6d7ba697bba..ebb8b364f35 100644
--- a/usr.sbin/smtpd/parse.y
+++ b/usr.sbin/smtpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.259 2019/08/25 03:40:45 martijn Exp $ */
+/* $OpenBSD: parse.y,v 1.260 2019/09/04 07:28:27 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -1297,6 +1297,21 @@ REJECT STRING {
| REWRITE STRING {
filter_config->rewrite = $2;
}
+| JUNK {
+ filter_config->junk = 1;
+}
+;
+
+filter_action_builtin_nojunk:
+REJECT STRING {
+ filter_config->reject = $2;
+}
+| DISCONNECT STRING {
+ filter_config->disconnect = $2;
+}
+| REWRITE STRING {
+ filter_config->rewrite = $2;
+}
;
filter_phase_check_fcrdns:
@@ -1508,7 +1523,7 @@ NOOP {
filter_phase_commit:
COMMIT {
filter_config->phase = FILTER_COMMIT;
-} MATCH filter_phase_commit_options filter_action_builtin
+} MATCH filter_phase_commit_options filter_action_builtin_nojunk
;
diff --git a/usr.sbin/smtpd/smtp_session.c b/usr.sbin/smtpd/smtp_session.c
index a671f6c3ba9..9ac05d92775 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.408 2019/08/28 15:50:36 martijn Exp $ */
+/* $OpenBSD: smtp_session.c,v 1.409 2019/09/04 07:28:27 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -126,6 +126,8 @@ struct smtp_tx {
int rcvcount;
int has_date;
int has_message_id;
+
+ uint8_t junk;
};
struct smtp_session {
@@ -154,6 +156,8 @@ struct smtp_session {
enum smtp_command last_cmd;
enum filter_phase filter_phase;
const char *filter_param;
+
+ uint8_t junk;
};
#define ADVERTISE_TLS(s) \
@@ -970,7 +974,8 @@ smtp_session_imsg(struct mproc *p, struct imsg *imsg)
m_msg(&m, imsg);
m_get_id(&m, &reqid);
m_get_int(&m, &filter_response);
- if (filter_response != FILTER_PROCEED)
+ if (filter_response != FILTER_PROCEED &&
+ filter_response != FILTER_JUNK)
m_get_string(&m, &filter_param);
else
filter_param = NULL;
@@ -998,9 +1003,17 @@ smtp_session_imsg(struct mproc *p, struct imsg *imsg)
smtp_proceed_rollback(s, NULL);
break;
+
+ case FILTER_JUNK:
+ if (s->tx)
+ s->tx->junk = 1;
+ else
+ s->junk = 1;
+ /* fallthrough */
+
case FILTER_PROCEED:
filter_param = s->filter_param;
- /* fallthrough*/
+ /* fallthrough */
case FILTER_REWRITE:
report_smtp_filter_response("smtp-in", s->id, s->filter_phase,
@@ -2815,6 +2828,9 @@ smtp_message_begin(struct smtp_tx *tx)
smtp_reply(s, "354 Enter mail, end with \".\""
" on a line by itself");
+ if (s->junk || (s->tx && s->tx->junk))
+ m_printf(tx, "X-Spam: Yes\n");
+
m_printf(tx, "Received: ");
if (!(s->listener->flags & F_MASK_SOURCE)) {
m_printf(tx, "from %s (%s [%s])",
diff --git a/usr.sbin/smtpd/smtpd.conf.5 b/usr.sbin/smtpd/smtpd.conf.5
index f64f1ae6695..55f626102f7 100644
--- a/usr.sbin/smtpd/smtpd.conf.5
+++ b/usr.sbin/smtpd/smtpd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: smtpd.conf.5,v 1.222 2019/09/03 04:48:20 martijn Exp $
+.\" $OpenBSD: smtpd.conf.5,v 1.223 2019/09/04 07:28:27 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: September 3 2019 $
+.Dd $Mdocdate: September 4 2019 $
.Dt SMTPD.CONF 5
.Os
.Sh NAME
@@ -348,6 +348,15 @@ to disconnect session with
Phase and matching conditions are documented in a specific section,
see
.Sx BUILTIN FILTERING .
+.It Ic filter Ar filter-name Ic phase Ar phase-name Ic match Ar conditions Ic junk
+Register builtin filter
+.Ar filter-name
+matching
+.Ar conditions
+to mark a session or a transaction as junk.
+Phase and matching conditions are documented in a specific section,
+see
+.Sx BUILTIN FILTERING .
.It Ic filter Ar filter-name Ic phase Ar phase-name Ic match Ar conditions Ic reject Ar message
Register builtin filter
.Ar filter-name
@@ -918,15 +927,18 @@ prefixing the table name with the keyword regex.
.It helo regex Pf < Ar table Ns > Ta helo name matches a regex in table
.El
Finally,
-three decisions may be taken at each phase:
+four decisions may be taken:
.Bl -column XXXXXXXXXXXXXXXXXXXXX -offset indent
.It disconnect Ar message Ta the session is disconnected with message
+.It junk Ta the session or transaction is junked
.It reject Ar message Ta the command is rejected with message
.It rewrite Ar value Ta the command parameter is rewritten with value
.El
.Pp
Decisions that involve a message require that the message be RFC valid,
meaning that they should either start with a 4xx or 5xx status code.
+Descisions can be taken at any phase,
+however junking can only happen before a message is committed.
.Ss FORMAT SPECIFIERS
Some configuration directives support expansion of their parameters at runtime.
Such directives (for example
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
index c5eb8ceb5fc..3eeda504c92 100644
--- a/usr.sbin/smtpd/smtpd.h
+++ b/usr.sbin/smtpd/smtpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.h,v 1.633 2019/08/28 15:50:36 martijn Exp $ */
+/* $OpenBSD: smtpd.h,v 1.634 2019/09/04 07:28:27 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -1046,6 +1046,7 @@ struct filter_config {
char *reject;
char *disconnect;
char *rewrite;
+ uint8_t junk;
char *proc;
const char **chain;
@@ -1095,6 +1096,7 @@ enum filter_status {
FILTER_REWRITE,
FILTER_REJECT,
FILTER_DISCONNECT,
+ FILTER_JUNK,
};
enum ca_resp_status {