Hi,

I will get back to you tomorrow as I have a very busy day today.

There is a work-around which is to use the %{mbox.from} variable
which is what we do on mbox and lmtp to avoid empty senders, but
your diff makes sense from a fast read, I need to assess if this
comes with side-effects or not before committing.

Thanks for your mail !

Gilles


On Tue, Nov 27, 2018 at 06:47:14PM +0200, Lauri Tirkkonen wrote:
> Hi, I noticed in my maillog that smtpd is dropping bounce messages
> destined for me on the floor, like so:
> 
>     Nov 27 16:04:44 quickman smtpd[66508]: 0000000000000000 mda delivery 
> evpid=75062f6aefbfab27 from=<> to=<[email protected]> 
> rcpt=<[email protected]> user=lotheac delay=0s result=PermFail stat=Error 
> ("smtpd: mda command line could not be expanded: No such file or directory")
> 
> my smtpd.conf is as follows:
> 
>     # $OpenBSD: smtpd.conf,v 1.11 2018/06/04 21:10:58 jmc Exp $
> 
>     # This is the smtpd server system-wide configuration file.
>     # See smtpd.conf(5) for more information.
> 
>     table aliases file:/etc/mail/aliases
> 
>     pki quickman.lotheac.fi cert "/etc/ssl/quickman.lotheac.fi.fullchain.pem"
>     pki quickman.lotheac.fi key "/etc/ssl/private/quickman.lotheac.fi.key"
> 
>     # To accept external mail, replace with: listen on all
>     #
>     listen on all tls
>     listen on lo0 port 10028 tag DKIM
> 
>     #action "local" maildir alias <aliases>
>     action "local" mda "/etc/mail/mda.sh '%{sender}'"
>     action "relay" relay
>     action "relay_dkim" relay host smtp://127.0.0.1:10027
> 
>     table maildest { "lotheac.fi" "quickman.lotheac.fi" }
>     # Uncomment the following to accept external mail for domain "example.org"
>     #
>     match from any for domain <maildest> action "local"
>     match for local action "local"
>     match tag DKIM for any action "relay"
>     match for any action "relay_dkim"
> 
> 
> so, it seems that the %{sender} expansion is failing somehow. From
> smtpd.conf(5):
> 
>     %{sender}            sender email address, may be empty string
> 
> clearly, in this case it *should* expand to the empty string - there is
> no envelope sender. However mda_expand_token returns 0 if the string
> ends up empty:
> 
> 204         /* expanded string is empty */
> 205         i = strlen(string);
> 206         if (i == 0)
> 207                 return 0;
> 
> and it does, because above 'string' has been set to the empty string
> (lines 119-121):
> 
> 115         if (!strcasecmp("sender", rtoken)) {
> 116                 if (snprintf(tmp, sizeof tmp, "%s@%s",
> 117                         dlv->sender.user, dlv->sender.domain) >= 
> (int)sizeof tmp)
> 118                         return -1;
> 119                 if (strcmp(tmp, "@") == 0)
> 120                         (void)strlcpy(tmp, "", sizeof tmp);
> 121                 string = tmp;
> 122         }
> 
> As an aside the error exit happens with err(), but mda_expand_format
> doesn't actually set errno, so ENOENT is not actually what is happening.
> Maybe that's another bug.
> 
> So, mda_expand_format() assumes that a 0 retval from mda_expand_token()
> is an error, even though it's a valid value (ie. the length of the empty
> string). Maybe it should return (size_t)-1 instead for errors? Diff for
> that below, it makes the expansion work for me.
> 
> I found this on 6.4, but also applies to -CURRENT.
> 
> diff --git a/usr.sbin/smtpd/mda_variables.c b/usr.sbin/smtpd/mda_variables.c
> index a23112c71e8..0a1605772f2 100644
> --- a/usr.sbin/smtpd/mda_variables.c
> +++ b/usr.sbin/smtpd/mda_variables.c
> @@ -75,14 +75,14 @@ mda_expand_token(char *dest, size_t len, const char 
> *token,
>       mods = NULL;
>  
>       if (strlcpy(rtoken, token, sizeof rtoken) >= sizeof rtoken)
> -             return 0;
> +             return -1;
>  
>       /* token[x[:y]] -> extracts optional x and y, converts into offsets */
>       if ((lbracket = strchr(rtoken, '[')) &&
>           (rbracket = strchr(rtoken, ']'))) {
>               /* ] before [ ... or empty */
>               if (rbracket < lbracket || rbracket - lbracket <= 1)
> -                     return 0;
> +                     return -1;
>  
>               *lbracket = *rbracket = '\0';
>                content  = lbracket + 1;
> @@ -102,7 +102,7 @@ mda_expand_token(char *dest, size_t len, const char 
> *token,
>                        }
>                }
>                if (errstr)
> -                      return 0;
> +                      return -1;
>  
>                /* token:mod_1,mod_2,mod_n -> extract modifiers */
>                mods = strchr(rbracket + 1, ':');
> @@ -115,7 +115,7 @@ mda_expand_token(char *dest, size_t len, const char 
> *token,
>       if (!strcasecmp("sender", rtoken)) {
>               if (snprintf(tmp, sizeof tmp, "%s@%s",
>                       dlv->sender.user, dlv->sender.domain) >= (int)sizeof 
> tmp)
> -                     return 0;
> +                     return -1;
>               if (strcmp(tmp, "@") == 0)
>                       (void)strlcpy(tmp, "", sizeof tmp);
>               string = tmp;
> @@ -123,7 +123,7 @@ mda_expand_token(char *dest, size_t len, const char 
> *token,
>       else if (!strcasecmp("rcpt", rtoken)) {
>               if (snprintf(tmp, sizeof tmp, "%s@%s",
>                       dlv->rcpt.user, dlv->rcpt.domain) >= (int)sizeof tmp)
> -                     return 0;
> +                     return -1;
>               if (strcmp(tmp, "@") == 0)
>                       (void)strlcpy(tmp, "", sizeof tmp);
>               string = tmp;
> @@ -131,7 +131,7 @@ mda_expand_token(char *dest, size_t len, const char 
> *token,
>       else if (!strcasecmp("dest", rtoken)) {
>               if (snprintf(tmp, sizeof tmp, "%s@%s",
>                       dlv->dest.user, dlv->dest.domain) >= (int)sizeof tmp)
> -                     return 0;
> +                     return -1;
>               if (strcmp(tmp, "@") == 0)
>                       (void)strlcpy(tmp, "", sizeof tmp);
>               string = tmp;
> @@ -161,17 +161,17 @@ mda_expand_token(char *dest, size_t len, const char 
> *token,
>       else if (!strcasecmp("mbox.from", rtoken)) {
>               if (snprintf(tmp, sizeof tmp, "%s@%s",
>                       dlv->sender.user, dlv->sender.domain) >= (int)sizeof 
> tmp)
> -                     return 0;
> +                     return -1;
>               if (strcmp(tmp, "@") == 0)
>                       (void)strlcpy(tmp, "MAILER-DAEMON", sizeof tmp);
>               string = tmp;
>       }
>       else
> -             return 0;
> +             return -1;
>  
>       if (string != tmp) {
>               if (strlcpy(tmp, string, sizeof tmp) >= sizeof tmp)
> -                     return 0;
> +                     return -1;
>               string = tmp;
>       }
>  
> @@ -187,12 +187,12 @@ mda_expand_token(char *dest, size_t len, const char 
> *token,
>                                               break;
>                                       }
>                                       if (!token_modifiers[i].f(tmp, sizeof 
> tmp))
> -                                             return 0; /* modifier error */
> +                                             return -1; /* modifier error */
>                                       break;
>                               }
>                       }
>                       if ((size_t)i == nitems(token_modifiers))
> -                             return 0; /* modifier not found */
> +                             return -1; /* modifier not found */
>               } while ((mods = sep) != NULL);
>       }
>  
> @@ -208,7 +208,7 @@ mda_expand_token(char *dest, size_t len, const char 
> *token,
>  
>       /* begin offset beyond end of string */
>       if (begoff >= i)
> -             return 0;
> +             return -1;
>  
>       /* end offset beyond end of string, make it end of string */
>       if (endoff >= i)
> @@ -225,13 +225,13 @@ mda_expand_token(char *dest, size_t len, const char 
> *token,
>  
>       /* check that final offsets are valid */
>       if (begoff < 0 || endoff < 0 || endoff < begoff)
> -             return 0;
> +             return -1;
>       endoff += 1; /* end offset is inclusive */
>  
>       /* check that substring does not exceed destination buffer length */
>       i = endoff - begoff;
>       if ((size_t)i + 1 >= len)
> -             return 0;
> +             return -1;
>  
>       string += begoff;
>       for (; i; i--) {
> @@ -308,7 +308,7 @@ mda_expand_format(char *buf, size_t len, const struct 
> deliver *dlv,
>  
>               exptoklen = mda_expand_token(exptok, sizeof exptok, token, dlv,
>                   ui, mda_command);
> -             if (exptoklen == 0)
> +             if (exptoklen == (size_t)-1)
>                       return 0;
>  
>               /* writing expanded token at ptmp will overflow tmpbuf */
> 
> -- 
> Lauri Tirkkonen | lotheac @ IRCnet
> 

-- 
Gilles Chehade                                                 @poolpOrg

https://www.poolp.org                 tip me: https://paypal.me/poolpOrg

Reply via email to