From ca42b2f9e36363082234bb5dedb77e8159af94dd Mon Sep 17 00:00:00 2001 From: tedu Date: Tue, 16 Aug 2016 04:55:33 +0000 Subject: [PATCH] add a special edition doas that only lets root drop privs. maybe the installer can use something like this, wink wink. ok deraadt --- distrib/special/Makefile | 4 +- distrib/special/doas/Makefile | 6 ++ distrib/special/doas/doas.c | 107 ++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 distrib/special/doas/Makefile create mode 100644 distrib/special/doas/doas.c diff --git a/distrib/special/Makefile b/distrib/special/Makefile index 71c61a285ee..b87f067d73a 100644 --- a/distrib/special/Makefile +++ b/distrib/special/Makefile @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile,v 1.39 2015/04/13 21:27:07 deraadt Exp $ +# $OpenBSD: Makefile,v 1.40 2016/08/16 04:55:33 tedu Exp $ SUBDIR= libstubs \ arch bioctl cat chmod chroot cp date dd df dhclient disklabel dmesg \ - ed eeprom encrypt fdisk fsck fsck_ext2fs fsck_ffs fsck_msdos ftp \ + doas ed eeprom encrypt fdisk fsck fsck_ext2fs fsck_ffs fsck_msdos ftp \ grep gzip hostname ifconfig init installboot kbd ksh ln ls md5 \ mkdir mknod mkuboot more mount mount_cd9660 mount_ext2fs \ mount_ffs mount_msdos mount_nfs mount_udf mt mv newfs newfs_ext2fs \ diff --git a/distrib/special/doas/Makefile b/distrib/special/doas/Makefile new file mode 100644 index 00000000000..ae95c24ed68 --- /dev/null +++ b/distrib/special/doas/Makefile @@ -0,0 +1,6 @@ +# $OpenBSD: Makefile,v 1.1 2016/08/16 04:55:33 tedu Exp $ + +PROG= doas +SRCS= doas.c + +.include diff --git a/distrib/special/doas/doas.c b/distrib/special/doas/doas.c new file mode 100644 index 00000000000..42c4d80bbd0 --- /dev/null +++ b/distrib/special/doas/doas.c @@ -0,0 +1,107 @@ +/* $OpenBSD: doas.c,v 1.1 2016/08/16 04:55:33 tedu Exp $ */ +/* + * Copyright (c) 2015 Ted Unangst + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * 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. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void __dead +usage(void) +{ + fprintf(stderr, "usage: doas [-u user] command [args]\n"); + exit(1); +} + +static int +parseuid(const char *s, uid_t *uid) +{ + struct passwd *pw; + const char *errstr; + + if ((pw = getpwnam(s)) != NULL) { + *uid = pw->pw_uid; + return 0; + } + *uid = strtonum(s, 0, UID_MAX, &errstr); + if (errstr) + return -1; + return 0; +} + +int +main(int argc, char **argv) +{ + const char *cmd; + struct passwd *pw; + uid_t uid; + uid_t target = 0; + gid_t groups[1]; + int ngroups; + int i, ch; + + setprogname("doas"); + + closefrom(STDERR_FILENO + 1); + + uid = getuid(); + if (uid != 0) + errc(1, EPERM, "root only"); + + while ((ch = getopt(argc, argv, "u:")) != -1) { + switch (ch) { + case 'u': + if (parseuid(optarg, &target) != 0) + errx(1, "unknown user"); + break; + default: + usage(); + break; + } + } + argv += optind; + argc -= optind; + + if (!argc) + usage(); + + cmd = argv[0]; + + pw = getpwuid(target); + if (!pw) + errx(1, "no passwd entry for target"); + groups[0] = pw->pw_gid; + + if (setgroups(1, groups) || + setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || + setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) + err(1, "failed to change user"); + + execvp(cmd, argv); + if (errno == ENOENT) + errx(1, "%s: command not found", cmd); + err(1, "%s", cmd); +} -- 2.20.1