aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Holstein <nathan.holstein@gmail.com>2015-08-02 13:30:58 -0400
committerNathan Holstein <nathan.holstein@gmail.com>2015-08-05 08:50:46 -0400
commit4272fe4a9344245a61a55fb8d4091f459c235dcc (patch)
tree11260ecf9c90ff0ac674a1f236d2852afccfeedb
parentad270e2f81fedbcef80cecb8be155953bdf5123d (diff)
downloadopendoas-4272fe4a9344245a61a55fb8d4091f459c235dcc.tar.gz
Add compatibility functions from OpenBSD.
This adds a shim library to mimic features of OpenBSD. Some of these functions are written from scratch, others are simply copies of their OpenBSD namesakes. Current implementation of the from-scratch variants are simply shims that intentionally fail. They'll need to be extended with secure implementations.
-rw-r--r--.gitignore1
-rw-r--r--Makefile12
-rw-r--r--libopenbsd/auth_userokay.c21
-rw-r--r--libopenbsd/execvpe.c156
-rw-r--r--libopenbsd/openbsd.h2
-rw-r--r--libopenbsd/reallocarray.c38
-rw-r--r--libopenbsd/setresuid.c22
-rw-r--r--libopenbsd/setusercontext.c24
-rw-r--r--libopenbsd/strtonum.c65
9 files changed, 339 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index 970069b..6fd68eb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
doas
+*.a
*.o
*.swp
diff --git a/Makefile b/Makefile
index 7bb667e..167d8dd 100644
--- a/Makefile
+++ b/Makefile
@@ -17,11 +17,17 @@ MANDIR?=/usr/share/man
default: ${PROG}
+OPENBSD:=reallocarray.c strtonum.c execvpe.c setresuid.c \
+ auth_userokay.c setusercontext.c
+OPENBSD:=$(addprefix libopenbsd/,${OPENBSD:.c=.o})
+libopenbsd.a: ${OPENBSD}
+ ${AR} -r $@ $?
+
OBJS:=${SRCS:.y=.c}
OBJS:=${OBJS:.c=.o}
-${PROG}: ${OBJS}
- ${CC} ${COPTS} ${LDOPTS} $^ -o $@
+${PROG}: ${OBJS} libopenbsd.a
+ ${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@
${BINDIR}/${PROG}: ${PROG}
cp $< $@
@@ -31,6 +37,8 @@ ${BINDIR}/${PROG}: ${PROG}
install: ${BINDIR}/${PROG}
clean:
+ rm -f libopenbsd.a
+ rm -f ${OPENBSD}
rm -f ${OBJS}
rm -f ${PROG}
diff --git a/libopenbsd/auth_userokay.c b/libopenbsd/auth_userokay.c
new file mode 100644
index 0000000..3890e03
--- /dev/null
+++ b/libopenbsd/auth_userokay.c
@@ -0,0 +1,21 @@
+/* Copyright 2015 Nathan Holstein */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "openbsd.h"
+
+int
+auth_userokay(char *name, char *style, char *type, char *password)
+{
+ if (style || type || password) {
+ fprintf(stderr, "auth_userokay(name, NULL, NULL, NULL)!\n");
+ exit(1);
+ }
+
+ fprintf(stderr, "failing auth check for %s\n", name);
+
+ return 0;
+}
+
diff --git a/libopenbsd/execvpe.c b/libopenbsd/execvpe.c
new file mode 100644
index 0000000..f080148
--- /dev/null
+++ b/libopenbsd/execvpe.c
@@ -0,0 +1,156 @@
+/* $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);
+}
diff --git a/libopenbsd/openbsd.h b/libopenbsd/openbsd.h
index bcf0e3b..5f7c364 100644
--- a/libopenbsd/openbsd.h
+++ b/libopenbsd/openbsd.h
@@ -1,6 +1,8 @@
#ifndef _LIB_OPENBSD_H_
#define _LIB_OPENBSD_H_
+#include <sys/types.h>
+
/* API definitions lifted from OpenBSD src/include */
/* bsd_auth.h */
diff --git a/libopenbsd/reallocarray.c b/libopenbsd/reallocarray.c
new file mode 100644
index 0000000..aa70686
--- /dev/null
+++ b/libopenbsd/reallocarray.c
@@ -0,0 +1,38 @@
+/* $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);
+}
diff --git a/libopenbsd/setresuid.c b/libopenbsd/setresuid.c
new file mode 100644
index 0000000..5837f2b
--- /dev/null
+++ b/libopenbsd/setresuid.c
@@ -0,0 +1,22 @@
+/* Copyright 2015 Nathan Holstein */
+
+#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;
+}
+
diff --git a/libopenbsd/setusercontext.c b/libopenbsd/setusercontext.c
new file mode 100644
index 0000000..692b51a
--- /dev/null
+++ b/libopenbsd/setusercontext.c
@@ -0,0 +1,24 @@
+/* Copyright 2015 Nathan Holstein */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "openbsd.h"
+
+int
+setusercontext(login_cap_t *lc, struct passwd *pwd, uid_t uid, unsigned int flags)
+{
+ if (lc != NULL || pwd == NULL ||
+ (flags & ~(LOGIN_SETGROUP | LOGIN_SETPRIORITY |
+ LOGIN_SETRESOURCES | LOGIN_SETUMASK |
+ LOGIN_SETUSER)) != 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ fprintf(stderr, "failing setusercontext() for %d\n", (int) uid);
+
+ return -1;
+}
+
diff --git a/libopenbsd/strtonum.c b/libopenbsd/strtonum.c
new file mode 100644
index 0000000..3725177
--- /dev/null
+++ b/libopenbsd/strtonum.c
@@ -0,0 +1,65 @@
+/* $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);
+}