Index | Thread | Search

From:
Philipp <philipp+obsd@bureaucracy.de>
Subject:
Re: smtpd: do not lowercase creds for K_AUTH
To:
tech@openbsd.org
Cc:
"Omar Polo" <op@omarpolo.com>
Date:
Fri, 27 Mar 2026 08:30:39 +0100

Download raw body.

Thread
  • Philipp:

    smtpd: do not lowercase creds for K_AUTH

[2026-03-21 17:14] "Omar Polo" <op@omarpolo.com>
> some time ago we've introduced a K_AUTH table lookup method, to offload
> the authentication handling to a proc table.  This is different from the
> previous credentials tables because they are supposed to return the hash
> of a password for the given user.
>
> The only problem with this is that we have a lowercase() before reaching
> the table itself, so for K_AUTH we end up lowercasing both the username
> and the password.
>
> The cautious reader will realize that this will leave also the username
> with the original casing.  I'm a bit unsure about what to do.  For
> K_AUTH the caller code will construct a string "username:password"
> without changing the casing, then calls table_lookup().  Being pedantic,
> the username *could* be case-sensitive, so there's a small argument for
> keeping the case as-is.
>
> okay?
>
> diff /home/op/w/smtpd
> path + /home/op/w/smtpd
> commit - 56d54b2a7cc014527ea8ba0e2bacd270917079ed
> blob - aca013debeab51e319144b92b5ac154bb6dca1ec
> file + table.c
> --- table.c
> +++ table.c
> @@ -144,7 +144,7 @@ table_lookup(struct table *table, enum table_service k
>  	r = -1;
>  	if (table->t_backend->lookup == NULL)
>  		errno = ENOTSUP;
> -	else if (!lowercase(lkey, key, sizeof lkey)) {
> +	else if (kind != K_AUTH && !lowercase(lkey, key, sizeof lkey)) {

Your path does't work, because it leaves lkey uninitialized, which is
later used for the lookup. As a quick fix I would suggest to use the
version from likle[0]:

        if (table->t_backend->lookup == NULL)
                errno = ENOTSUP;
+       else if (kind == K_AUTH)
+               r = table->t_backend->lookup(table, kind, key, NULL);
        else if (!lowercase(lkey, key, sizeof lkey)) {
                log_warnx("warn: lookup key too long: %s", key);
                errno = EINVAL;


This still leaves lkey uninitialized, but this is not used in the K_AUTH
case. A better solution would be to seperate the K_AUTH path a bit more
from the lookup path.

Philipp

[0] https://github.com/OpenSMTPD/OpenSMTPD/issues/1268#issue-2643210338