From: Duncaen Date: Wed, 8 Jun 2016 15:50:28 +0000 (+0200) Subject: open pam sessions with right user and remove setusercontext shim X-Git-Tag: v0.3~12 X-Git-Url: https://git.armaanb.net/?p=opendoas.git;a=commitdiff_plain;h=4f7ed3854a4db241401f5b84cbb6246a06a17561 open pam sessions with right user and remove setusercontext shim before this change the sessions were opened as the user running doas. Now it sets its uid to root and then opens a pam session for the target user. The setusercontext shim was removed, because pam handles all this and its easier to just call setresuid and setresgid instead. --- diff --git a/configure b/configure index cc23132..3e34695 100755 --- a/configure +++ b/configure @@ -280,18 +280,6 @@ int main(void) { printf 'LDFLAGS += -lpam\n' >>$CONFIG_MK } -# -# Check for login_cap.h. -# -src=' -#include -int main(void) { - return 0; -}' -check_func "login_cap_h" "$src" || { - printf 'OPENBSD += setusercontext.o\n' >>$CONFIG_MK -} - # # Check for execvpe(). # diff --git a/doas.c b/doas.c index 3e15824..f1b2ec0 100644 --- a/doas.c +++ b/doas.c @@ -439,6 +439,10 @@ main(int argc, char **argv, char **envp) 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) @@ -473,9 +477,8 @@ main(int argc, char **argv, char **envp) explicit_bzero(rbuf, sizeof(rbuf)); } #elif HAVE_PAM_APPL_H - if (!doas_pam(myname, !nflag, rule->options & NOPASS)) { - syslog(LOG_AUTHPRIV | LOG_NOTICE, - "failed auth for %s", myname); + if (!doas_pam(pw->pw_name, myname, !nflag, rule->options & NOPASS)) { + syslog(LOG_AUTHPRIV | LOG_NOTICE, "failed auth for %s", myname); errc(1, EPERM, NULL); } #else @@ -486,14 +489,19 @@ main(int argc, char **argv, char **envp) 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 + if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) + errx(1, "setgid"); + if (initgroups(pw->pw_name, pw->pw_gid) != 0) + errx(1, "initgroups"); + if (setresuid(target, target, target) != 0) + errx(1, "setuid"); +#endif if (pledge("stdio rpath exec", NULL) == -1) err(1, "pledge"); diff --git a/doas_pam.c b/doas_pam.c index f8b6e63..4f2731d 100644 --- a/doas_pam.c +++ b/doas_pam.c @@ -39,6 +39,12 @@ static pam_handle_t *pamh = NULL; static sig_atomic_t volatile caught_signal = 0; static char doas_prompt[128]; +static void +catchsig(int sig) +{ + caught_signal = sig; +} + static char * prompt(const char *msg, int echo_on, int *pam) { @@ -48,7 +54,7 @@ prompt(const char *msg, int echo_on, int *pam) /* overwrite default prompt if it matches "Password:[ ]" */ if (strncmp(msg,"Password:", 9) == 0 && - (msg[9] == '\0' || (msg[9] == ' ' && msg[10] == '\0'))) + (msg[9] == '\0' || (msg[9] == ' ' && msg[10] == '\0'))) prompt = doas_prompt; else prompt = msg; @@ -86,7 +92,7 @@ doas_pam_conv(int nmsgs, const struct pam_message **msgs, case PAM_ERROR_MSG: case PAM_TEXT_INFO: if (fprintf(style == PAM_ERROR_MSG ? stderr : stdout, - "%s\n", msgs[i]->msg) < 0) + "%s\n", msgs[i]->msg) < 0) goto fail; break; @@ -117,14 +123,8 @@ fail: return PAM_CONV_ERR; } -static void -catchsig(int sig) -{ - caught_signal = sig; -} - int -doas_pam(char *name, int interactive, int nopass) +doas_pam(const char *user, const char* ruser, int interactive, int nopass) { static const struct pam_conv conv = { .conv = doas_pam_conv, @@ -134,23 +134,22 @@ doas_pam(char *name, int interactive, int nopass) pid_t child; int ret; - if (!name) + if (!user || !ruser) return 0; - ret = pam_start(PAM_SERVICE_NAME, name, &conv, &pamh); - if (ret != PAM_SUCCESS) - errx(1, "pam_start(\"%s\", \"%s\", ?, ?): failed\n", - PAM_SERVICE_NAME, name); + /* pam needs the real root */ + if(setuid(0)) + errx(1, "setuid"); - ret = pam_set_item(pamh, PAM_USER, name); + ret = pam_start(PAM_SERVICE_NAME, ruser, &conv, &pamh); if (ret != PAM_SUCCESS) - errx(1, "pam_set_item(?, PAM_USER, \"%s\"): %s\n", - name, pam_strerror(pamh, ret)); + errx(1, "pam_start(\"%s\", \"%s\", ?, ?): failed\n", + PAM_SERVICE_NAME, ruser); - ret = pam_set_item(pamh, PAM_RUSER, name); + ret = pam_set_item(pamh, PAM_RUSER, ruser); if (ret != PAM_SUCCESS) - errx(1, "pam_set_item(?, PAM_RUSER, \"%s\"): %s\n", - name, pam_strerror(pamh, ret)); + warn("pam_set_item(?, PAM_RUSER, \"%s\"): %s\n", + pam_strerror(pamh, ret), ruser); if (isatty(0) && (ttydev = ttyname(0)) != NULL) { if (strncmp(ttydev, "/dev/", 5)) @@ -160,8 +159,8 @@ doas_pam(char *name, int interactive, int nopass) ret = pam_set_item(pamh, PAM_TTY, tty); if (ret != PAM_SUCCESS) - errx(1, "pam_set_item(?, PAM_TTY, \"%s\"): %s\n", - tty, pam_strerror(pamh, ret)); + warn("pam_set_item(?, PAM_TTY, \"%s\"): %s\n", + tty, pam_strerror(pamh, ret)); } if (!nopass) { @@ -173,14 +172,12 @@ doas_pam(char *name, int interactive, int nopass) if (gethostname(host, sizeof(host))) snprintf(host, sizeof(host), "?"); snprintf(doas_prompt, sizeof(doas_prompt), - "\rdoas (%.32s@%.32s) password: ", name, host); + "\rdoas (%.32s@%.32s) password: ", ruser, host); /* authenticate */ ret = pam_authenticate(pamh, 0); if (ret != PAM_SUCCESS) { - ret = pam_end(pamh, ret); - if (ret != PAM_SUCCESS) - errx(1, "pam_end(): %s\n", pam_strerror(pamh, ret)); + pam_end(pamh, ret); return 0; } } @@ -193,10 +190,14 @@ doas_pam(char *name, int interactive, int nopass) if (ret != PAM_SUCCESS) return 0; + ret = pam_set_item(pamh, PAM_USER, user); + if (ret != PAM_SUCCESS) + warn("pam_set_item(?, PAM_USER, \"%s\"): %s\n", user, + pam_strerror(pamh, ret)); + ret = pam_setcred(pamh, PAM_ESTABLISH_CRED); if (ret != PAM_SUCCESS) - errx(1, "pam_setcred(?, PAM_ESTABLISH_CRED): %s\n", - pam_strerror(pamh, ret)); + warn("pam_setcred(?, PAM_ESTABLISH_CRED): %s\n", pam_strerror(pamh, ret)); /* open session */ ret = pam_open_session(pamh, 0); @@ -233,10 +234,10 @@ doas_pam(char *name, int interactive, int nopass) /* unblock SIGTERM and SIGALRM to catch them */ sigemptyset(&sigs); - if(sigaddset(&sigs, SIGTERM) || - sigaddset(&sigs, SIGALRM) || - sigaction(SIGTERM, &act, &oldact) || - sigprocmask(SIG_UNBLOCK, &sigs, NULL)) { + if (sigaddset(&sigs, SIGTERM) || + sigaddset(&sigs, SIGALRM) || + sigaction(SIGTERM, &act, &oldact) || + sigprocmask(SIG_UNBLOCK, &sigs, NULL)) { warn("failed to set signal handler"); caught_signal = 1; } @@ -246,7 +247,7 @@ doas_pam(char *name, int interactive, int nopass) if (waitpid(child, &status, 0) != -1) { if (WIFSIGNALED(status)) { fprintf(stderr, "%s%s\n", strsignal(WTERMSIG(status)), - WCOREDUMP(status) ? " (core dumped)" : ""); + WCOREDUMP(status) ? " (core dumped)" : ""); status = WTERMSIG(status) + 128; } else { status = WEXITSTATUS(status); diff --git a/includes.h b/includes.h index e9ebf63..776a940 100644 --- a/includes.h +++ b/includes.h @@ -20,7 +20,7 @@ #include "openbsd.h" #ifdef HAVE_PAM_APPL_H -int doas_pam(char *name, int interactive, int nopass); +int doas_pam(const char *user, const char *ruser, int interactive, int nopass); #endif #endif /* INCLUDES_H */ diff --git a/libopenbsd/openbsd.h b/libopenbsd/openbsd.h index 87be1c0..0586844 100644 --- a/libopenbsd/openbsd.h +++ b/libopenbsd/openbsd.h @@ -8,23 +8,6 @@ /* API definitions lifted from OpenBSD src/include */ -/* 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 */ -#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); -#endif /* !HAVE_LOGIN_CAP_H */ - /* pwd.h */ #define _PW_NAME_LEN 63 diff --git a/libopenbsd/setusercontext.c b/libopenbsd/setusercontext.c deleted file mode 100644 index 6b05dd5..0000000 --- a/libopenbsd/setusercontext.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2015 Nathan Holstein - * - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include "includes.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; -} - diff --git a/pam.d__doas__linux b/pam.d__doas__linux index 9781fb2..813a0e4 100644 --- a/pam.d__doas__linux +++ b/pam.d__doas__linux @@ -1,10 +1,9 @@ #%PAM-1.0 -auth sufficient pam_timestamp.so timestamp_timeout=300 verbose debug -auth sufficient pam_rootok.so +auth sufficient pam_timestamp.so timestamp_timeout=300 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 optional pam_timestamp.so timestamp_timeout=300 session required pam_env.so session required pam_unix.so