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

Reply via email to