opendoas

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

commit e88a009620a604d57d85bd53b971cfa77e44315e
parent 788dd4b64a25b2705f962c37962363c22d9c49f9
Author: Duncaen <mail@duncano.de>
Date:   Sun, 26 Jun 2016 23:10:37 +0200

add --without-pam configure option to allow passwd/shadow auth

Diffstat:
bsd.prog.mk | 6+++---
configure | 19+++++++++++++++++--
doas.c | 52+++++++++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 67 insertions(+), 10 deletions(-)

diff --git a/bsd.prog.mk b/bsd.prog.mk @@ -18,14 +18,14 @@ ${PROG}: ${OBJS} libopenbsd.a install: ${PROG} ${PAM_DOAS} ${MAN} mkdir -p -m 0755 ${DESTDIR}${BINDIR} - mkdir -p -m 0755 ${DESTDIR}${PAMDIR} + [ -n "${PAM_DOAS}" ] && mkdir -p -m 0755 ${DESTDIR}${PAMDIR} mkdir -p -m 0755 ${DESTDIR}${MANDIR}/man1 mkdir -p -m 0755 ${DESTDIR}${MANDIR}/man5 cp -f ${PROG} ${DESTDIR}${BINDIR} chown ${BINOWN}:${BINGRP} ${DESTDIR}${BINDIR}/${PROG} chmod ${BINMODE} ${DESTDIR}${BINDIR}/${PROG} - cp ${PAM_DOAS} ${DESTDIR}${PAMDIR}/doas - chmod 0644 ${DESTDIR}${PAMDIR}/doas + [ -n "${PAM_DOAS}" ] && cp ${PAM_DOAS} ${DESTDIR}${PAMDIR}/doas || true + [ -n "${PAM_DOAS}" ] && chmod 0644 ${DESTDIR}${PAMDIR}/doas cp -f doas.1 ${DESTDIR}${MANDIR}/man1 cp -f doas.conf.5 ${DESTDIR}${MANDIR}/man5 diff --git a/configure b/configure @@ -45,6 +45,7 @@ for x; do --target) TARGET=$var;; --enable-debug) DEBUG=yes;; --enable-static) BUILD_STATIC=yes;; + --without-pam) WITHOUT_PAM=yes;; --help|-h) usage;; *) die "Error: unknown option $opt";; esac @@ -96,7 +97,8 @@ case "$OS" in linux) OS_CFLAGS="$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 + [ -z "$WITHOUT_PAM" ] && \ + printf 'PAM_DOAS = pam.d__doas__linux\n' >>$CONFIG_MK ;; esac @@ -282,13 +284,26 @@ src=' int main(void) { return 0; }' -[ -z "$have_bsd_auth_h" ] && \ +[ -z "$WITHOUT_PAM" -a -z "$have_bsd_auth_h" ] && \ check_func "pam_appl_h" "$src" && { printf 'SRCS += pam.c\n' >>$CONFIG_MK printf 'LDFLAGS += -lpam\n' >>$CONFIG_MK } # +# Check for shadow.h. +# +src=' +#include <shadow.h> +int main(void) { + return 0; +}' +[ -z "$WITHOUT_PAM" -a -z "$have_bsd_auth_h" ] || \ + check_func "shadow_h" "$src" && { + printf 'LDFLAGS += -lcrypt\n' >>$CONFIG_MK + } + +# # Check for execvpe(). # src=' diff --git a/doas.c b/doas.c @@ -28,6 +28,9 @@ #include <grp.h> #include <syslog.h> #include <errno.h> +#if HAVE_SHADOW_H +#include <shadow.h> +#endif #include "includes.h" @@ -341,10 +344,6 @@ main(int argc, char **argv) errc(1, EPERM, NULL); } - pw = getpwuid(target); - if (!pw) - errx(1, "no passwd entry for target"); - #ifdef HAVE_BSD_AUTH_H if (!(rule->options & NOPASS)) { if (nflag) @@ -379,24 +378,67 @@ main(int argc, char **argv) explicit_bzero(rbuf, sizeof(rbuf)); } #elif HAVE_PAM_APPL_H + pw = getpwuid(target); + if (!pw) + errx(1, "no passwd entry for target"); + if (!pamauth(pw->pw_name, myname, !nflag, rule->options & NOPASS)) { syslog(LOG_AUTHPRIV | LOG_NOTICE, "failed auth for %s", myname); errc(1, EPERM, NULL); } -#else +#elif HAVE_SHADOW_H + const char *pass; + if (!(rule->options & NOPASS)) { + if (nflag) errx(1, "Authorization required"); + + pass = pw->pw_passwd; + if (pass[0] == 'x' && pass[1] == '\0') { + struct spwd *sp; + if (!(sp = getspnam(myname))) + errx(1, "Authorization failed"); + pass = sp->sp_pwdp; + } + + char *challenge, *response, rbuf[1024], cbuf[128], host[HOST_NAME_MAX + 1]; + if (gethostname(host, sizeof(host))) + snprintf(host, sizeof(host), "?"); + snprintf(cbuf, sizeof(cbuf), + "\rdoas (%.32s@%.32s) password: ", myname, host); + challenge = cbuf; + + response = readpassphrase(challenge, rbuf, sizeof(rbuf), RPP_REQUIRE_TTY); + if (response == NULL && errno == ENOTTY) { + syslog(LOG_AUTHPRIV | LOG_NOTICE, + "tty required for %s", myname); + errx(1, "a tty is required"); + } + if (strcmp(crypt(response, pass), pass) != 0) { + syslog(LOG_AUTHPRIV | LOG_NOTICE, "failed auth for %s", myname); + errc(1, EPERM, NULL); + } + explicit_bzero(rbuf, sizeof(rbuf)); + } +#else + if (!(rule->options & NOPASS)) + errx(1, "Authorization required"); #endif /* HAVE_BSD_AUTH_H */ if (pledge("stdio rpath getpw exec id", NULL) == -1) err(1, "pledge"); + pw = getpwuid(target); + if (!pw) + errx(1, "no passwd entry for target"); + #ifdef HAVE_BSD_AUTH_H if (setusercontext(NULL, pw, target, LOGIN_SETGROUP | LOGIN_SETPRIORITY | LOGIN_SETRESOURCES | LOGIN_SETUMASK | LOGIN_SETUSER) != 0) errx(1, "failed to set user context for target"); #else + warn(pw->pw_name); if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) errx(1, "setresgid"); if (initgroups(pw->pw_name, pw->pw_gid) != 0)