aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Zhukov <zhuk@openbsd.org>2015-07-21 11:04:06 +0000
committerVadim Zhukov <zhuk@openbsd.org>2015-07-21 11:04:06 +0000
commite355b1d04349731687a4eb6222a91d9b2dcf7e6f (patch)
treec0086e431190e603df35bb183557859e338ff849
parentcdc72f2f64334711d9cddf6855081addd5328627 (diff)
downloadopendoas-e355b1d04349731687a4eb6222a91d9b2dcf7e6f.tar.gz
Add argument matching support to doas.
Input and generic support from many. Final okay from tedu@.
-rw-r--r--doas.14
-rw-r--r--doas.c28
-rw-r--r--doas.conf.514
-rw-r--r--doas.h3
-rw-r--r--parse.y35
5 files changed, 67 insertions, 17 deletions
diff --git a/doas.1 b/doas.1
index cd076ea..351d5fd 100644
--- 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>
.\"
@@ -55,6 +55,8 @@ could not be parsed.
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
diff --git a/doas.c b/doas.c
index a712bc3..b77e17f 100644
--- 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>
*
@@ -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,
- struct rule *r)
+ const char **cmdargs, struct rule *r)
{
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->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,
- 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++) {
- if (match(uid, groups, ngroups, target, cmd, rules[i]))
+ if (match(uid, groups, ngroups, target, cmd, cmdargs, rules[i]))
*lastr = rules[i];
}
if (!*lastr)
@@ -334,7 +347,8 @@ main(int argc, char **argv, char **envp)
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();
diff --git a/doas.conf.5 b/doas.conf.5
index 8d3cd1e..7510bd0 100644
--- a/doas.conf.5
+++ b/doas.conf.5
@@ -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>
.\"
@@ -33,7 +33,9 @@ The rules have the following format:
.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:
@@ -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.
+.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.
diff --git a/doas.h b/doas.h
index 8576e41..9f0e5e4 100644
--- 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;
@@ -6,6 +6,7 @@ struct rule {
const char *ident;
const char *target;
const char *cmd;
+ const char **cmdargs;
const char **envlist;
};
diff --git a/parse.y b/parse.y
index f1e90ab..7dc1816 100644
--- 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>
*
@@ -32,6 +32,8 @@ typedef struct {
struct {
int action;
int options;
+ const char *cmd;
+ const char **cmdargs;
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
@@ -71,7 +73,8 @@ rule: action ident target cmd {
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;
@@ -136,9 +139,28 @@ target: /* 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 },
+ { "args", TARGS },
{ "nopass", TNOPASS },
{ "keepenv", TKEEPENV },
};