Ask for a password when we're going to fail() anyway, to avoid leaking information about available commands. The sudo(8) behaves the same way, FWIW.
okay? -- WBR, Vadim Zhukov Index: doas.c =================================================================== RCS file: /cvs/src/usr.bin/doas/doas.c,v retrieving revision 1.2 diff -u -p -r1.2 doas.c --- doas.c 16 Jul 2015 21:00:59 -0000 1.2 +++ doas.c 16 Jul 2015 22:05:44 -0000 @@ -249,7 +249,7 @@ main(int argc, char **argv, char **envp) char myname[32]; uid_t uid, target = 0; gid_t groups[NGROUPS_MAX + 1]; - int ngroups; + int ngroups, permitted; struct passwd *pw; struct rule *rule; const char *cmd; @@ -292,17 +292,17 @@ main(int argc, char **argv, char **envp) err(1, "can't get groups"); groups[ngroups++] = getgid(); - if (!permit(uid, groups, ngroups, &rule, target, cmd)) { + permitted = permit(uid, groups, ngroups, &rule, target, cmd); + if (!permitted) syslog(LOG_AUTHPRIV | LOG_NOTICE, "failed command for %s: %s", myname, cmdline); - fail(); - } - - if (!(rule->options & NOPASS)) { + if (!permitted || !(rule->options & NOPASS)) { if (!auth_userokay(myname, NULL, NULL, NULL)) { syslog(LOG_AUTHPRIV | LOG_NOTICE, "failed password for %s", myname); fail(); } } + if (!permitted) + fail(); envp = copyenv((const char **)envp, rule); pw = getpwuid(target);