Index | Thread | Search

From:
Christian Schulte <cs@schulte.it>
Subject:
Add match option 'from domain' to smtpd.conf(5)
To:
tech@openbsd.org
Date:
Sun, 22 Sep 2024 08:11:30 +0200

Download raw body.

Thread
smtpd.conf(5) currently supports a "for domain" match option. This diff
adds an additional "from domain" option. Example configuration for a
backup MX case:

table aliases file:/etc/mail/aliases
table domains { "lots-of-domains.com", "large-list.com" }

listen on socket
listen on all

action "local_mail" mbox alias <aliases>
action "outbound" relay
action "backup" relay backup

match from domain <domains> for any !auth reject
match from any for domain <domains> action "backup"
match from any action "local_mail"
match for any action "outbound"

Without "from domain", something similar currently can be achieved by
using "from mail-from regex", but this would require an additional table
I would like to avoid. Primary use case for me is to restrict sending
mail for the non relay case - e.g. when the MSA on port 587 requires
auth and tls for submission, the MTA on port 25 still allows sending
mail to each other @lots-of-domains.com or @large-list.com for the non
relay case. Makes things easier when that list of domains is quite large
or changes frequently.

With the diff applied and that

match from domain <domains> for any !auth reject

line in the configuration, OpenSMTPD will reject such mails.

Index: usr.sbin/smtpd//parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/parse.y,v
retrieving revision 1.299
diff -u -p -u -r1.299 parse.y
--- usr.sbin/smtpd//parse.y	19 Feb 2024 21:00:19 -0000	1.299
+++ usr.sbin/smtpd//parse.y	22 Sep 2024 05:47:51 -0000
@@ -1228,6 +1228,43 @@ negation TAG REGEX tables {
 	rule->flag_from = $1 ? -1 : 1;
 	rule->table_from = strdup(t->t_name);
 }
+| negation FROM DOMAIN tables {
+	struct table   *t = $4;
+
+	if (rule->flag_from) {
+		yyerror("from already specified for this rule");
+		YYERROR;
+	}
+
+	if (!table_check_use(t, T_DYNAMIC|T_LIST, K_DOMAIN)) {
+		yyerror("table \"%s\" may not be used for 'from' lookups",
+		    t->t_name);
+		YYERROR;
+	}
+
+	rule->flag_from = $1 ? -1 : 1;
+	rule->flag_from_domain = 1;
+	rule->table_from = strdup(t->t_name);
+}
+| negation FROM DOMAIN 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_domain = 1;
+	rule->flag_from_regex = 1;
+	rule->table_from = strdup(t->t_name);
+}
 | negation FROM SRC tables {
 	struct table   *t = $4;

Index: usr.sbin/smtpd//ruleset.c
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/ruleset.c,v
retrieving revision 1.48
diff -u -p -u -r1.48 ruleset.c
--- usr.sbin/smtpd//ruleset.c	14 Jun 2021 17:58:16 -0000	1.48
+++ usr.sbin/smtpd//ruleset.c	22 Sep 2024 05:47:51 -0000
@@ -70,6 +70,10 @@ ruleset_match_from(struct rule *r, const
 			return 0;
 		key = evp->hostname;
 	}
+	else if (r->flag_from_domain) {
+		key = evp->sender.domain;
+		service = K_DOMAIN;
+	}
 	else {
 		key = ss_to_text(&evp->ss);
 		if (r->flag_from_socket) {
Index: usr.sbin/smtpd//smtpd.conf.5
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/smtpd.conf.5,v
retrieving revision 1.272
diff -u -p -u -r1.272 smtpd.conf.5
--- usr.sbin/smtpd//smtpd.conf.5	26 Jul 2024 06:24:52 -0000	1.272
+++ usr.sbin/smtpd//smtpd.conf.5	22 Sep 2024 05:47:51 -0000
@@ -668,6 +668,23 @@ Specify that session may originate from
 no matter the source IP address.
 .It Xo
 .Op Ic \&!
+.Cm from domain
+.Ar domain | Pf < Ar domain Ns >
+.Xc
+Specify that session may originate from sender domain or sender domain list
+.Ar domain ,
+no matter the source IP address.
+.It Xo
+.Op Ic \&!
+.Cm from domain regex
+.Ar domain | Pf < Ar domain Ns >
+.Xc
+Specify that session may originate from sender domain regex or sender
domain
+regex list
+.Ar domain ,
+no matter the source IP address.
+.It Xo
+.Op Ic \&!
 .Cm from local
 .Xc
 Specify that session may only originate from a local IP address,
Index: usr.sbin/smtpd//smtpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/smtpd.h,v
retrieving revision 1.688
diff -u -p -u -r1.688 smtpd.h
--- usr.sbin/smtpd//smtpd.h	3 Sep 2024 12:07:40 -0000	1.688
+++ usr.sbin/smtpd//smtpd.h	22 Sep 2024 05:47:51 -0000
@@ -1226,6 +1226,7 @@ struct rule {
 	int8_t	flag_tag;
 	int8_t	flag_from;
 	int8_t	flag_for;
+	int8_t	flag_from_domain;
 	int8_t	flag_from_rdns;
 	int8_t	flag_from_socket;