From part 1:

On Thu, 16 Mar 2017 12:04:44 +1100
<bytevolc...@safe-mail.net> wrote:

> On Wed, 15 Mar 2017 20:15:26 -0400
> "Ted Unangst" <t...@tedunangst.com> wrote:
> 
> > Did I get it backwards? If you have setenv { HERE= there }, your
> > diff changes behavior.
> >   
> 
> Now I see where you are coming from. It's meant to empty $HERE, and
> copy $there. Thanks, I'll look into this.
> 

So I looked into this and gave up. Whilst I fixed the problem you
mentioned, the lexer became much more complex and confusing than I
expected, and I introduced a static variable.


Out of interest, here is the second patch, diff from stock doas(1),
adding an option to vary the "persist" timeout.

The only change in behaviour I see now is that commands or arguments
in the form "<keyword>=<string>" need to be escaped or placed in quotes.
For example, "persist=yes", "permit=yea", "deny=nah" need escaping, but
"persistence=low", "permission=granted", "denial=really" are fine.

Also "keepenv { HERE= there }" amongst others, works like before.

------

Index: usr.bin/doas/doas.c
===================================================================
RCS file: /cvs/src/usr.bin/doas/doas.c,v
retrieving revision 1.70
diff -u -p -r1.70 doas.c
--- usr.bin/doas/doas.c 9 Mar 2017 21:25:01 -0000       1.70
+++ usr.bin/doas/doas.c 16 Mar 2017 15:52:18 -0000
@@ -200,7 +200,7 @@ authuser(char *myname, char *login_style
        auth_session_t *as;
        int fd = -1;
 
-       if (persist)
+       if (persist > 0)
                fd = open("/dev/tty", O_RDWR);
        if (fd != -1) {
                if (ioctl(fd, TIOCCHKVERAUTH) == 0)
@@ -233,8 +233,7 @@ authuser(char *myname, char *login_style
        explicit_bzero(rbuf, sizeof(rbuf));
 good:
        if (fd != -1) {
-               int secs = 5 * 60;
-               ioctl(fd, TIOCSETVERAUTH, &secs);
+               ioctl(fd, TIOCSETVERAUTH, &persist);
                close(fd);
        }
 }
@@ -361,7 +360,8 @@ main(int argc, char **argv)
                if (nflag)
                        errx(1, "Authorization required");
 
-               authuser(myname, login_style, rule->options & PERSIST);
+               authuser(myname, login_style,
+                       ((rule->options & PERSIST) ? rule->persist : 0));
        }
 
        if (pledge("stdio rpath getpw exec id", NULL) == -1)
Index: usr.bin/doas/doas.conf.5
===================================================================
RCS file: /cvs/src/usr.bin/doas/doas.conf.5,v
retrieving revision 1.31
diff -u -p -r1.31 doas.conf.5
--- usr.bin/doas/doas.conf.5    5 Dec 2016 10:58:07 -0000       1.31
+++ usr.bin/doas/doas.conf.5    16 Mar 2017 15:52:18 -0000
@@ -47,9 +47,12 @@ Options are:
 .Bl -tag -width keepenv
 .It Ic nopass
 The user is not required to enter a password.
-.It Ic persist
+.It Ic persist Ns Oo = Ns Ar time Oc
 After the user successfully authenticates, do not ask for a password
-again for some time.
+again for
+.Ar time
+seconds (5 minutes by default). There cannot be any whitespace on either side
+of the '=' sign.
 .It Ic keepenv
 The user's environment is maintained.
 The default is to reset the environment, except for the variables
Index: usr.bin/doas/doas.h
===================================================================
RCS file: /cvs/src/usr.bin/doas/doas.h,v
retrieving revision 1.12
diff -u -p -r1.12 doas.h
--- usr.bin/doas/doas.h 5 Oct 2016 17:40:25 -0000       1.12
+++ usr.bin/doas/doas.h 16 Mar 2017 15:52:18 -0000
@@ -18,6 +18,7 @@
 struct rule {
        int action;
        int options;
+       int persist;
        const char *ident;
        const char *target;
        const char *cmd;
Index: usr.bin/doas/parse.y
===================================================================
RCS file: /cvs/src/usr.bin/doas/parse.y,v
retrieving revision 1.26
diff -u -p -r1.26 parse.y
--- usr.bin/doas/parse.y        2 Jan 2017 01:40:20 -0000       1.26
+++ usr.bin/doas/parse.y        16 Mar 2017 15:52:18 -0000
@@ -20,9 +20,11 @@
 #include <ctype.h>
 #include <unistd.h>
 #include <stdint.h>
+#include <limits.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
+#include <errno.h>
 #include <err.h>
 
 #include "doas.h"
@@ -32,6 +34,7 @@ typedef struct {
                struct {
                        int action;
                        int options;
+                       int persist;
                        const char *cmd;
                        const char **cmdargs;
                        const char **envlist;
@@ -89,6 +92,7 @@ rule:         action ident target cmd {
                        r->action = $1.action;
                        r->options = $1.options;
                        r->envlist = $1.envlist;
+                       r->persist = $1.persist;
                        r->ident = $2.str;
                        r->target = $3.str;
                        r->cmd = $4.cmd;
@@ -109,6 +113,7 @@ action:             TPERMIT options {
                        $$.action = PERMIT;
                        $$.options = $2.options;
                        $$.envlist = $2.envlist;
+                       $$.persist = $2.persist;
                } | TDENY {
                        $$.action = DENY;
                        $$.options = 0;
@@ -121,6 +126,8 @@ options:    /* none */ {
                } | options option {
                        $$.options = $1.options | $2.options;
                        $$.envlist = $1.envlist;
+                       if($2.options & PERSIST)
+                               $$.persist = $2.persist;
                        if (($$.options & (NOPASS|PERSIST)) == 
(NOPASS|PERSIST)) {
                                yyerror("can't combine nopass and persist");
                                YYERROR;
@@ -139,6 +146,20 @@ option:            TNOPASS {
                } | TPERSIST {
                        $$.options = PERSIST;
                        $$.envlist = NULL;
+                       $$.persist = 300;
+                       if($1.str) {
+                               char *ep = NULL;
+                               errno = 0;
+                               long number = strtol($1.str, &ep, 10);
+                               if(*($1.str) == '\0' || *ep != '\0') {
+                                       yyerror("not a valid integer");
+                                       YYERROR;
+                               } else if(errno == ERANGE || number <= 0 || 
number > INT_MAX) {
+                                       yyerror("number out of range");
+                                       YYERROR;
+                               }
+                               $$.persist = number;
+                       }
                } | TKEEPENV {
                        $$.options = KEEPENV;
                        $$.envlist = NULL;
@@ -325,10 +346,20 @@ eow:
                        goto repeat;
        }
        if (!nonkw) {
+               char *eq = NULL;
+               if((eq = strchr(buf, '=')) != NULL)
+                       *eq = '\0';
                for (i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) {
-                       if (strcmp(buf, keywords[i].word) == 0)
+                       if (strcmp(buf, keywords[i].word) == 0) {
+                               str = NULL;
+                               if(eq && (str = strdup(eq + 1)) == NULL)
+                                       err(1, "strdup");
+                               yylval.str = str;
                                return keywords[i].token;
+                       }
                }
+               if(eq)
+                       *eq = '=';
        }
        if ((str = strdup(buf)) == NULL)
                err(1, "strdup");

Reply via email to