-# $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 \
--- /dev/null
+/* $OpenBSD: doas.c,v 1.1 2016/08/16 04:55:33 tedu Exp $ */
+/*
+ * Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <err.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <syslog.h>
+#include <errno.h>
+
+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);
+}