From: Christian Schulte Subject: smtpd.conf(5): Add domain-from match option in addition to mail-from To: tech@openbsd.org Date: Tue, 24 Sep 2024 05:51:24 +0200 Sorry for disturbing you again. This has been discussed on the OpenSMTPD mailing list, where I got pointed to the "correct" direction. Since I sent a patch to @tech, I somehow feel I should at least send the corrected version here as well. My bad. I should not have sent anything like this here in the first place. All the diff adds is a domain-from match option modeled after the mail-from match option with the only difference, that the domain-from match option will be backed by a table of service K_DOMAIN instead of K_MAILADDR. The discussion on the misc@opensmtpd.org mailing list ended with Hi Can you stop spamming me. That's the last response I got after having used telnet on port 25 to demonstrate that it's exactly about this kind of spamming I woud like to get rid of. I take that response as a proof of concept. It should not have been possible to send those mails without beeing authenticated in the first place. So. Here's the final diff I will be running locally although I hate running something great with patches. I got pointed to various options including writing a table backend myself and got told that this would be flexibility. No. I am not going to write a whole new table backend, when I just can run OpenSMTPD with the following diff applied. Sorry for stealing your time. You have better things to do, of course. I can live with running OpenSMTPD with patches, although I really hate doing that. 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 24 Sep 2024 03:13:33 -0000 @@ -167,7 +167,7 @@ typedef struct { %token ACTION ADMD ALIAS ANY ARROW AUTH AUTH_OPTIONAL %token BACKUP BOUNCE BYPASS %token CA CERT CHAIN CHROOT CIPHERS COMMIT COMPRESSION CONNECT -%token DATA DATA_LINE DHE DISCONNECT DOMAIN +%token DATA DATA_LINE DHE DISCONNECT DOMAIN DOMAIN_FROM %token EHLO ENABLE ENCRYPTION ERROR EXPAND_ONLY %token FCRDNS FILTER FOR FORWARD_ONLY FROM %token GROUP @@ -1129,6 +1129,41 @@ negation TAG REGEX tables { rule->flag_smtp_auth_regex = 1; rule->table_smtp_auth = strdup(t->t_name); } +| negation DOMAIN_FROM tables { + struct table *t = $3; + + if (rule->flag_smtp_domain_from) { + yyerror("domain-from already specified for this rule"); + YYERROR; + } + + if (!table_check_use(t, T_DYNAMIC|T_LIST|T_HASH, K_DOMAIN)) { + yyerror("table \"%s\" may not be used for domain-from lookups", + t->t_name); + YYERROR; + } + + rule->flag_smtp_domain_from = $1 ? -1 : 1; + rule->table_smtp_domain_from = strdup(t->t_name); +} +| negation DOMAIN_FROM REGEX tables { + struct table *t = $4; + + if (rule->flag_smtp_domain_from) { + yyerror("domain-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 domain-from lookups", + t->t_name); + YYERROR; + } + + rule->flag_smtp_domain_from = $1 ? -1 : 1; + rule->flag_smtp_domain_from_regex = 1; + rule->table_smtp_domain_from = strdup(t->t_name); +} | negation MAIL_FROM tables { struct table *t = $3; @@ -1363,6 +1398,48 @@ negation TAG REGEX tables { rule->table_smtp_auth = strdup(t->t_name); } +| negation FROM DOMAIN_FROM tables { + struct table *anyhost = table_find(conf, ""); + 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|T_HASH, K_DOMAIN)) { + yyerror("table \"%s\" may not be used for from lookups", + t->t_name); + YYERROR; + } + + rule->flag_from = 1; + rule->table_from = strdup(anyhost->t_name); + rule->flag_smtp_domain_from = $1 ? -1 : 1; + rule->table_smtp_domain_from = strdup(t->t_name); +} +| negation FROM DOMAIN_FROM REGEX tables { + struct table *anyhost = table_find(conf, ""); + 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; + rule->table_from = strdup(anyhost->t_name); + rule->flag_smtp_domain_from = $1 ? -1 : 1; + rule->flag_smtp_domain_from_regex = 1; + rule->table_smtp_domain_from = strdup(t->t_name); +} + | negation FROM MAIL_FROM tables { struct table *anyhost = table_find(conf, ""); struct table *t = $4; @@ -2667,6 +2744,7 @@ lookup(char *s) { "dhe", DHE }, { "disconnect", DISCONNECT }, { "domain", DOMAIN }, + { "domain-from", DOMAIN_FROM }, { "ehlo", EHLO }, { "encryption", ENCRYPTION }, { "expand-only", EXPAND_ONLY }, 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 24 Sep 2024 03:13:33 -0000 @@ -165,6 +165,27 @@ ruleset_match_smtp_auth(struct rule *r, } static int +ruleset_match_smtp_domain_from(struct rule *r, const struct envelope *evp) +{ + int ret; + const char *key; + struct table *table; + enum table_service service = K_DOMAIN; + + if (!r->flag_smtp_domain_from) + return 1; + + if (r->flag_smtp_domain_from_regex) + service = K_REGEX; + + key = evp->sender.domain; + table = table_find(env, r->table_smtp_domain_from); + ret = table_match(table, service, key); + + return MATCH_RESULT(ret, r->flag_smtp_domain_from); +} + +static int ruleset_match_smtp_mail_from(struct rule *r, const struct envelope *evp) { int ret; @@ -230,6 +251,7 @@ ruleset_match(const struct envelope *evp MATCH_EVAL(ruleset_match_smtp_helo(r, evp)); MATCH_EVAL(ruleset_match_smtp_auth(r, evp)); MATCH_EVAL(ruleset_match_smtp_starttls(r, evp)); + MATCH_EVAL(ruleset_match_smtp_domain_from(r, evp)); MATCH_EVAL(ruleset_match_smtp_mail_from(r, evp)); MATCH_EVAL(ruleset_match_smtp_rcpt_to(r, evp)); goto matched; 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 24 Sep 2024 03:13:33 -0000 @@ -675,6 +675,22 @@ or from the local enqueuer. This is the default, and may be omitted. .It Xo .Op Ic \&! +.Cm from domain-from +.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-from regex +.Ar domain | Pf < Ar domain Ns > +.Xc +Specify that session may originate from regex or regex list +.Ar domain , +no matter the source IP address. +.It Xo +.Op Ic \&! .Cm from mail-from .Ar sender | Pf < Ar sender Ns > .Xc 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 24 Sep 2024 03:13:33 -0000 @@ -1236,12 +1236,14 @@ struct rule { int8_t flag_smtp_helo; int8_t flag_smtp_starttls; int8_t flag_smtp_auth; + int8_t flag_smtp_domain_from; int8_t flag_smtp_mail_from; int8_t flag_smtp_rcpt_to; int8_t flag_smtp_helo_regex; int8_t flag_smtp_starttls_regex; int8_t flag_smtp_auth_regex; + int8_t flag_smtp_domain_from_regex; int8_t flag_smtp_mail_from_regex; int8_t flag_smtp_rcpt_to_regex; @@ -1252,6 +1254,7 @@ struct rule { char *table_smtp_helo; char *table_smtp_auth; + char *table_smtp_domain_from; char *table_smtp_mail_from; char *table_smtp_rcpt_to; Index: usr.sbin/smtpd/to.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/to.c,v retrieving revision 1.50 diff -u -p -u -r1.50 to.c --- usr.sbin/smtpd/to.c 31 May 2023 16:51:46 -0000 1.50 +++ usr.sbin/smtpd/to.c 24 Sep 2024 03:13:33 -0000 @@ -480,6 +480,13 @@ rule_to_text(struct rule *r) (void)strlcat(buf, " tls", sizeof buf); } + if (r->flag_smtp_domain_from) { + if (r->flag_smtp_domain_from < 0) + (void)strlcat(buf, " !", sizeof buf); + (void)strlcat(buf, " domain-from ", sizeof buf); + (void)strlcat(buf, r->table_smtp_domain_from, sizeof buf); + } + if (r->flag_smtp_mail_from) { if (r->flag_smtp_mail_from < 0) (void)strlcat(buf, " !", sizeof buf);