doas: add optional timeout to persist directive
Anthony BOCCI <[email protected]> Sat, 01 Aug 2026 15:26:06 +0000
| Newsgroups | gmane.os.openbsd.tech |
|---|---|
| Message-ID | <LF7o3tepEYpCVCC6-qUfCAI3hVXquoKj8ItcKES-YOHOC2ca7TGTLOELzCq1HEiEIw-rvQ-5o1ai8oOEcYmhAn4q7DtR5K1JMOCvyZA8MkE=@abosec.fr> |
This is an OpenPGP/MIME signed message (RFC 4880 and 3156)
--------d7653d291080ff3bf85f325963c9b4f0ff79b206cc08b63065646101fcc405fc
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;charset=utf-8
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 =3D -1;
@@ -258,7 +258,7 @@ authuser(char *myname, char *login_style, int persist)
exit(1);
good:
if (fd !=3D -1) {
- int secs =3D 5 * 60;
+ int secs =3D (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->time=
out);
}
if ((p =3D getenv("PATH")) !=3D 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 =3D $1.action;
r->options =3D $1.options;
r->envlist =3D $1.envlist;
+ r->timeout =3D $1.timeout;
r->ident =3D $2.str;
r->target =3D $3.str;
r->cmd =3D $4.cmd;
@@ -111,6 +114,7 @@ action: TPERMIT options {
$$.action =3D PERMIT;
$$.options =3D $2.options;
$$.envlist =3D $2.envlist;
+ $$.timeout =3D $2.timeout;
} | TDENY {
$$.action =3D DENY;
$$.options =3D 0;
@@ -120,9 +124,11 @@ action: TPERMIT options {
options: /* none */ {
$$.options =3D 0;
$$.envlist =3D NULL;
+ $$.timeout =3D 0;
} | options option {
$$.options =3D $1.options | $2.options;
$$.envlist =3D $1.envlist;
+ $$.timeout =3D ($2.timeout > 0) ? $2.timeout : $1.timeout;
if (($$.options & (NOPASS|PERSIST)) =3D=3D (NOPASS|PERSIST)) {
yyerror("can't combine nopass and persist");
YYERROR;
@@ -144,6 +150,11 @@ option: TNOPASS {
} | TPERSIST {
$$.options =3D PERSIST;
$$.envlist =3D NULL;
+ $$.timeout =3D 0;
+ } | TPERSIST TNUMBER {
+ $$.options =3D PERSIST;
+ $$.envlist =3D NULL;
+ $$.timeout =3D $2.timeout;
} | TKEEPENV {
$$.options =3D KEEPENV;
$$.envlist =3D 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 =3D 0, quotes =3D 0, qerr =3D 0, escape =3D 0, nonkw =3D 0;
unsigned long qpos =3D 0;
size_t i;
+ long timeout =3D 0;
p =3D buf;
ebuf =3D buf + sizeof(buf);
@@ -342,6 +354,14 @@ eow:
return keywords[i].token;
}
}
+ if (isdigit(buf[0])) {
+ errno =3D 0;
+ timeout =3D strtol(buf, &endptr, 10);
+ if (errno !=3D ERANGE && timeout >=3D 0 && timeout <=3D INT_MAX && *endp=
tr =3D=3D '\0') {
+ yylval.timeout =3D (int)timeout;
+ return TNUMBER;
+ }
+ }
if ((str =3D strdup(buf)) =3D=3D NULL)
err(1, "%s", __func__);
yylval.str =3D str;
--
Anthony=
--------d7653d291080ff3bf85f325963c9b4f0ff79b206cc08b63065646101fcc405fc
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: OpenPGP digital signature
Content-Disposition: attachment; filename="signature.asc"
-----BEGIN PGP SIGNATURE-----
Version: ProtonMail
wrsEARYKAG0FgmpuD/8JEAEjrKiRlre2RRQAAAAAABwAIHNhbHRAbm90YXRp
b25zLm9wZW5wZ3Bqcy5vcmeL6cBle4BX6LG+xuN5pmgiamdVVG7u15zxDKKG
y991pxYhBDpU3BNSwCzjKhgxRwEjrKiRlre2AADJzQD/SRUy7L3Nz8NSmvRz
XdibzgR2gO3eEdFbtt2A1pNY4pAA/1CQQU1WlUJdmiPbCcLoP7nfhnQ2CICg
2L6gVE8XoX8J
=ieFz
-----END PGP SIGNATURE-----
--------d7653d291080ff3bf85f325963c9b4f0ff79b206cc08b63065646101fcc405fc--