untrusted comment: verify with openbsd-66-base.pub
RWSvK/c+cFe24Nnboj1PMZE5lNWPO6yDiz1nnvFzjiJVyt1UhQXi1GeQx0vtgyCOKv090914EufmxN/iI8Jlbj1NNhT4mylAWw0=

OpenBSD 6.6 errata 010, December 3, 2019:

libc's authentication layer performed insufficient username validation.

Apply by doing:
   signify -Vep /etc/signify/openbsd-66-base.pub -x 010_libcauth.patch.sig \
       -m - | (cd /usr/src && patch -p0)

And then rebuild and install libc, su and login:
   cd /usr/src/lib/libc
   make obj
   make
   make install
   cd /usr/src/usr.bin/su
   make obj
   make
   make install
   cd /usr/src/usr.bin/login
   make obj
   make
   make install

Index: lib/libc/gen/auth_subr.c
===================================================================
RCS file: /cvs/src/lib/libc/gen/auth_subr.c,v
diff -u -p -u -r1.53 auth_subr.c
--- lib/libc/gen/auth_subr.c    28 Jun 2019 13:32:41 -0000      1.53
+++ lib/libc/gen/auth_subr.c    3 Dec 2019 06:59:16 -0000
@@ -304,7 +304,7 @@ auth_challenge(auth_session_t *as)
       char path[PATH_MAX];
       int len;

-       if (as == NULL || as->style == NULL || as->name == NULL)
+       if (as == NULL || as->style == NULL || !_auth_validuser(as->name))
               return (NULL);

       len = snprintf(path, sizeof(path), _PATH_AUTHPROG "%s", as->style);
@@ -316,7 +316,7 @@ auth_challenge(auth_session_t *as)
       free(as->challenge);
       as->challenge = NULL;

