--- /dev/null
+bcallah=Brian Callahan <bcallah@devio.us>
+benno= <benno@openbsd.org>
+bentley= <bentley@openbsd.org>
+deraadt=Theo de Raadt <deraadt@openbsd.org>
+doug= <doug@openbsd.org>
+espie=Marc Espie <espie@openbsd.org>
+jmc=Jean-Marie Cannie <jmc@openbsd.org>
+nicm=Nicholas Marriott <nicm@openbsd.org>
+schwarze=Ingo Schwarze <schwarze@openbsd.org>
+tedu=Ted Unangst <tedu@openbsd.org>
+zhuk=Vadim Zhukov <zhuk@openbsd.org>
--- /dev/null
+doas
+
+*.a
+*.o
+
+*.swp
+*.swo
--- /dev/null
+portions copyright (c) 2015 Nathan Holstein
+portions copyright (c) 2015 Ted Unangst
+
+To the best of my knowledge, everything is released under the BSD license.
+
+Additional bits copyright of their respective authors, see individual
+files for details.
MAN= doas.1 doas.conf.5
BINOWN= root
-BINMODE=4555
+BINGRP= wheel
+BINMODE=4511
-CFLAGS+= -I${.CURDIR}
-COPTS+= -Wall
+CFLAGS+= -I${CURDIR}
+COPTS+= -Wall -Wextra -Werror -pedantic -std=c11
+LDFLAGS+= -lpam
-.include <bsd.prog.mk>
+include bsd.prog.mk
--- /dev/null
+# OpenDoas: a portable version of OpenBSD's `doas` command
+
+`doas` is a minimal replacement for the venerable `sudo`. It was
+initially [written by Ted Unangst](http://www.tedunangst.com/flak/post/doas)
+of the OpenBSD project to provide 95% of the features of `sudo` with a
+fraction of the codebase.
+
+This is still a work in progress! Please do not deploy yet in a critical
+environment! Of note, `doas` semantics may yet change, and I haven't
+completed PAM integration yet!
+
+## Building and installing
+
+Building `doas` should be just a simple `make` away.
+
+The included makefile also has an installation target. Installation
+requires root access to properly set the executable permissions. You'll
+also need to install a `doas.conf` file:
+
+```
+make && sudo make install
+echo "permit :admin" | sudo tee /etc/doas.conf
+```
+
+Oh the irony, using `sudo` to install `doas`!
+
+## About the port
+
+As much as possible I've attempted to stick to `doas` as tedu desired
+it. As things stand it's essentially just code lifted from OpenBSD with
+PAM based authentication glommed on to it.
+
+I've used cvsync and git-cvsimport to retain the history of the core
+source files. I may choose to go back and do the same with some of the
+compatibility functions (such as reallocarray.c).
+
+I have found it necessary to make some fixes to the codebase. One was
+a segfault due to differences in yacc/bison, others were just minor
+fixes to warnings. Once this appears stable, I may try to upstream some
+of these.
+
+Currently, this is only tested on MacOSX 10.10 with Clang. My next goal
+is support for Fedora Linux as well. Contributions gladly accepted. ;-)
+
+## Copyright
+
+All code from OpenBSD is licensed under the BSD license, please see
+individual files for details as the specific text varies from file to
+file.
+
+All code I've written is licensed with the 2-clause BSD.
--- /dev/null
+# Copyright 2015 Nathan Holstein
+
+BINDIR?=/usr/bin
+MANDIR?=/usr/share/man
+
+default: ${PROG}
+
+OPENBSD:=reallocarray.c strtonum.c execvpe.c setresuid.c \
+ auth_userokay.c setusercontext.c explicit_bzero.c
+OPENBSD:=$(addprefix libopenbsd/,${OPENBSD:.c=.o})
+libopenbsd.a: ${OPENBSD}
+ ${AR} -r $@ $?
+
+CFLAGS:=${CFLAGS} -I${CURDIR}/libopenbsd ${COPTS}
+
+OBJS:=${SRCS:.y=.c}
+OBJS:=${OBJS:.c=.o}
+
+${PROG}: ${OBJS} libopenbsd.a
+ ${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@
+
+.%.chmod: %
+ cp $< $@
+ chmod ${BINMODE} $@
+ chown ${BINOWN}:${BINGRP} $@
+
+${BINDIR}:
+ mkdir -pm 0755 $@
+
+${BINDIR}/${PROG}: .${PROG}.chmod ${BINDIR}
+ mv $< $@
+
+MAN:=$(join $(addprefix ${MANDIR}/man,$(patsubst .%,%/,$(suffix ${MAN}))),${MAN})
+$(foreach M,${MAN},$(eval $M: $(notdir $M); cp $$< $$@))
+
+install: ${BINDIR}/${PROG} ${MAN}
+
+clean:
+ rm -f libopenbsd.a
+ rm -f ${OPENBSD}
+ rm -f ${OBJS}
+ rm -f ${PROG}
+
+.PHONY: default clean install man
+.INTERMEDIATE: .${PROG}.chmod
#include <sys/stat.h>
#include <limits.h>
-#include <login_cap.h>
-#include <bsd_auth.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <errno.h>
+#include "openbsd.h"
+
#include "doas.h"
static void __dead
{
size_t cnt = 0;
- while (*arr) {
- cnt++;
- arr++;
+ if (arr) {
+ while (*arr) {
+ cnt++;
+ arr++;
+ }
}
return cnt;
}
yyfp = fopen(filename, "r");
if (!yyfp) {
- if (checkperms)
- fprintf(stderr, "doas is not enabled.\n");
- else
- warn("could not open config file");
+ warn("could not open config file");
exit(1);
}
* Copy the environment variables in safeset from oldenvp to envp.
*/
static int
-copyenvhelper(const char **oldenvp, const char **safeset, int nsafe,
+copyenvhelper(const char **oldenvp, const char **safeset, size_t nsafe,
char **envp, int ei)
{
- int i;
+ size_t i;
for (i = 0; i < nsafe; i++) {
const char **oe = oldenvp;
char **envp;
const char **extra;
int ei;
- int nsafe, nbad;
- int nextras = 0;
+ size_t nsafe, nbad;
+ size_t nextras = 0;
/* if there was no envvar whitelist, pass all except badset ones */
nbad = arraylen(badset);
--- /dev/null
+/*
+ * Copyright (c) 2015 Nathan Holstein <nathan.holstein@gmail.com>
+ *
+ * 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 <errno.h>
+#include <pwd.h>
+#include <readpassphrase.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <security/pam_appl.h>
+
+#include "openbsd.h"
+
+#define PAM_SERVICE "sudo"
+
+#define __UNUSED __attribute__ ((unused))
+
+static int
+pam_conv(__UNUSED int huh, __UNUSED const struct pam_message **msg,
+ __UNUSED struct pam_response **rsp, __UNUSED void *ptr)
+{
+ return 0;
+}
+
+static struct pam_conv conv = {
+ .conv = pam_conv,
+ .appdata_ptr = NULL,
+};
+
+static int
+check_pam(const char *user)
+{
+ fprintf(stderr, "check_pam(%s)\n", user);
+
+ int ret;
+ pam_handle_t *pamh = NULL;
+
+ ret = pam_start(PAM_SERVICE, user, &conv, &pamh);
+ if (ret != 0) {
+ fprintf(stderr, "pam_start(\"%s\", \"%s\", ?, ?): failed\n",
+ PAM_SERVICE, user);
+ return -1;
+ }
+
+ if ((ret = pam_close_session(pamh, 0)) != 0) {
+ fprintf(stderr, "pam_close_session(): %s\n", pam_strerror(pamh, ret));
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+auth_userokay(char *name, char *style, char *type, char *password)
+{
+ if (!name)
+ return 0;
+ if (style || type || password) {
+ fprintf(stderr, "auth_userokay(name, NULL, NULL, NULL)!\n");
+ exit(1);
+ }
+
+ int ret = check_pam(name);
+ if (ret != 0) {
+ fprintf(stderr, "PAM authentication failed\n");
+ return 0;
+ }
+
+ /*
+ char passbuf[256];
+ if (readpassphrase("Password: ", passbuf, sizeof(passbuf),
+ RPP_REQUIRE_TTY) == NULL)
+ return 0;
+
+ explicit_bzero(passbuf, sizeof(passbuf));
+ */
+
+ fprintf(stderr, "failing auth check for %s\n", name);
+ return 0;
+}
+
--- /dev/null
+/* $OpenBSD: exec.c,v 1.20 2013/01/08 02:26:09 deraadt Exp $ */
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int
+execvpe(const char *name, char *const *argv, char *const *envp)
+{
+ char **memp;
+ int cnt;
+ size_t lp, ln, len;
+ char *p;
+ int eacces = 0;
+ char *bp, *cur, *path, buf[PATH_MAX];
+
+ /*
+ * Do not allow null name
+ */
+ if (name == NULL || *name == '\0') {
+ errno = ENOENT;
+ return (-1);
+ }
+
+ /* If it's an absolute or relative path name, it's easy. */
+ if (strchr(name, '/')) {
+ bp = (char *)name;
+ cur = path = NULL;
+ goto retry;
+ }
+ bp = buf;
+
+ /* Get the path we're searching. */
+ if (!(path = getenv("PATH")))
+ path = _PATH_DEFPATH;
+ len = strlen(path) + 1;
+ cur = alloca(len);
+ if (cur == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ strlcpy(cur, path, len);
+ path = cur;
+ while ((p = strsep(&cur, ":"))) {
+ /*
+ * It's a SHELL path -- double, leading and trailing colons
+ * mean the current directory.
+ */
+ if (!*p) {
+ p = ".";
+ lp = 1;
+ } else
+ lp = strlen(p);
+ ln = strlen(name);
+
+ /*
+ * If the path is too long complain. This is a possible
+ * security issue; given a way to make the path too long
+ * the user may execute the wrong program.
+ */
+ if (lp + ln + 2 > sizeof(buf)) {
+ struct iovec iov[3];
+
+ iov[0].iov_base = "execvp: ";
+ iov[0].iov_len = 8;
+ iov[1].iov_base = p;
+ iov[1].iov_len = lp;
+ iov[2].iov_base = ": path too long\n";
+ iov[2].iov_len = 16;
+ (void)writev(STDERR_FILENO, iov, 3);
+ continue;
+ }
+ bcopy(p, buf, lp);
+ buf[lp] = '/';
+ bcopy(name, buf + lp + 1, ln);
+ buf[lp + ln + 1] = '\0';
+
+retry: (void)execve(bp, argv, envp);
+ switch(errno) {
+ case E2BIG:
+ goto done;
+ case EISDIR:
+ case ELOOP:
+ case ENAMETOOLONG:
+ case ENOENT:
+ break;
+ case ENOEXEC:
+ for (cnt = 0; argv[cnt]; ++cnt)
+ ;
+ memp = alloca((cnt + 2) * sizeof(char *));
+ if (memp == NULL)
+ goto done;
+ memp[0] = "sh";
+ memp[1] = bp;
+ bcopy(argv + 1, memp + 2, cnt * sizeof(char *));
+ (void)execve(_PATH_BSHELL, memp, envp);
+ goto done;
+ case ENOMEM:
+ goto done;
+ case ENOTDIR:
+ break;
+ case ETXTBSY:
+ /*
+ * We used to retry here, but sh(1) doesn't.
+ */
+ goto done;
+ case EACCES:
+ eacces = 1;
+ break;
+ default:
+ goto done;
+ }
+ }
+ if (eacces)
+ errno = EACCES;
+ else if (!errno)
+ errno = ENOENT;
+done:
+ return (-1);
+}
--- /dev/null
+/* $OpenBSD: explicit_bzero.c,v 1.2 2014/06/10 04:17:37 deraadt Exp $ */
+/*
+ * Public domain.
+ * Written by Matthew Dempsky.
+ */
+
+#include <string.h>
+
+#define __UNUSED __attribute__ ((unused))
+
+__attribute__((weak)) void
+__explicit_bzero_hook(__UNUSED void *buf, __UNUSED size_t len)
+{
+}
+
+void
+explicit_bzero(void *buf, size_t len)
+{
+ memset(buf, 0, len);
+ __explicit_bzero_hook(buf, len);
+}
--- /dev/null
+#ifndef _LIB_OPENBSD_H_
+#define _LIB_OPENBSD_H_
+
+#include <sys/types.h>
+
+/* API definitions lifted from OpenBSD src/include */
+
+/* bsd_auth.h */
+int auth_userokay(char *, char *, char *, char *);
+
+/* login_cap.h */
+#define LOGIN_SETGROUP 0x0001 /* Set group */
+#define LOGIN_SETLOGIN 0x0002 /* Set login */
+#define LOGIN_SETPATH 0x0004 /* Set path */
+#define LOGIN_SETPRIORITY 0x0008 /* Set priority */
+#define LOGIN_SETRESOURCES 0x0010 /* Set resource limits */
+#define LOGIN_SETUMASK 0x0020 /* Set umask */
+#define LOGIN_SETUSER 0x0040 /* Set user */
+#define LOGIN_SETENV 0x0080 /* Set environment */
+#define LOGIN_SETALL 0x00ff /* Set all. */
+
+typedef struct login_cap login_cap_t;
+struct passwd;
+int setusercontext(login_cap_t *, struct passwd *, uid_t, unsigned int);
+
+/* pwd.h */
+#define _PW_NAME_LEN 63
+
+/* stdlib.h */
+void * reallocarray(void *optr, size_t nmemb, size_t size);
+long long strtonum(const char *numstr, long long minval,
+ long long maxval, const char **errstrp);
+
+/* string.h */
+void explicit_bzero(void *, size_t);
+
+/* unistd.h */
+int execvpe(const char *, char *const *, char *const *);
+int setresuid(uid_t, uid_t, uid_t);
+
+#endif
--- /dev/null
+/* $OpenBSD: reallocarray.c,v 1.1 2014/05/08 21:43:49 deraadt Exp $ */
+/*
+ * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
+ *
+ * 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 <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/*
+ * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+ * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+ */
+#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
+
+void *
+reallocarray(void *optr, size_t nmemb, size_t size)
+{
+ if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+ nmemb > 0 && SIZE_MAX / nmemb < size) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ return realloc(optr, size * nmemb);
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Nathan Holstein <nathan.holstein@gmail.com>
+ *
+ * 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 <errno.h>
+#include <unistd.h>
+
+/* I don't think we can actually mimic the right semantics? */
+int
+setresuid(uid_t ruid, uid_t euid, uid_t suid)
+{
+ int ret;
+ if (suid != ruid) {
+ errno = EPERM;
+ return -1;
+ }
+ if ((ret = setuid(ruid)) != 0)
+ return ret;
+ if ((ret = seteuid(euid)) != 0)
+ return ret;
+ return 0;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 Nathan Holstein <nathan.holstein@gmail.com>
+ *
+ * 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/resource.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "openbsd.h"
+
+int
+setusercontext(login_cap_t *lc, struct passwd *pw, uid_t uid, unsigned int flags)
+{
+ int ret;
+
+ if (lc != NULL || pw == NULL ||
+ (flags & ~(LOGIN_SETGROUP | LOGIN_SETPRIORITY |
+ LOGIN_SETRESOURCES | LOGIN_SETUMASK |
+ LOGIN_SETUSER)) != 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (flags & LOGIN_SETGROUP) {
+ if ((ret = setgid(pw->pw_gid)) != 0)
+ return ret;
+ if ((ret = initgroups(pw->pw_name, pw->pw_gid)) != 0)
+ return ret;
+ }
+
+ if (flags & LOGIN_SETPRIORITY) {
+ if ((ret = setpriority(PRIO_PROCESS, getpid(), 0)) != 0)
+ return ret;
+ if ((ret = setpriority(PRIO_USER, uid, 0)) != 0)
+ return ret;
+ }
+
+ if (flags & LOGIN_SETRESOURCES) {
+ }
+
+ if (flags & LOGIN_SETUMASK)
+ umask(S_IWGRP | S_IWOTH);
+
+ if (flags & LOGIN_SETUSER)
+ return setuid(uid);
+
+ return 0;
+}
+
--- /dev/null
+/* $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $ */
+
+/*
+ * Copyright (c) 2004 Ted Unangst and Todd Miller
+ * All rights reserved.
+ *
+ * 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 <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#define INVALID 1
+#define TOOSMALL 2
+#define TOOLARGE 3
+
+long long
+strtonum(const char *numstr, long long minval, long long maxval,
+ const char **errstrp)
+{
+ long long ll = 0;
+ int error = 0;
+ char *ep;
+ struct errval {
+ const char *errstr;
+ int err;
+ } ev[4] = {
+ { NULL, 0 },
+ { "invalid", EINVAL },
+ { "too small", ERANGE },
+ { "too large", ERANGE },
+ };
+
+ ev[0].err = errno;
+ errno = 0;
+ if (minval > maxval) {
+ error = INVALID;
+ } else {
+ ll = strtoll(numstr, &ep, 10);
+ if (numstr == ep || *ep != '\0')
+ error = INVALID;
+ else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
+ error = TOOSMALL;
+ else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
+ error = TOOLARGE;
+ }
+ if (errstrp != NULL)
+ *errstrp = ev[error].errstr;
+ errno = ev[error].err;
+ if (error)
+ ll = 0;
+
+ return (ll);
+}
%{
#include <sys/types.h>
#include <ctype.h>
-#include <unistd.h>
-#include <stdint.h>
+#include <err.h>
#include <stdarg.h>
#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
#include <string.h>
-#include <err.h>
+#include <unistd.h>
+
+#include "openbsd.h"
#include "doas.h"
$$.action = DENY;
} ;
-options: /* none */
- | options option {
+options: /* none */ {
+ $$.options = 0;
+ $$.envlist = NULL;
+ } | options option {
$$.options = $1.options | $2.options;
$$.envlist = $1.envlist;
if ($2.envlist) {
} ;
option: TNOPASS {
$$.options = NOPASS;
+ $$.envlist = NULL;
} | TKEEPENV {
$$.options = KEEPENV;
+ $$.envlist = NULL;
} | TKEEPENV '{' envlist '}' {
$$.options = KEEPENV;
$$.envlist = $3.envlist;
} ;
envlist: /* empty */ {
- if (!($$.envlist = calloc(1, sizeof(char *))))
- errx(1, "can't allocate envlist");
+ $$.envlist = NULL;
} | envlist TSTRING {
int nenv = arraylen($1.envlist);
if (!($$.envlist = reallocarray($1.envlist, nenv + 2,
} ;
argslist: /* empty */ {
- if (!($$.cmdargs = calloc(1, sizeof(char *))))
- errx(1, "can't allocate args");
+ $$.cmdargs = NULL;
} | argslist TSTRING {
int nargs = arraylen($1.cmdargs);
if (!($$.cmdargs = reallocarray($1.cmdargs, nargs + 2,
yylex(void)
{
char buf[1024], *ebuf, *p, *str;
- int i, c, quotes = 0, escape = 0, qpos = -1, nonkw = 0;
+ int c, quotes = 0, escape = 0, qpos = -1, nonkw = 0;
p = buf;
ebuf = buf + sizeof(buf);
goto repeat;
}
if (!nonkw) {
+ size_t i;
for (i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) {
if (strcmp(buf, keywords[i].word) == 0)
return keywords[i].token;