]> git.armaanb.net Git - opendoas.git/commitdiff
Add argument matching support to doas.
authorVadim Zhukov <zhuk@openbsd.org>
Tue, 21 Jul 2015 11:04:06 +0000 (11:04 +0000)
committerVadim Zhukov <zhuk@openbsd.org>
Tue, 21 Jul 2015 11:04:06 +0000 (11:04 +0000)
Input and generic support from many. Final okay from tedu@.

doas.1
doas.c
doas.conf.5
doas.h
parse.y

diff --git a/doas.1 b/doas.1
index cd076ea0205ce31d03e12a15264c2938f0990843..351d5fd82462f333ab4fc6930a26bb8fbfaf1d6e 100644 (file)
--- a/doas.1
+++ b/doas.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: doas.1,v 1.6 2015/07/19 16:42:31 espie Exp $
+.\" $OpenBSD: doas.1,v 1.7 2015/07/19 17:00:22 jmc Exp $
 .\"
 .\"Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
 .\"
 .\"
 .\"Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
 .\"
@@ -55,6 +55,8 @@ could not be parsed.
 The user attempted to run a command which is not permitted.
 .It
 The password was incorrect.
 The user attempted to run a command which is not permitted.
 .It
 The password was incorrect.
+.It
+The actual program is absent or not executable.
 .El
 .Sh SEE ALSO
 .Xr doas.conf 5
 .El
 .Sh SEE ALSO
 .Xr doas.conf 5
diff --git a/doas.c b/doas.c
index a712bc3799970a2f6096d82ac16ed9ef1c3fd1ec..b77e17f6953eb88faa8bd69f95f5ac8fc7a3f35d 100644 (file)
--- a/doas.c
+++ b/doas.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: doas.c,v 1.13 2015/07/20 01:00:48 tedu Exp $ */
+/* $OpenBSD: doas.c,v 1.14 2015/07/20 01:04:37 tedu Exp $ */
 /*
  * Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
  *
 /*
  * Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
  *
@@ -97,7 +97,7 @@ strtogid(const char *s)
 
 static int
 match(uid_t uid, gid_t *groups, int ngroups, uid_t target, const char *cmd,
 
 static int
 match(uid_t uid, gid_t *groups, int ngroups, uid_t target, const char *cmd,
-    struct rule *r)
+    const char **cmdargs, struct rule *r)
 {
        int i;
 
 {
        int i;
 
@@ -117,20 +117,33 @@ match(uid_t uid, gid_t *groups, int ngroups, uid_t target, const char *cmd,
        }
        if (r->target && uidcheck(r->target, target) != 0)
                return 0;
        }
        if (r->target && uidcheck(r->target, target) != 0)
                return 0;
-       if (r->cmd && strcmp(r->cmd, cmd) != 0)
-               return 0;
+       if (r->cmd) {
+               if (strcmp(r->cmd, cmd))
+                       return 0;
+               if (r->cmdargs) {
+                       /* if arguments were given, they should match explicitly */
+                       for (i = 0; r->cmdargs[i]; i++) {
+                               if (!cmdargs[i])
+                                       return 0;
+                               if (strcmp(r->cmdargs[i], cmdargs[i]))
+                                       return 0;
+                       }
+                       if (cmdargs[i])
+                               return 0;
+               }
+       }
        return 1;
 }
 
 static int
 permit(uid_t uid, gid_t *groups, int ngroups, struct rule **lastr,
        return 1;
 }
 
 static int
 permit(uid_t uid, gid_t *groups, int ngroups, struct rule **lastr,
-    uid_t target, const char *cmd)
+    uid_t target, const char *cmd, const char **cmdargs)
 {
        int i;
 
        *lastr = NULL;
        for (i = 0; i < nrules; i++) {
 {
        int i;
 
        *lastr = NULL;
        for (i = 0; i < nrules; i++) {
-               if (match(uid, groups, ngroups, target, cmd, rules[i]))
+               if (match(uid, groups, ngroups, target, cmd, cmdargs, rules[i]))
                        *lastr = rules[i];
        }
        if (!*lastr)
                        *lastr = rules[i];
        }
        if (!*lastr)
@@ -334,7 +347,8 @@ main(int argc, char **argv, char **envp)
                        errx(1, "command line too long");
        }
 
                        errx(1, "command line too long");
        }
 
