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.

Reply via email to