On 22.09.24 18:46, Philipp wrote: > [2024-09-22 16:04] Christian Schulte <c...@schulte.it> >> On 22.09.24 15:35, Christian Schulte wrote: >>> On 22.09.24 12:16, Philipp wrote: >>>> [2024-09-22 09:39] Christian Schulte <c...@schulte.it> >>>>> >>>>> [snip] >>>>> >>>> >>>> There are several problems: >>>> >>>> First of all it's not that simple to know for wich domains your server >>>> is reponsible for. Yes you could check MX recourds and lookup the A >>>> and AAAA records. But a negativ match isn't true, because you might >>>> be a MX later in the chain or run behind some NAT. >>>> >>>> Next when you have a server for outgoing mails and one for incomming >>>> mails the mails within the domain might just be relayed like any other >>>> mail. This way the mails for the "own" domain also flowin like other >>>> mails from extern. There are other setups where your check wouldn't >>>> work. >> >> If a SMTP daemon does not know about which domains it is responsible >> for, I would rate such a setup as broken by design. That would mean >> someone has given up lots of control about the setup. Doing all kinds of >> routing solely based on network addresses and such giving up on SMTP >> semantics, I do not understand why that may make sense. > > You miss the point.
Seems I missed a lot of points by just reading the man page. Would this be ok to add? Adds a new domain-from keyword to the grammar, though. 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 17:22:41 -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, "<anyhost>"); + 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, "<anyhost>"); + 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, "<anyhost>"); 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 22 Sep 2024 17:22:41 -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 22 Sep 2024 17:22:41 -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 22 Sep 2024 17:22:41 -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 22 Sep 2024 17:22:41 -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);