]> git.armaanb.net Git - opendoas.git/commitdiff
Add compatibility functions from OpenBSD.
authorNathan Holstein <nathan.holstein@gmail.com>
Sun, 2 Aug 2015 17:30:58 +0000 (13:30 -0400)
committerNathan Holstein <nathan.holstein@gmail.com>
Wed, 5 Aug 2015 12:50:46 +0000 (08:50 -0400)
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.

.gitignore
Makefile
libopenbsd/auth_userokay.c [new file with mode: 0644]
libopenbsd/execvpe.c [new file with mode: 0644]
libopenbsd/openbsd.h
libopenbsd/reallocarray.c [new file with mode: 0644]
libopenbsd/setresuid.c [new file with mode: 0644]
libopenbsd/setusercontext.c [new file with mode: 0644]
libopenbsd/strtonum.c [new file with mode: 0644]

index 970069b93ff268546cc703b18dffd2fc731014a1..6fd68ebf7e5558a24339518ce6d5aa9a5def26fd 100644 (file)
@@ -1,5 +1,6 @@
 doas
 
+*.a
 *.o
 
 *.swp
index 7bb667e9a8927aa4be886f245bc56fd0acdec04e..167d8dd5f8894451f28babf8af99909b2e56a168 100644 (file)
--- 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 (file)
index 0000000..3890e03
--- /dev/null
@@ -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 (file)
index 0000000..f080148
--- /dev/null
@@ -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);
+}
index bcf0e3b8ac57c3d022a0e9100c41a5726fa18d65..5f7c364c2a0809baa922a206012ea2e87b4979d9 100644 (file)
@@ -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 (file)
index 0000000..aa70686
--- /dev/null
@@ -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 (file)
index 0000000..5837f2b
--- /dev/null
@@ -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 (file)
index 0000000..692b51a
--- /dev/null
@@ -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 (file)
index 0000000..3725177
--- /dev/null
@@ -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);
+}