Hi!

I have observed a problem with opensmptd which I consider a bug in the
implementation. I already tried to submit a report via
b...@opensmtpd.org, but apart from a bounce due to some incorrect setup
of this alias I did not receive any reply.

Maybe someone on this list can point me into the right direction. :)

I am a relatively new user of opensmtpd (portable, v6.8.0-p2) on
FreeBSD. After looking through the code I believe that the problem is
also present in OpenBSD's version. But let's start from the beginning.

The server hosting my mailboxes has the following configuration:

> table aliases "..."
> srs key "secret"
>
> action "local" mbox alias <aliases>
> action "relay" relay host smtp+tls://mx.example.com srs
> 
> match from any for domain "example.com" action "local"
> match from local for any action "relay"

Note that I setup SRS for mails that are relayed after aliases are
expanded and senders are expanded. My problem is now that opensmptd is
not accepting bounces for SRS sender addresses it generates.

Let's assume my aliases looks like this:

> iwillbounce nonexist...@nonexample.com

When I now send mail to `iwillbou...@example.com` the sender address is
correctly rewritten to `SRS0=...@example.com`. The original sender
address is encoded in this SRS address. If on its following path the
mail bounces, opensmtpd is not accepting bounces for this address.

The SMTP session then looks like this:

> HELO test
> [...]
> MAIL FROM:<>
> [...]
> RCPT TO:<SRS0=...@example.com>
> 550 Invalid recipient: <SRS0=...@example.com>

I was investigating the code for SRS-recipient handling (lka_session.c):

>  /* handle SRS */
>  if (env->sc_srs_key != NULL &&
>      ep.sender.user[0] == '\0' &&
>      (strncasecmp(ep.rcpt.user, "SRS0=", 5) == 0 ||
>      strncasecmp(ep.rcpt.user, "SRS1=", 5) == 0)) {
>      srs_decoded = srs_decode(mailaddr_to_text(&ep.rcpt));
>      if (srs_decoded &&
>          text_to_mailaddr(&ep.rcpt, srs_decoded)) {
>          /* flag envelope internal and override rcpt */
>          ep.flags |= EF_INTERNAL;
>          xn->u.mailaddr = ep.rcpt;
>          lks->envelope = ep;
>      }
>      else {
>          log_warn("SRS failed to decode: %s",
>              mailaddr_to_text(&ep.rcpt));
>      }
>  }
>
>  /* Pass the node through the ruleset */
>  rule = ruleset_match(&ep);
>  if (rule == NULL || rule->reject) {
>      lks->error = (errno == EAGAIN) ?
>          LKA_TEMPFAIL : LKA_PERMFAIL;
>      break;
>  }

If the mail server sends an `MAIL FROM:<>` and `RCPT TO:<SRS0=...@example.com>`
the code path is triggered and the SRS address is rewritten. Note that
`text_to_mailaddr(&ep.rcpt, srs_decoded)` sets the recipient address of
the envelope, but leaves the destination address alone. In my case the
recipient address is the original sender address of the initial mail.
The destination address is still `SRS0=...@example.com`.

For this rewritten internal envelope all rules in the `smtpd.conf` file
are evaluated, as per `rule = ruleset_match(&ep)`.

I think the problem is now that in ruleset.c there is:

> static int
> ruleset_match_to(struct rule *r, const struct envelope *evp)
> {
>   int     ret;
>   struct table    *table;
>   enum table_service service = K_DOMAIN;
>
>   if (!r->flag_for)
>       return 1;
>
>   if (r->flag_for_regex)
>       service = K_REGEX;
> 
>   table = table_find(env, r->table_for);
>   ret = table_match(table, service, evp->dest.domain);
> 
>   return MATCH_RESULT(ret, r->flag_for);
> }

Note that `table_match(table, service, evp->dest.domain)` looks at the
destination address (still @example.com!) and not the recipient address
(srs decoded, original sender).

In the end the first rule is matched (local delivery). If no local user
with the same name exists, the mail is rejected (otherwise it is
delivered to the wrong user). The intended goal is obviously to relay the
bounce notification to the original sender (second rule).

I patched my local version of opensmtpd to also replace the destination
address (`text_to_mailaddr(&ep.dest, srs_decoded)`) and now bounces to
SRS address are relayed correctly to the original sender. Reason for
this is that opensmtpd recognizes that the SRS decoded address is not
local anymore, the first rule does not match and the relay option is
chosen.

To be honest, I am still a bit confused about the difference of
recipient and destination address. I don't know when opensmtpd uses one
or the other. Is it safe to rewrite both addresses in the SRS decoding
case?

It would be great if someone could look into this issue. Of course I am
also interested if the conclusions of my debugging session are correct. :)


Best regards,
Stefan Haller

Reply via email to