-       auth_call(as, path, as->style, "-s", "challenge", as->name,
+       auth_call(as, path, as->style, "-s", "challenge", "--", as->name,
           as->class, (char *)NULL);
       if (as->state & AUTH_CHALLENGE)
               as->challenge = auth_getvalue(as, "challenge");
@@ -476,6 +476,10 @@ auth_setitem(auth_session_t *as, auth_it
       case AUTHV_NAME:
               if (value == as->name)
                       return (0);
+               if (value != NULL && !_auth_validuser(value)) {
+                       errno = EINVAL;
+                       return (-1);
+               }
               if (value != NULL && (value = strdup(value)) == NULL)
                       return (-1);
               free(as->name);
@@ -821,6 +825,7 @@ auth_call(auth_session_t *as, char *path
               argv[argc++] = "-v";
               argv[argc++] = "fd=4";          /* AUTH_FD, see below */
       }
+       /* XXX - fail if out of space in argv */
       for (opt = as->optlist; opt != NULL; opt = opt->next) {
               if (argc < Nargc - 2) {
                       argv[argc++] = "-v";
Index: lib/libc/gen/authenticate.c
===================================================================
RCS file: /cvs/src/lib/libc/gen/authenticate.c,v
diff -u -p -u -r1.27 authenticate.c
--- lib/libc/gen/authenticate.c 28 Jun 2019 13:32:41 -0000      1.27
+++ lib/libc/gen/authenticate.c 3 Dec 2019 01:33:42 -0000
@@ -174,6 +174,17 @@ auth_cat(char *file)
DEF_WEAK(auth_cat);

int
+_auth_validuser(const char *name)
+{
+       /* User name must be specified and may not start with a '-'. */
+       if (name == NULL || *name == '\0' || *name == '-') {
+               syslog(LOG_ERR, "invalid user name %s", name ? name : "(NULL)");
+               return 0;
+       }
+       return 1;
+}
+
+int
auth_approval(auth_session_t *as, login_cap_t *lc, char *name, char *type)
{
       int close_on_exit, close_lc_on_exit, len;
@@ -192,6 +203,10 @@ auth_approval(auth_session_t *as, login_

       if (pwd == NULL) {
               if (name != NULL) {
+                       if (!_auth_validuser(name)) {
+                               warnx("cannot approve who we don't recognize");
+                               return (0);
+                       }
                       getpwnam_r(name, &pwstore, pwbuf, sizeof(pwbuf), &pwd);
               } else {
                       getpwuid_r(getuid(), &pwstore, pwbuf, sizeof(pwbuf),
@@ -217,7 +232,7 @@ auth_approval(auth_session_t *as, login_
               }
               if (pwd == NULL && (approve = strchr(name, '.')) != NULL) {
                       strlcpy(path, name, sizeof path);
-                       path[approve-name] = '\0';
+                       path[approve - name] = '\0';
                       getpwnam_r(name, &pwstore, pwbuf, sizeof(pwbuf), &pwd);
               }
               lc = login_getclass(pwd ? pwd->pw_class : NULL);
@@ -290,7 +305,7 @@ auth_approval(auth_session_t *as, login_
               }
       }
       if (approve)
-               auth_call(as, approve, strrchr(approve, '/') + 1, name,
+               auth_call(as, approve, strrchr(approve, '/') + 1, "--", name,
                   lc->lc_class, type, (char *)NULL);

out:
@@ -314,6 +329,8 @@ auth_usercheck(char *name, char *style,
       struct passwd pwstore, *pwd = NULL;
       char *slash;

+       if (!_auth_validuser(name))
+               return (NULL);
       if (strlcpy(namebuf, name, sizeof(namebuf)) >= sizeof(namebuf))
               return (NULL);
       name = namebuf;
@@ -382,6 +399,8 @@ auth_userchallenge(char *name, char *sty
       struct passwd pwstore, *pwd = NULL;
       char *slash, pwbuf[_PW_BUF_LEN];

+       if (!_auth_validuser(name))
+               return (NULL);
       if (strlen(name) >= sizeof(namebuf))
               return (NULL);
       strlcpy(namebuf, name, sizeof namebuf);
@@ -440,7 +459,8 @@ auth_userresponse(auth_session_t *as, ch
       auth_setstate(as, 0);

       if ((style = auth_getitem(as, AUTHV_STYLE)) == NULL ||
-           (name = auth_getitem(as, AUTHV_NAME)) == NULL) {
+           (name = auth_getitem(as, AUTHV_NAME)) == NULL ||
+           !_auth_validuser(name)) {
               if (more == 0)
                       return (auth_close(as));
               return(0);
@@ -466,7 +486,8 @@ auth_userresponse(auth_session_t *as, ch
       } else
               auth_setdata(as, "", 1);

-       auth_call(as, path, style, "-s", "response", name, class, (char *)NULL);
+       auth_call(as, path, style, "-s", "response", "--", name,
+           class, (char *)NULL);

       /*
        * If they authenticated then make sure they did not expire
@@ -495,7 +516,7 @@ auth_verify(auth_session_t *as, char *st
       char path[PATH_MAX];

       if ((name == NULL || style == NULL) && as == NULL)
-               return (as);
+               return (NULL);

       if (as == NULL && (as = auth_open()) == NULL)
               return (NULL);
@@ -509,12 +530,14 @@ auth_verify(auth_session_t *as, char *st

       style = auth_getitem(as, AUTHV_STYLE);
       name = auth_getitem(as, AUTHV_NAME);
+       if (!_auth_validuser(name))
+               return (as);

       snprintf(path, sizeof(path), _PATH_AUTHPROG "%s", style);
       va_start(ap, name);
       auth_set_va_list(as, ap);
       auth_call(as, path, auth_getitem(as, AUTHV_STYLE), "-s",
-           auth_getitem(as, AUTHV_SERVICE), name, (char *)NULL);
+           auth_getitem(as, AUTHV_SERVICE), "--", name, (char *)NULL);
       va_end(ap);
       return (as);
}
Index: lib/libc/hidden/bsd_auth.h
===================================================================
RCS file: /cvs/src/lib/libc/hidden/bsd_auth.h,v
diff -u -p -u -r1.1 bsd_auth.h
--- lib/libc/hidden/bsd_auth.h  12 Sep 2015 15:20:14 -0000      1.1
+++ lib/libc/hidden/bsd_auth.h  3 Dec 2019 01:33:42 -0000
@@ -20,6 +20,10 @@

#include_next <bsd_auth.h>

+__BEGIN_HIDDEN_DECLS
+int _auth_validuser(const char *name);
+__END_HIDDEN_DECLS
+
PROTO_NORMAL(auth_approval);
PROTO_NORMAL(auth_call);
PROTO_NORMAL(auth_cat);
Index: usr.bin/su/su.c
===================================================================
RCS file: /cvs/src/usr.bin/su/su.c,v
diff -u -p -u -r1.77 su.c
--- usr.bin/su/su.c     14 Sep 2019 17:47:01 -0000      1.77
+++ usr.bin/su/su.c     3 Dec 2019 01:33:42 -0000
@@ -149,11 +149,11 @@ main(int argc, char **argv)
       if (pwd == NULL)
               auth_errx(as, 1, "who are you?");
       if ((username = strdup(pwd->pw_name)) == NULL)
-               auth_errx(as, 1, "can't allocate memory");
+               auth_err(as, 1, NULL);
       if (asme && !altshell) {
               if (pwd->pw_shell && *pwd->pw_shell) {
                       if ((shell = strdup(pwd->pw_shell)) == NULL)
-                               auth_errx(as, 1, "can't allocate memory");
+                               auth_err(as, 1, NULL);
               } else {
                       shell = _PATH_BSHELL;
                       iscsh = NO;
@@ -196,7 +196,7 @@ main(int argc, char **argv)
               auth_clean(as);
               if (auth_setitem(as, AUTHV_INTERACTIVE, "True") != 0 ||
                   auth_setitem(as, AUTHV_NAME, user) != 0)
-                       auth_errx(as, 1, "can't allocate memory");
+                       auth_err(as, 1, NULL);
               if ((user = auth_getitem(as, AUTHV_NAME)) == NULL)
                       auth_errx(as, 1, "internal error");
               if (auth_setpwd(as, NULL) || (pwd = auth_getpwd(as)) == NULL) {
@@ -225,6 +225,8 @@ main(int argc, char **argv)
               }
               fprintf(stderr, "Login incorrect\n");
       }
+       if (pwd == NULL)
+               auth_errx(as, 1, "internal error");

       if (pledge("stdio unveil rpath getpw exec id", NULL) == -1)
               err(1, "pledge");
@@ -236,7 +238,7 @@ main(int argc, char **argv)
                               auth_errx(as, 1, "permission denied (shell).");
               } else if (pwd->pw_shell && *pwd->pw_shell) {
                       if ((shell = strdup(pwd->pw_shell)) == NULL)
-                               auth_errx(as, 1, "can't allocate memory");
+                               auth_err(as, 1, NULL);
                       iscsh = UNSET;
               } else {
                       shell = _PATH_BSHELL;
Index: usr.bin/login/login.c
===================================================================
RCS file: /cvs/src/usr.bin/login/login.c,v
diff -u -p -u -r1.71 login.c
--- usr.bin/login/login.c       28 Jun 2019 13:35:01 -0000      1.71
+++ usr.bin/login/login.c       3 Dec 2019 03:45:18 -0000
@@ -340,8 +340,13 @@ main(int argc, char *argv[])
               }
               shell = strrchr(script, '/') + 1;
               auth_setstate(as, AUTH_OKAY);
-               auth_call(as, script, shell,
-                   fflag ? "-f" : username, fflag ? username : 0, (char *)0);
+               if (fflag) {
+                       auth_call(as, script, shell, "-f", "--", username,
+                           (char *)NULL);
+               } else {
+                       auth_call(as, script, shell, "--", username,
+                           (char *)NULL);
+               }
               if (!(auth_getstate(as) & AUTH_ALLOW))
                       quickexit(1);
               auth_setenv(as);
@@ -367,7 +372,7 @@ main(int argc, char *argv[])
       }

       /*
-        * Request the things like the approval script print things
+        * Request that things like the approval script print things
        * to stdout (in particular, the nologins files)
        */
       auth_setitem(as, AUTHV_INTERACTIVE, "True");