of the OpenBSD project to provide 95% of the features of `sudo` with a
fraction of the codebase.
-This fork insults you, similar to `sudo`.
+This fork insults you, similar to `sudo`. To enable, add the "insult" option
+to your `doas.conf`
## Building and installation discouragements
}
void
-authfail(void)
+authfail(int opt)
{
#ifdef DOAS_INSULTS
- printf("%s\n", getinsult());
+ if (opt)
+ printf("%s\n", getinsult());
#endif
errx(1, "Authentication failed");
if (nflag)
errx(1, "Authentication required");
- shadowauth(mypw->pw_name, rule->options & PERSIST);
+ int ret = shadowauth(mypw->pw_name, rule->options & PERSIST);
+ if (ret == 5)
+ authfail(rule->options & INSULT);
}
#elif !defined(USE_PAM)
/* no authentication provider, only allow NOPASS rules */
then the value to be set is taken from the existing environment
variable of the indicated name.
This option is processed after the default environment has been created.
+.It Ic insult
+Insult the user when they get their password wrong.
.El
.It Ar identity
The username to match.
#define KEEPENV 0x2
#define PERSIST 0x4
#define NOLOG 0x8
+#define INSULT 0x10
#ifdef USE_PAM
-void pamauth(const char *, const char *, int, int, int);
+int pamauth(const char *, const char *, int, int, int);
#endif
#ifdef USE_SHADOW
-void shadowauth(const char *, int);
+int shadowauth(const char *, int);
#endif
#ifdef USE_TIMESTAMP
#endif
const char * getinsult(void);
-void authfail(void);
+void authfail(int);
exit(status);
}
-void
+int
pamauth(const char *user, const char *myname, int interactive, int nopass, int persist)
{
static const struct pam_conv conv = {
#endif
if (!user || !myname)
- authfail();
+ return(5);
ret = pam_start(PAM_SERVICE_NAME, myname, &conv, &pamh);
if (ret != PAM_SUCCESS)
if (!nopass) {
if (!interactive)
- authfail();
+ return(5);
/* doas style prompt for pam */
char host[HOST_NAME_MAX + 1];
if (ret != PAM_SUCCESS) {
pamcleanup(ret, sess, cred);
syslog(LOG_AUTHPRIV | LOG_NOTICE, "failed auth for %s", myname);
- authfail();
+ return(5);
}
}
if (ret != PAM_SUCCESS) {
pamcleanup(ret, sess, cred);
syslog(LOG_AUTHPRIV | LOG_NOTICE, "failed auth for %s", myname);
- authfail();
+ return(5);
}
/* set PAM_USER to the user we want to be */
}
#endif
watchsession(child, sess, cred);
+ return(0);
}
%}
%token TPERMIT TDENY TAS TCMD TARGS
-%token TNOPASS TNOLOG TPERSIST TKEEPENV TSETENV
+%token TNOPASS TNOLOG TPERSIST TKEEPENV TSETENV TINSULT
%token TSTRING
%%
} | TKEEPENV {
$$.options = KEEPENV;
$$.envlist = NULL;
+ } | TINSULT {
+ $$.options = INSULT;
+ $$.envlist = NULL;
} | TSETENV '{' strlist '}' {
$$.options = 0;
$$.envlist = $3.strlist;
{ "persist", TPERSIST },
{ "keepenv", TKEEPENV },
{ "setenv", TSETENV },
+ { "insult", TINSULT },
};
int
#define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
#endif
-void
+int
shadowauth(const char *myname, int persist)
{
const char *hash;
if (hash[0] == 'x' && hash[1] == '\0') {
struct spwd *sp;
if ((sp = getspnam(myname)) == NULL) {
- authfail();
+ return(5);
}
hash = sp->sp_pwdp;
} else if (hash[0] != '*') {
- authfail();
+ return(5);
}
char host[HOST_NAME_MAX + 1];
if ((encrypted = crypt(response, hash)) == NULL) {
explicit_bzero(rbuf, sizeof(rbuf));
printf(getinsult());
- authfail();
+ return(5);
}
explicit_bzero(rbuf, sizeof(rbuf));
if (strcmp(encrypted, hash) != 0) {
syslog(LOG_AUTHPRIV | LOG_NOTICE, "failed auth for %s", myname);
- authfail();
+ return(5);
}
#ifdef USE_TIMESTAMP
close(fd);
}
#endif
+ return(0);
}