opendoas

A portable version of the OpenBSD `doas` command
git clone https://pi.duncano.de/git/opendoas.git
Log | Files | Refs | README | LICENSE

commit 861d30f4b90c5312b33358caea08e8e26fc24818
parent 610e74190352a5c8c1f1746a272fc7364cb2bac3
Author: Duncaen <mail@duncano.de>
Date:   Fri,  6 May 2016 03:00:16 +0200

Add configure script

Diffstat:
.gitignore | 2++
LICENSE | 1+
Makefile | 4----
bsd.prog.mk | 20++++++++++----------
configure | 300+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
doas.c | 2+-
includes.h | 22++++++++++++++++++++++
libopenbsd/auth_userokay.c | 5+----
libopenbsd/execvpe.c | 2++
libopenbsd/openbsd.h | 42+++++++++++++++++++++++++++++++++++++++++-
libopenbsd/setusercontext.c | 3++-
pam.d__doas__linux | 10++++++++++
12 files changed, 392 insertions(+), 21 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -8,3 +8,5 @@ version.h *.swp *.swo + +config.mk diff --git a/LICENSE b/LICENSE @@ -1,5 +1,6 @@ portions copyright (c) 2015 Nathan Holstein portions copyright (c) 2015 Ted Unangst +portions copyright (c) 2016 Duncan Overbruck To the best of my knowledge, everything is released under the BSD license. diff --git a/Makefile b/Makefile @@ -16,7 +16,3 @@ LDFLAGS+= -lpam include bsd.prog.mk doas.o: version.h - -/etc/pam.d/doas: pam.d__doas - cp $< $@ -install: /etc/pam.d/doas diff --git a/bsd.prog.mk b/bsd.prog.mk @@ -1,12 +1,9 @@ # 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 +include config.mk + OPENBSD:=$(addprefix libopenbsd/,${OPENBSD:.c=.o}) libopenbsd.a: ${OPENBSD} ${AR} -r $@ $? @@ -21,15 +18,18 @@ ${PROG}: ${OBJS} libopenbsd.a .%.chmod: % cp $< $@ - chmod ${BINMODE} $@ chown ${BINOWN}:${BINGRP} $@ + chmod ${BINMODE} $@ -${BINDIR}: +${DESTRDIR}${BINDIR} ${DESTRDIR}${PAMDIR}: mkdir -pm 0755 $@ -${BINDIR}/${PROG}: .${PROG}.chmod ${BINDIR} +${DESTDIR}${BINDIR}/${PROG}: .${PROG}.chmod ${BINDIR} mv $< $@ +${DESTDIR}${PAMDIR}/doas: ${PAM_DOAS} + cp $< $@ + VERSION:=\#define VERSION "$(shell git describe --dirty --tags --long --always)" OLDVERSION:=$(shell [ -f version.h ] && cat version.h) version.h: ; @echo '$(VERSION)' > $@ @@ -37,10 +37,10 @@ ifneq ($(VERSION),$(OLDVERSION)) .PHONY: version.h endif -MAN:=$(join $(addprefix ${MANDIR}/man,$(patsubst .%,%/,$(suffix ${MAN}))),${MAN}) +MAN:=$(join $(addprefix ${DESTDIR}${MANDIR}/man,$(patsubst .%,%/,$(suffix ${MAN}))),${MAN}) $(foreach M,${MAN},$(eval $M: $(notdir $M); cp $$< $$@)) -install: ${BINDIR}/${PROG} ${MAN} +install: ${DESTDIR}${BINDIR}/${PROG} ${DESTDIR}${PAMDIR}/doas ${MAN} clean: rm -f version.h diff --git a/configure b/configure @@ -0,0 +1,300 @@ +#!/bin/sh + +for x; do + opt=${x%%=*} + var=${x#*=} + case "$opt" in + --enable-debug) DEBUG=yes;; + --prefix) PREFIX=$var;; + --exec-prefix) EPREFIX=$var;; + --bindir) BINDIR=$var;; + --mandir) MANDIR=$var;; + --datadir) SHAREDIR=$var;; + --build) BUILD=$var;; + --host) HOST=$var;; + --target) TARGET=$var;; + --includedir) INCLUDEDIR=$var;; + --sysconfdir) SYSCONFDIR=$var;; + --pamdir) PAMDIR=$var;; + --localstatedir) LOCALSTATEDIR=$var;; + --libdir) LIBDIR=$var;; + --datadir|--infodir) ;; # ignore autotools + --verbose) unset SILENT;; + --pkgconfigdir) PKGCONFIGDIR=$var;; + --enable-static) BUILD_STATIC=yes;; + --enable-seccomp) BUILD_SECCOMP=yes;; + --help) usage;; + *) echo "$0: WARNING: unknown option $opt" >&2;; + esac +done + +CONFIG_MK=config.mk +rm -f "$CONFIG_MK" + +cat <<EOF >>$CONFIG_MK +DESTDIR ?= / +PREFIX ?= ${PREFIX:="/usr"} +EPREFIX ?= ${EPREFIX:="${PREFIX}"} +SHAREDIR ?= ${SHAREDIR:="${PREFIX}/share"} +BINDIR ?= ${BINDIR:="${PREFIX}/bin"} +MANDIR ?= ${MANDIR:="${SHAREDIR}/man"} +SYSCONFDIR?= ${SYSCONFDIR:="/etc"} +PAMDIR ?= ${PAMDIR:="${SYSCONFDIR}/pam.d"} +EOF + +if [ -z "$BUILD" ]; then + BUILD="$(uname -m)-unknown-$(uname -s | tr '[:upper:]' '[:lower:]')" +fi +if [ -z "$HOST" ]; then + [ -z "$TARGET" ] && TARGET=$BUILD + HOST=$TARGET +fi +if [ -z "$TARGET" ]; then + [ -z "$HOST" ] && HOST=$BUILD + TARGET=$HOST +fi + +if [ -z "$OS" ]; then + # Derive OS from cpu-manufacturer-os-kernel + CPU=${TARGET%%-*} + REST=${TARGET#*-} + MANU=${REST%%-*} + REST=${REST#*-} + OS=${REST%%-*} + REST=${REST#*-} + KERNEL=${REST%%-*} +fi + +case "$OS" in + linux) + OS_CFLAGS="-D_DEFAULT_SOURCE -D_GNU_SOURCE -DUID_MAX=60000 -DGID_MAX=60000" + printf 'CURDIR := .\n' >>$CONFIG_MK + printf 'PAM_DOAS = pam.d__doas__linux\n' >>$CONFIG_MK + ;; +esac + +[ -n "$OS_CFLAGS" ] && \ + printf 'CFLAGS += %s\n' "$OS_CFLAGS" >>$CONFIG_MK + +# Add CPPFLAGS/CFLAGS/LDFLAGS to CC for testing features +XCC="${CC:=clang} $CFLAGS $OS_CFLAGS $CPPFLAGS $LDFLAGS" +# Make sure to disable --as-needed for CC tests. +XCC="$XCC -Wl,--no-as-needed" + +check_func() { + func="$1"; src="$2"; shift 2 + printf 'Checking for %-14s\t\t' "$func ..." + printf '%s\n' "$src" >"_$func.c" + if $XCC "_$func.c" -o "_$func" 2>/dev/null; then + printf 'yes.\n' + upperfunc="$(printf '%s\n' "$func" | tr '[[:lower:]]' '[[:upper:]]')" + printf 'CFLAGS += -DHAVE_%s\n' "$upperfunc" >>$CONFIG_MK + else + printf 'no.\n' + fi + rm -f "_$func.c" "_$func" +} + +src=' +#include <string.h> +int main(void) { + explicit_bzero(NULL, 0); + return 0; +}' +check_func "explicit_bzero" "$src" || { + printf 'OPENBSD += explicit_bzero.c\n' >>$CONFIG_MK +} + + +# +# Check for strlcat(). +# +src=' +#include <string.h> +int main(void) { + const char s1[] = "foo"; + char s2[10]; + strlccat(s2, s1, sizeof(s2)); + return 0; +}' +check_func "strlcat" "$src" || { + printf 'OPENBSD += strlcat.c\n' >>$CONFIG_MK +} + +# +# Check for strlcpy(). +# +src=' +#include <string.h> +int main(void) { + const char s1[] = "foo"; + char s2[10]; + strlcpy(s2, s1, sizeof(s2)); + return 0; +}' +check_func "strlcpy" "$src" || { + printf 'OPENBSD += strlcpy.c\n' >>$CONFIG_MK +} + +# +# Check for errc(). +# +src=' +#include <err.h> +int main(void) { + errc(0, 0, ""); + return 0; +}' +check_func "errc" "$src" || { + printf 'OPENBSD += errc.c\n' >>$CONFIG_MK +} + +# +# Check for verrc(). +# +src=' +#include <err.h> +int main(void) { + verrc(0, 0, ""); + return 0; +}' +check_func "verrc" "$src" || { + printf 'OPENBSD += verrc.c\n' >>$CONFIG_MK +} + +# +# Check for setprogname(). +# +src=' +#include <stdlib.h> +int main(void) { + setprogname(""); + return 0; +}' +check_func "setprogname" "$src" || { + printf 'OPENBSD += progname.c\n' >>$CONFIG_MK +} + +# +# Check for readpassphrase(). +# +src=' +#include <readpassphrase.h> +int main(void) { + char buf[12]; + readpassphrase("", buf, sizeof(buf), 0); + return 0; +}' +check_func "readpassphrase" "$src" || { + printf 'OPENBSD += readpassphrase.c\n' >>$CONFIG_MK +} + +# +# Check for strtonum(). +# +src=' +#include <stdlib.h> +int main(void) { + const char *errstr; + strtonum("", 1, 64, &errstr); + return 0; +}' +check_func "strtonum" "$src" || { + printf 'OPENBSD += strtonum.c\n' >>$CONFIG_MK +} + +# +# Check for reallocarray(). +# +src=' +#include <stdlib.h> +int main(void) { + reallocarray(NULL, 0, 0); + return 0; +}' +check_func "reallocarray" "$src" || { + printf 'OPENBSD += reallocarray.c\n' >>$CONFIG_MK +} + +# +# Check for bsd_auth.h. +# +src=' +#include <bsd_auth.h> +int main(void) { + return 0; +}' +check_func "bsd_auth_h" "$src" || { + printf 'OPENBSD += auth_userokay.c\n' >>$CONFIG_MK +} + +# +# Check for login_cap.h. +# +src=' +#include <login_cap.h> +int main(void) { + return 0; +}' +check_func "login_cap_h" "$src" || { + printf 'OPENBSD += setusercontext.c\n' >>$CONFIG_MK +} + +# +# Check for execvpe(). +# +src=' +#include <unistd.h> +int main(void) { + const char *p = { "", NULL }; + execvpe("", p, p); + return 0; +}' +check_func "execvpe" "$src" || { + printf 'OPENBSD += execvpe.c\n' >>$CONFIG_MK +} + +# +# Check for setresuid(). +# +src=' +#include <unistd.h> +int main(void) { + setresuid(0, 0, 0); + return 0; +}' +check_func "setresuid" "$src" || { + printf 'OPENBSD += setresuid.c\n' >>$CONFIG_MK +} + +# +# Check for pledge(). +# +src=' +#include <unistd.h> +int main(void) { + pledge("", NULL); + return 0; +}' +check_func "pledge" "$src" && { + have_pledge=1 +} + +# +# Check for seccomp.h +# +src=' +#include <linux/seccomp.h> +#include <sys/prctl.h> +#include <unistd.h> +int main(void) { + prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL); + return 0; +}' +if [ -n "$have_pledge" -a -n "$BUILD_SECCOMP" ]; then + check_func "seccomp_h" "$src" && { + printf 'OPENBSD += pledge-seccomp.c\n' >>$CONFIG_MK + } +elif [ -n "$have_pledge" ]; then + printf 'OPENBSD += pledge-noop.c\n' >>$CONFIG_MK +fi diff --git a/doas.c b/doas.c @@ -29,7 +29,7 @@ #include <syslog.h> #include <errno.h> -#include "openbsd.h" +#include "includes.h" #include "doas.h" #include "version.h" diff --git a/includes.h b/includes.h @@ -0,0 +1,22 @@ +#ifndef INCLUDES_H +#define INCLUDES_H + +#ifndef __UNUSED +# define __UNUSED __attribute__ ((unused)) +#endif + +#ifndef __dead +# define __dead +#endif + +#ifndef _PATH_TTY +# define _PATH_TTY "/dev/tty" +#endif + +#ifdef HAVE_READPASSPHRASE_H +# include <readpassphrase.h> +#endif + +#include "openbsd.h" + +#endif /* INCLUDES_H */ diff --git a/libopenbsd/auth_userokay.c b/libopenbsd/auth_userokay.c @@ -18,19 +18,16 @@ #include <err.h> #include <errno.h> #include <pwd.h> -#include <readpassphrase.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <security/pam_appl.h> -#include "openbsd.h" +#include "includes.h" #define PAM_SERVICE "doas" -#define __UNUSED __attribute__ ((unused)) - static char * pam_prompt(const char *msg, int echo_on, int *pam) { diff --git a/libopenbsd/execvpe.c b/libopenbsd/execvpe.c @@ -40,6 +40,8 @@ #include <string.h> #include <unistd.h> +#include "includes.h" + int execvpe(const char *name, char *const *argv, char *const *envp) { diff --git a/libopenbsd/openbsd.h b/libopenbsd/openbsd.h @@ -1,14 +1,21 @@ #ifndef _LIB_OPENBSD_H_ #define _LIB_OPENBSD_H_ +#include <stdarg.h> #include <sys/types.h> +#include <sys/cdefs.h> + +#include "readpassphrase.h" /* API definitions lifted from OpenBSD src/include */ /* bsd_auth.h */ +#ifndef HAVE_BSD_AUTH_H int auth_userokay(char *, char *, char *, char *); +#endif /* !HAVE_BSD_AUTH_H */ /* login_cap.h */ +#ifndef HAVE_LOGIN_CAP_H #define LOGIN_SETGROUP 0x0001 /* Set group */ #define LOGIN_SETLOGIN 0x0002 /* Set login */ #define LOGIN_SETPATH 0x0004 /* Set path */ @@ -22,20 +29,53 @@ int auth_userokay(char *, char *, char *, char *); typedef struct login_cap login_cap_t; struct passwd; int setusercontext(login_cap_t *, struct passwd *, uid_t, unsigned int); +#endif /* !HAVE_LOGIN_CAP_H */ /* pwd.h */ #define _PW_NAME_LEN 63 /* stdlib.h */ +#ifndef HAVE_REALLOCARRAY void * reallocarray(void *optr, size_t nmemb, size_t size); +#endif /* HAVE_REALLOCARRAY */ +#ifndef HAVE_STRTONUM long long strtonum(const char *numstr, long long minval, long long maxval, const char **errstrp); +#endif /* !HAVE_STRTONUM */ /* string.h */ +#ifndef HAVE_EXPLICIT_BZERO void explicit_bzero(void *, size_t); +#endif +#ifndef HAVE_STRLCAT +size_t strlcat(char *dst, const char *src, size_t dsize); +#endif /* !HAVE_STRLCAT */ +#ifndef HAVE_STRLCPY +size_t strlcpy(char *dst, const char *src, size_t dsize); +#endif /* !HAVE_STRLCPY */ /* unistd.h */ +#ifndef HAVE_EXECVPE int execvpe(const char *, char *const *, char *const *); +#endif /* !HAVE_EXECVPE */ +#ifndef HAVE_SETRESUID int setresuid(uid_t, uid_t, uid_t); +#endif /* !HAVE_SETRESUID */ +#ifndef HAVE_PLEDGE +int pledge(const char *promises, const char *paths[]); +#endif /* !HAVE_PLEDGE */ -#endif +/* err.h */ +#ifndef HAVE_VERRC +void verrc(int eval, int code, const char *fmt, va_list ap); +#endif /* !HAVE_VERRC */ +#ifndef HAVE_ERRC +void errc(int eval, int code, const char *fmt, ...); +#endif /* !HAVE_ERRC */ + +#ifndef HAVE_SETPROGNAME +const char * getprogname(void); +void setprogname(const char *progname); +#endif /* !HAVE_SETPROGNAME */ + +#endif /* _LIB_OPENBSD_H_ */ diff --git a/libopenbsd/setusercontext.c b/libopenbsd/setusercontext.c @@ -21,8 +21,9 @@ #include <pwd.h> #include <stdlib.h> #include <unistd.h> +#include <grp.h> -#include "openbsd.h" +#include "includes.h" int setusercontext(login_cap_t *lc, struct passwd *pw, uid_t uid, unsigned int flags) diff --git a/pam.d__doas__linux b/pam.d__doas__linux @@ -0,0 +1,10 @@ +#%PAM-1.0 +auth sufficient pam_timestamp.so timestamp_timeout=300 verbose debug +auth sufficient pam_rootok.so +auth required pam_unix.so +account required pam_unix.so +session optional pam_xauth.so +session optional pam_umask.so usergroups umask=022 +session optional pam_timestamp.so timestamp_timeout=300 debug +session required pam_env.so +session required pam_unix.so