~armaan/opendoas

b5d211d5d75b031f70e12565e704e7a9c817df83 — Armaan Bhojwani 4 months ago 71b759e v6.9
Add insult option to doas.conf
7 files changed, 31 insertions(+), 18 deletions(-)

M README.md
M doas.c
M doas.conf.5
M doas.h
M pam.c
M parse.y
M shadow.c
M README.md => README.md +2 -1
@@ 7,7 7,8 @@ initially [written by Ted Unangst](http://www.tedunangst.com/flak/post/doas)
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


M doas.c => doas.c +6 -3
@@ 237,11 237,12 @@ mygetpwuid_r(uid_t uid, struct passwd *pwd, struct passwd **result)
}

void
authfail(void)
authfail(int opt)
{

#ifdef DOAS_INSULTS
	printf("%s\n", getinsult());
	if (opt)
		printf("%s\n", getinsult());
#endif

	errx(1, "Authentication failed");


@@ 366,7 367,9 @@ main(int argc, char **argv)
		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 */

M doas.conf.5 => doas.conf.5 +2 -0
@@ 67,6 67,8 @@ is a
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.

M doas.h => doas.h +4 -3
@@ 43,13 43,14 @@ char **prepenv(const struct rule *, const struct passwd *,
#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


@@ 59,4 60,4 @@ int timestamp_clear(void);
#endif

const char * getinsult(void);
void authfail(void);
void authfail(int);

M pam.c => pam.c +6 -5
@@ 226,7 226,7 @@ close:
	exit(status);
}

void
int
pamauth(const char *user, const char *myname, int interactive, int nopass, int persist)
{
	static const struct pam_conv conv = {


@@ 245,7 245,7 @@ pamauth(const char *user, const char *myname, int interactive, int nopass, int p
#endif

	if (!user || !myname)
		authfail();
		return(5);

	ret = pam_start(PAM_SERVICE_NAME, myname, &conv, &pamh);
	if (ret != PAM_SUCCESS)


@@ 277,7 277,7 @@ pamauth(const char *user, const char *myname, int interactive, int nopass, int p

	if (!nopass) {
		if (!interactive)
			authfail();
			return(5);

		/* doas style prompt for pam */
		char host[HOST_NAME_MAX + 1];


@@ 291,7 291,7 @@ pamauth(const char *user, const char *myname, int interactive, int nopass, int p
		if (ret != PAM_SUCCESS) {
			pamcleanup(ret, sess, cred);
			syslog(LOG_AUTHPRIV | LOG_NOTICE, "failed auth for %s", myname);
			authfail();
			return(5);
		}
	}



@@ 304,7 304,7 @@ pamauth(const char *user, const char *myname, int interactive, int nopass, int p
	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 */


@@ 346,4 346,5 @@ pamauth(const char *user, const char *myname, int interactive, int nopass, int p
	}
#endif
	watchsession(child, sess, cred);
	return(0);
}

M parse.y => parse.y +5 -1
@@ 75,7 75,7 @@ arraylen(const char **arr)
%}

%token TPERMIT TDENY TAS TCMD TARGS
%token TNOPASS TNOLOG TPERSIST TKEEPENV TSETENV
%token TNOPASS TNOLOG TPERSIST TKEEPENV TSETENV TINSULT
%token TSTRING

%%


@@ 150,6 150,9 @@ option:		TNOPASS {
		} | TKEEPENV {
			$$.options = KEEPENV;
			$$.envlist = NULL;
		} | TINSULT {
			$$.options = INSULT;
			$$.envlist = NULL;
		} | TSETENV '{' strlist '}' {
			$$.options = 0;
			$$.envlist = $3.strlist;


@@ 221,6 224,7 @@ static struct keyword {
	{ "persist", TPERSIST },
	{ "keepenv", TKEEPENV },
	{ "setenv", TSETENV },
	{ "insult", TINSULT },
};

int

M shadow.c => shadow.c +6 -5
@@ 41,7 41,7 @@
#define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
#endif

void
int
shadowauth(const char *myname, int persist)
{
	const char *hash;


@@ 68,11 68,11 @@ shadowauth(const char *myname, int persist)
	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];


@@ 93,12 93,12 @@ shadowauth(const char *myname, int persist)
	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


@@ 108,4 108,5 @@ good:
		close(fd);
	}
#endif
	return(0);
}