Index | Thread | Search

From:
op@omarpolo.com
Subject:
smtpd: independant match and action order
To:
tech@openbsd.org
Cc:
"Gilles Chehade" <gilles.chehade@gmail.com>
Date:
Sat, 17 May 2025 17:06:34 +0200

Download raw body.

Thread
After an issue on github[1], I realized that we don't seem to document
that an action needs to be defined prior its use in a match statement.

[1]: https://github.com/OpenSMTPD/OpenSMTPD/issues/1285

However, do we need this restriction?  Diff belows moves the action
check after the configuration has been fully parsed.  The downside is
that now you get a generic "referenced unknown action foo" error without
a line number, but the plus side is that action and matches can be put
in any order.

The alternative would just be a man page diff to highlight the ordering
requirement.

Thoughts?


diff /usr/src
path + /usr/src
commit - 26403af47fcfb92c30d7cca9d0ea2e1019abe6fb
blob - aa4dd7f06254e5bdd9ba58d609d357a82fedb45e
file + usr.sbin/smtpd/parse.y
--- usr.sbin/smtpd/parse.y
+++ usr.sbin/smtpd/parse.y
@@ -1508,21 +1508,13 @@ match_option match_options
 | /* empty */
 ;
 
-match_dispatcher:
-STRING {
-	if (dict_get(conf->sc_dispatchers, $1) == NULL) {
-		yyerror("no such dispatcher: %s", $1);
-		YYERROR;
-	}
-	rule->dispatcher = $1;
-}
-;
-
 action:
 REJECT {
 	rule->reject = 1;
 }
-| ACTION match_dispatcher
+| ACTION STRING {
+	rule->dispatcher = $2;
+}
 ;
 
 match:
@@ -3140,6 +3132,15 @@ parse_config(struct smtpd *x_conf, const char *filenam
 	popfile();
 	endservent();
 
+	/* Make sure no unknown actions were referenced */
+	TAILQ_FOREACH(rule, conf->sc_rules, r_entry) {
+		if (dict_get(conf->sc_dispatchers, rule->dispatcher) == NULL) {
+			log_warnx("error: referenced unknown action %s",
+			    rule->dispatcher);
+			errors++;
+		}
+	}
+
 	/* If the socket listener was not configured, create a default one. */
 	if (!conf->sc_sock_listener) {
 		memset(&listen_opts, 0, sizeof listen_opts);