summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Zhukov <zhuk@cvs.openbsd.org>2015-07-26 17:24:03 +0000
committerVadim Zhukov <zhuk@cvs.openbsd.org>2015-07-26 17:24:03 +0000
commit728ba6a9c3cd408643c1f8bcb7a151d19918c39b (patch)
treedb4d920e0cdaba4d3497a8047211e30091e77c73
parent2afeceaa3106553d69805e23bd0a64225235b2b7 (diff)
Implement command matching without execution. This just extends
functionality of the -C flag, so we are not introducing more garbage. Input and okay from jmc@ (documentation) and tedu@ (everything).
-rw-r--r--usr.bin/doas/doas.124
-rw-r--r--usr.bin/doas/doas.c63
2 files changed, 69 insertions, 18 deletions
diff --git a/usr.bin/doas/doas.1 b/usr.bin/doas/doas.1
index 673fd4daaa2..90f71b853ab 100644
--- a/usr.bin/doas/doas.1
+++ b/usr.bin/doas/doas.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: doas.1,v 1.10 2015/07/21 17:49:33 jmc Exp $
+.\" $OpenBSD: doas.1,v 1.11 2015/07/26 17:24:02 zhuk Exp $
.\"
.\"Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
.\"
@@ -13,7 +13,7 @@
.\"WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\"ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\"OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.Dd $Mdocdate: July 21 2015 $
+.Dd $Mdocdate: July 26 2015 $
.Dt DOAS 1
.Os
.Sh NAME
@@ -30,6 +30,13 @@
The
.Nm
utility executes the given command as another user.
+The
+.Ar command
+argument is mandatory unless
+.Fl C
+or
+.Fl s
+is specified.
.Pp
The options are as follows:
.Bl -tag -width tenletters
@@ -37,6 +44,19 @@ The options are as follows:
Parse and check the configuration file
.Ar config ,
then exit.
+If
+.Ar command
+is supplied,
+.Nm
+will also perform command matching.
+In the latter case
+either
+.Sq permit ,
+.Sq permit nopass
+or
+.Sq deny
+will be printed on standard output, depending on command
+matching results.
No command is executed.
.It Fl s
Execute the shell from
diff --git a/usr.bin/doas/doas.c b/usr.bin/doas/doas.c
index f34e3da8b97..d06012a01f7 100644
--- a/usr.bin/doas/doas.c
+++ b/usr.bin/doas/doas.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: doas.c,v 1.21 2015/07/24 06:36:42 zhuk Exp $ */
+/* $OpenBSD: doas.c,v 1.22 2015/07/26 17:24:02 zhuk Exp $ */
/*
* Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
*
@@ -152,7 +152,7 @@ permit(uid_t uid, gid_t *groups, int ngroups, struct rule **lastr,
}
static void
-parseconfig(const char *filename)
+parseconfig(const char *filename, int checkperms)
{
extern FILE *yyfp;
extern int yyparse(void);
@@ -160,16 +160,21 @@ parseconfig(const char *filename)
yyfp = fopen(filename, "r");
if (!yyfp) {
- fprintf(stderr, "doas is not enabled.\n");
+ if (checkperms)
+ fprintf(stderr, "doas is not enabled.\n");
+ else
+ warn("could not open config file");
exit(1);
}
- if (fstat(fileno(yyfp), &sb) != 0)
- err(1, "fstat(\"%s\")", filename);
- if ((sb.st_mode & (S_IWGRP|S_IWOTH)) != 0)
- errx(1, "%s is writable by group or other", filename);
- if (sb.st_uid != 0)
- errx(1, "%s is not owned by root", filename);
+ if (checkperms) {
+ if (fstat(fileno(yyfp), &sb) != 0)
+ err(1, "fstat(\"%s\")", filename);
+ if ((sb.st_mode & (S_IWGRP|S_IWOTH)) != 0)
+ errx(1, "%s is writable by group or other", filename);
+ if (sb.st_uid != 0)
+ errx(1, "%s is not owned by root", filename);
+ }
yyparse();
fclose(yyfp);
@@ -277,11 +282,32 @@ fail(void)
exit(1);
}
+static int
+checkconfig(const char *confpath, int argc, char **argv,
+ uid_t uid, gid_t *groups, int ngroups, uid_t target) {
+ struct rule *rule;
+
+ setresuid(uid, uid, uid);
+ parseconfig(confpath, 0);
+ if (!argc)
+ exit(0);
+
+ if (permit(uid, groups, ngroups, &rule, target, argv[0],
+ (const char **)argv + 1)) {
+ printf("permit%s\n", (rule->options & NOPASS) ? " nopass" : "");
+ return 1;
+ } else {
+ printf("deny\n");
+ return 0;
+ }
+}
+
int
main(int argc, char **argv, char **envp)
{
const char *safepath = "/bin:/sbin:/usr/bin:/usr/sbin:"
"/usr/local/bin:/usr/local/sbin";
+ const char *confpath = NULL;
char *shargv[] = { NULL, NULL };
char *sh;
const char *cmd;
@@ -296,13 +322,11 @@ main(int argc, char **argv, char **envp)
int i, ch;
int sflag = 0;
- uid = getuid();
while ((ch = getopt(argc, argv, "C:su:")) != -1) {
switch (ch) {
case 'C':
- setresuid(uid, uid, uid);
- parseconfig(optarg);
- exit(0);
+ confpath = optarg;
+ break;
case 'u':
if (parseuid(optarg, &target) != 0)
errx(1, "unknown user");
@@ -318,11 +342,13 @@ main(int argc, char **argv, char **envp)
argv += optind;
argc -= optind;
- if ((!sflag && !argc) || (sflag && argc))
+ if (confpath) {
+ if (sflag)
+ usage();
+ } else if ((!sflag && !argc) || (sflag && argc))
usage();
- parseconfig("/etc/doas.conf");
-
+ uid = getuid();
pw = getpwuid(uid);
if (!pw)
err(1, "getpwuid failed");
@@ -343,6 +369,11 @@ main(int argc, char **argv, char **envp)
argc = 1;
}
+ if (confpath)
+ exit(!checkconfig(confpath, argc, argv, uid, groups, ngroups,
+ target));
+ parseconfig("/etc/doas.conf", 1);
+
cmd = argv[0];
if (strlcpy(cmdline, argv[0], sizeof(cmdline)) >= sizeof(cmdline))
errx(1, "command line too long");