Download raw body.
doas: add optional timeout to persist directive
Hi,
Currently, the persist timeout in doas is hard-coded to 5 minutes.
In some situations, a shorter timeout is desirable to reduce the
window during which a compromised session could be abused without
re-authentication.
This patch adds an optional argument to the persist keyword in
doas.conf, allowing the user to specify the duration in seconds before
re-authentication is required.
The default remains 300 seconds when no argument is provided, so
existing configurations are unaffected.
Example:
permit persist 30 :wheel
--- usr.bin/doas/doas.c
+++ usr.bin/doas/doas.c
@@ -241,7 +241,7 @@ authuser_checkpass(char *myname, char *login_style)
}
static void
-authuser(char *myname, char *login_style, int persist)
+authuser(char *myname, char *login_style, int persist, int timeout)
{
int i, fd = -1;
@@ -258,7 +258,7 @@ authuser(char *myname, char *login_style, int persist)
exit(1);
good:
if (fd != -1) {
- int secs = 5 * 60;
+ int secs = (timeout > 0) ? timeout : 5 * 60;
ioctl(fd, TIOCSETVERAUTH, &secs);
close(fd);
}
@@ -427,7 +427,7 @@ main(int argc, char **argv)
if (nflag)
errx(1, "Authentication required");
- authuser(mypw->pw_name, login_style, rule->options & PERSIST);
+ authuser(mypw->pw_name, login_style, rule->options & PERSIST, rule->timeout);
}
if ((p = getenv("PATH")) != NULL)
diff --git usr.bin/doas/doas.conf.5 usr.bin/doas/doas.conf.5
index c547366ab0b..c2976d0a48b 100644
--- usr.bin/doas/doas.conf.5
+++ usr.bin/doas/doas.conf.5
@@ -48,9 +48,9 @@ The user is not required to enter a password.
.It Ic nolog
Do not log successful command execution to
.Xr syslogd 8 .
-.It Ic persist
+.It Ic persist Op Ar N
After the user successfully authenticates, do not ask for a password
-again for some time.
+again for N seconds, the default is 5 minutes.
.It Ic keepenv
Environment variables other than those listed in
.Xr doas 1
diff --git usr.bin/doas/doas.h usr.bin/doas/doas.h
index ce6a03618ac..bc9b4fd129c 100644
--- usr.bin/doas/doas.h
+++ usr.bin/doas/doas.h
@@ -18,6 +18,7 @@
struct rule {
int action;
int options;
+ int timeout;
const char *ident;
const char *target;
const char *cmd;
diff --git usr.bin/doas/parse.y usr.bin/doas/parse.y
index 604becb5445..f8902b923b4 100644
--- usr.bin/doas/parse.y
+++ usr.bin/doas/parse.y
@@ -25,6 +25,7 @@
#include <stdio.h>
#include <string.h>
#include <err.h>
+#include <errno.h>
#include "doas.h"
@@ -33,6 +34,7 @@ typedef struct {
struct {
int action;
int options;
+ int timeout;
const char *cmd;
const char **cmdargs;
const char **envlist;
@@ -72,7 +74,7 @@ arraylen(const char **arr)
%token TPERMIT TDENY TAS TCMD TARGS
%token TNOPASS TNOLOG TPERSIST TKEEPENV TSETENV
-%token TSTRING
+%token TSTRING TNUMBER
%%
@@ -91,6 +93,7 @@ rule: action ident target cmd {
r->action = $1.action;
r->options = $1.options;
r->envlist = $1.envlist;
+ r->timeout = $1.timeout;
r->ident = $2.str;
r->target = $3.str;
r->cmd = $4.cmd;
@@ -111,6 +114,7 @@ action: TPERMIT options {
$$.action = PERMIT;
$$.options = $2.options;
$$.envlist = $2.envlist;
+ $$.timeout = $2.timeout;
} | TDENY {
$$.action = DENY;
$$.options = 0;
@@ -120,9 +124,11 @@ action: TPERMIT options {
options: /* none */ {
$$.options = 0;
$$.envlist = NULL;
+ $$.timeout = 0;
} | options option {
$$.options = $1.options | $2.options;
$$.envlist = $1.envlist;
+ $$.timeout = ($2.timeout > 0) ? $2.timeout : $1.timeout;
if (($$.options & (NOPASS|PERSIST)) == (NOPASS|PERSIST)) {
yyerror("can't combine nopass and persist");
YYERROR;
@@ -144,6 +150,11 @@ option: TNOPASS {
} | TPERSIST {
$$.options = PERSIST;
$$.envlist = NULL;
+ $$.timeout = 0;
+ } | TPERSIST TNUMBER {
+ $$.options = PERSIST;
+ $$.envlist = NULL;
+ $$.timeout = $2.timeout;
} | TKEEPENV {
$$.options = KEEPENV;
$$.envlist = NULL;
@@ -224,10 +235,11 @@ static struct keyword {
int
yylex(void)
{
- char buf[1024], *ebuf, *p, *str;
+ char buf[1024], *ebuf, *p, *str, *endptr;
int c, quoted = 0, quotes = 0, qerr = 0, escape = 0, nonkw = 0;
unsigned long qpos = 0;
size_t i;
+ long timeout = 0;
p = buf;
ebuf = buf + sizeof(buf);
@@ -342,6 +354,14 @@ eow:
return keywords[i].token;
}
}
+ if (isdigit(buf[0])) {
+ errno = 0;
+ timeout = strtol(buf, &endptr, 10);
+ if (errno != ERANGE && timeout >= 0 && timeout <= INT_MAX && *endptr == '\0') {
+ yylval.timeout = (int)timeout;
+ return TNUMBER;
+ }
+ }
if ((str = strdup(buf)) == NULL)
err(1, "%s", __func__);
yylval.str = str;
--
Anthony
doas: add optional timeout to persist directive