On 07/27/2015 01:21 PM, Marc Espie wrote:
On Mon, Jul 27, 2015 at 10:54:02AM +0300, Gregory Edigarov wrote:
Hi,

sudo was having a nice feature of not overwhelming the user with password
prompts (cookies :-) ).

This diff is adding this back to doas(1).

Index: doas.c
===================================================================
RCS file: /cvs/src/usr.bin/doas/doas.c,v
retrieving revision 1.27
diff -c -r1.27 doas.c
*** doas.c    26 Jul 2015 22:44:33 -0000    1.27
--- doas.c    27 Jul 2015 06:50:32 -0000
***************
*** 18,29 ****
--- 18,31 ----
   #include <sys/types.h>
   #include <sys/stat.h>

+ #include <fcntl.h>
   #include <limits.h>
   #include <login_cap.h>
   #include <bsd_auth.h>
   #include <string.h>
   #include <stdio.h>
   #include <stdlib.h>
+ #include <time.h>
   #include <err.h>
   #include <unistd.h>
   #include <pwd.h>
***************
*** 52,57 ****
--- 54,82 ----
       return cnt;
   }

+ int
+ checktimeout (const char *username)
+ {
+     char path[PATH_MAX];
+     struct stat stinfo;
+     time_t tv;
+     int fh;
+
+     snprintf((char *)&path,PATH_MAX-1,"/tmp/doas.timestamp.%s",username);
+     tv = time((time_t *)NULL);
+
+     if (!stat(path,(struct stat *)&stinfo) &&
(tv-stinfo.st_mtim.tv_sec)<pw_timeout)
+             return 1;
+     else {
+         fh = creat(path,S_IRUSR|S_IWUSR);
+         close(fh);
+         return 0;
+     }
+     return 0;
+ }
+
+
+
   static int
   parseuid(const char *s, uid_t *uid)
   {
***************
*** 399,405 ****
               "failed command for %s: %s", myname, cmdline);
           fail();
       }
!
       if (!(rule->options & NOPASS)) {
           if (nflag)
               errx(1, "Authorization required");
--- 424,430 ----
               "failed command for %s: %s", myname, cmdline);
           fail();
       }
!  if (pw_timeout && !checktimeout(pw->pw_name)) {
       if (!(rule->options & NOPASS)) {
           if (nflag)
               errx(1, "Authorization required");
***************
*** 409,414 ****
--- 434,440 ----
               fail();
           }
       }
+ }
       envp = copyenv((const char **)envp, rule);

       pw = getpwuid(target);
Index: doas.conf.5
===================================================================
RCS file: /cvs/src/usr.bin/doas/doas.conf.5,v
retrieving revision 1.11
diff -c -r1.11 doas.conf.5
*** doas.conf.5    23 Jul 2015 15:26:37 -0000    1.11
--- doas.conf.5    27 Jul 2015 06:50:32 -0000
***************
*** 22,31 ****
   .Sh DESCRIPTION
   The
   .Xr doas 1
! utility executes commands as other users according to the rules
   in the
   .Nm
   configuration file.
   .Pp
   The rules have the following format:
   .Bd -ragged -offset indent
--- 22,42 ----
   .Sh DESCRIPTION
   The
   .Xr doas 1
! utility executes commands as other users according to the rules and
options
   in the
   .Nm
   configuration file.
+ .Sh OPTIONS
+ .Pp
+ The configuration file currently accepts one option:
+ .Bd -ragged -offset indent
+ .Ic timeout
+ tsec
+ .Pp
+ By default
+ .Ic doas
+ prompts for password on every execution. This option sets timeout for
password reprompt to the tsec seconds value.
+ .Sh RULES
   .Pp
   The rules have the following format:
   .Bd -ragged -offset indent
***************
*** 113,118 ****
--- 124,132 ----
   .Bd -literal -offset indent
   # Non-exhaustive list of variables needed to
   # build release(8) and ports(7)
+ # timeout is optional
+ timeout 300 # sets the password reprompt time out to 5 minutes
+
   permit nopass keepenv { \e
           FTPMODE PKG_CACHE PKG_PATH SM_PATH SSH_AUTH_SOCK \e
           DESTDIR DISTDIR FETCH_CMD FLAVOR GROUP MAKE MAKECONF \e
Index: doas.h
===================================================================
RCS file: /cvs/src/usr.bin/doas/doas.h,v
retrieving revision 1.4
diff -c -r1.4 doas.h
*** doas.h    24 Jul 2015 06:36:42 -0000    1.4
--- doas.h    27 Jul 2015 06:50:32 -0000
***************
*** 10,15 ****
--- 10,16 ----
       const char **envlist;
   };

+ extern time_t pw_timeout;
   extern struct rule **rules;
   extern int nrules, maxrules;
   extern int parse_errors;
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.bin/doas/parse.y,v
retrieving revision 1.10
diff -c -r1.10 parse.y
*** parse.y    24 Jul 2015 06:36:42 -0000    1.10
--- parse.y    27 Jul 2015 06:50:32 -0000
***************
*** 17,22 ****
--- 17,23 ----

   %{
   #include <sys/types.h>
+ #include <sys/limits.h>
   #include <ctype.h>
   #include <unistd.h>
   #include <stdint.h>
***************
*** 24,29 ****
--- 25,31 ----
   #include <stdio.h>
   #include <string.h>
   #include <err.h>
+ #include <errno.h>

   #include "doas.h"

***************
*** 45,50 ****
--- 47,53 ----

   FILE *yyfp;

+ time_t pw_timeout;
   struct rule **rules;
   int nrules, maxrules;
   int parse_errors = 0;
***************
*** 56,62 ****
   %}

   %token TPERMIT TDENY TAS TCMD TARGS
! %token TNOPASS TKEEPENV
   %token TSTRING

   %%
--- 59,65 ----
   %}

   %token TPERMIT TDENY TAS TCMD TARGS
! %token TNOPASS TKEEPENV TTIMEOUT
   %token TSTRING

   %%
***************
*** 64,72 ****
--- 67,87 ----
   grammar:    /* empty */
           | grammar '\n'
           | grammar rule '\n'
+         | grammar timeout '\n'
           | error '\n'
           ;

+ timeout:    TTIMEOUT TSTRING {
+             errno = 0;
+             char *ep;
+             pw_timeout = strtol($2.str,&ep,10);
+             if ($2.str[0] == '\0' || *ep != '\0')
+                 errx (1, "timeout must be a number of seconds");
+             if (errno == ERANGE && pw_timeout == ULONG_MAX)
+                 errx (1, "timeout is out of range");
+             //printf ("Timeout is: %d\n",timeout);
+         };
+
   rule:        action ident target cmd {
               struct rule *r;
               r = calloc(1, sizeof(*r));
***************
*** 193,198 ****
--- 208,214 ----
       { "args", TARGS },
       { "nopass", TNOPASS },
       { "keepenv", TKEEPENV },
+     { "timeout", TTIMEOUT },
   };

   int
This patch is totally wrong in intent, as it expands the trust of doas to
other files in the filesystem.

It also features an obvious vulnerability... I'm sorry, but you don't know
what you're doing.

Hint: if I create the file
/tmp/doas.timestamp.edigarov
then I can come into your account if you have pw_timeout configured.
Thanks for showing that to me, Marc. Will think on how to implement that in a more secure way. I think I need to add a token based check? Correct?

Reply via email to