-       if (!permit(uid, groups, ngroups, &rule, target, cmd)) {
+       if (!permit(uid, groups, ngroups, &rule, target, cmd,
+           (const char**)argv + 1)) {
                syslog(LOG_AUTHPRIV | LOG_NOTICE,
                    "failed command for %s: %s", myname, cmdline);
                fail();
                syslog(LOG_AUTHPRIV | LOG_NOTICE,
                    "failed command for %s: %s", myname, cmdline);
                fail();
index 8d3cd1eb109f0e48c9cf1197016b6c14c4429bfa..7510bd0b4ac0219f36d7e766307e9b9a29b337ea 100644 (file)
@@ -1,4 +1,4 @@
-.\" $OpenBSD: doas.conf.5,v 1.6 2015/07/20 07:43:27 jmc Exp $
+.\" $OpenBSD: doas.conf.5,v 1.7 2015/07/20 20:18:45 tedu Exp $
 .\"
 .\"Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
 .\"
 .\"
 .\"Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
 .\"
@@ -33,7 +33,9 @@ The rules have the following format:
 .Op Ar options
 .Ar identity
 .Op Ic as Ar target
 .Op Ar options
 .Ar identity
 .Op Ic as Ar target
-.Op Ic cmd Ar command
+.Oo
+.Ic cmd Ar command Op Ic args ...
+.Oc
 .Ed
 .Pp
 Rules consist of the following parts:
 .Ed
 .Pp
 Rules consist of the following parts:
@@ -71,6 +73,14 @@ The default is root.
 The command the user is allowed or denied to run.
 The default is all commands.
 Be advised that it's best to specify absolute paths.
 The command the user is allowed or denied to run.
 The default is all commands.
 Be advised that it's best to specify absolute paths.
+.It Ic args Op ...
+Arguments to command.
+If specified, the command arguments set provided by user and
+the command arguments set in rule should be the same for successful
+rule match.
+Specifying
+.Ic args
+alone means that command should be run without any arguments.
 .El
 .Pp
 The last matching rule determines the action taken.
 .El
 .Pp
 The last matching rule determines the action taken.
diff --git a/doas.h b/doas.h
index 8576e41668787a6faa3fac5fd7614663cd7f385a..9f0e5e491a43165e091222cdd3ab76edaade9e0e 100644 (file)
--- a/doas.h
+++ b/doas.h
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $OpenBSD: doas.h,v 1.2 2015/07/18 07:49:16 bcallah Exp $ */
 
 struct rule {
        int action;
 
 struct rule {
        int action;
@@ -6,6 +6,7 @@ struct rule {
        const char *ident;
        const char *target;
        const char *cmd;
        const char *ident;
        const char *target;
        const char *cmd;
+       const char **cmdargs;
        const char **envlist;
 };
 
        const char **envlist;
 };
 
diff --git a/parse.y b/parse.y
index f1e90ab9039fc555fd05e4a0acf6890d922888fd..7dc18161183081a8091067f927f3b37baf66ec83 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.5 2015/07/19 22:09:08 benno Exp $ */
+/* $OpenBSD: parse.y,v 1.6 2015/07/19 22:11:41 benno Exp $ */
 /*
  * Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
  *
 /*
  * Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
  *
@@ -32,6 +32,8 @@ typedef struct {
                struct {
                        int action;
                        int options;
                struct {
                        int action;
                        int options;
+                       const char *cmd;
+                       const char **cmdargs;
                        const char **envlist;
                };
                const char *str;
                        const char **envlist;
                };
                const char *str;
@@ -50,7 +52,7 @@ int yyparse(void);
 
 %}
 
 
 %}
 
-%token TPERMIT TDENY TAS TCMD
+%token TPERMIT TDENY TAS TCMD TARGS
 %token TNOPASS TKEEPENV
 %token TSTRING
 
 %token TNOPASS TKEEPENV
 %token TSTRING
 
@@ -71,7 +73,8 @@ rule:         action ident target cmd {
                        r->envlist = $1.envlist;
                        r->ident = $2.str;
                        r->target = $3.str;
                        r->envlist = $1.envlist;
                        r->ident = $2.str;
                        r->target = $3.str;
-                       r->cmd = $4.str;
+                       r->cmd = $4.cmd;
+                       r->cmdargs = $4.cmdargs;
                        if (nrules == maxrules) {
                                if (maxrules == 0)
                                        maxrules = 63;
                        if (nrules == maxrules) {
                                if (maxrules == 0)
                                        maxrules = 63;
@@ -136,9 +139,28 @@ target:            /* optional */ {
                } ;
 
 cmd:           /* optional */ {
                } ;
 
 cmd:           /* optional */ {
-                       $$.str = NULL;
-               } | TCMD TSTRING {
-                       $$.str = $2.str;
+                       $$.cmd = NULL;
+                       $$.cmdargs = NULL;
+               } | TCMD TSTRING args {
+                       $$.cmd = $2.str;
+                       $$.cmdargs = $3.cmdargs;
+               } ;
+
+args:          /* empty */ {
+                       $$.cmdargs = NULL;
+               } | TARGS argslist {
+                       $$.cmdargs = $2.cmdargs;
+               } ;
+
+argslist:      /* empty */ {
+                       if (!($$.cmdargs = calloc(1, sizeof(char *))))
+                               errx(1, "can't allocate args");
+               } | argslist TSTRING {
+                       int nargs = arraylen($1.cmdargs);
+                       if (!($$.cmdargs = reallocarray($1.cmdargs, nargs + 2, sizeof(char *))))
+                               errx(1, "can't allocate args");
+                       $$.cmdargs[nargs] = $2.str;
+                       $$.cmdargs[nargs + 1] = NULL;
                } ;
 
 %%
                } ;
 
 %%
@@ -160,6 +182,7 @@ struct keyword {
        { "permit", TPERMIT },
        { "as", TAS },
        { "cmd", TCMD },
        { "permit", TPERMIT },
        { "as", TAS },
        { "cmd", TCMD },
+       { "args", TARGS },
        { "nopass", TNOPASS },
        { "keepenv", TKEEPENV },
 };
        { "nopass", TNOPASS },
        { "keepenv", TKEEPENV },
 };