opendoas

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

commit cbae406f55e6b1da7ec40417f24a5beceefd655d
parent eb33da16ec8b0203cd48cd06f85bb4e9cf19d250
Author: Duncaen <mail@duncano.de>
Date:   Sun,  8 May 2016 22:23:26 +0200

Make pam session handling more failsafe

Diffstat:
doas_pam.c | 61++++++++++++++++++++++++++++++-------------------------------
1 file changed, 30 insertions(+), 31 deletions(-)

diff --git a/doas_pam.c b/doas_pam.c @@ -163,29 +163,27 @@ doas_pam(char *name, int interactive, int nopass) } } + ret = pam_acct_mgmt(pamh, 0); + if (ret == PAM_NEW_AUTHTOK_REQD) + ret = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); + + /* account not vaild or changing the auth token failed */ + if (ret != PAM_SUCCESS) + return 0; + ret = pam_setcred(pamh, PAM_ESTABLISH_CRED); if (ret != PAM_SUCCESS) errx(1, "pam_setcred(?, PAM_ESTABLISH_CRED): %s\n", pam_strerror(pamh, ret)); - ret = pam_acct_mgmt(pamh, 0); - if (ret != PAM_SUCCESS) - errx(1, "pam_setcred(): %s\n", pam_strerror(pamh, ret)); - /* open session */ ret = pam_open_session(pamh, 0); if (ret != PAM_SUCCESS) errx(1, "pam_open_session(): %s\n", pam_strerror(pamh, ret)); if ((child = fork()) == -1) { - ret = pam_close_session(pamh, 0); - if (ret != PAM_SUCCESS) - errx(1, "pam_close_session(): %s\n", pam_strerror(pamh, ret)); - - ret = pam_end(pamh, PAM_ABORT); - if (ret != PAM_SUCCESS) - errx(1, "pam_end(): %s\n", pam_strerror(pamh, ret)); - + pam_close_session(pamh, 0); + pam_end(pamh, PAM_ABORT); errx(1, "fork()"); } @@ -202,37 +200,41 @@ doas_pam(char *name, int interactive, int nopass) /* block signals */ sigfillset(&sigs); if (sigprocmask(SIG_BLOCK, &sigs, NULL)) { - errx(1, "sigprocmask()"); + warn("failed to block signals"); + caught_signal = 1; } /* setup signal handler */ act.sa_handler = catchsig; sigemptyset(&act.sa_mask); act.sa_flags = 0; - sigemptyset(&sigs); /* 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)) { - errx(1, "failed to set signal handler"); + warn("failed to set signal handler"); + caught_signal = 1; } - /* wait for child to be terminated */ - if (waitpid(child, &status, 0) != -1) { - if (WIFSIGNALED(status)) { - fprintf(stderr, "%s%s\n", strsignal(WTERMSIG(status)), - WCOREDUMP(status) ? " (core dumped)" : ""); - status = WTERMSIG(status) + 128; - } else { - status = WEXITSTATUS(status); + if (!caught_signal) { + /* wait for child to be terminated */ + if (waitpid(child, &status, 0) != -1) { + if (WIFSIGNALED(status)) { + fprintf(stderr, "%s%s\n", strsignal(WTERMSIG(status)), + WCOREDUMP(status) ? " (core dumped)" : ""); + status = WTERMSIG(status) + 128; + } else { + status = WEXITSTATUS(status); + } } + else if (caught_signal) + status = caught_signal + 128; + else + status = 1; } - else if (caught_signal) - status = caught_signal + 128; - else - status = 1; if (caught_signal) { fprintf(stderr, "\nSession terminated, killing shell\n"); @@ -244,9 +246,7 @@ doas_pam(char *name, int interactive, int nopass) if (ret != PAM_SUCCESS) errx(1, "pam_close_session(): %s\n", pam_strerror(pamh, ret)); - ret = pam_end(pamh, PAM_SUCCESS); - if (ret != PAM_SUCCESS) - errx(1, "pam_end(): %s\n", pam_strerror(pamh, ret)); + pam_end(pamh, PAM_SUCCESS); if (caught_signal) { /* kill child */ @@ -262,6 +262,5 @@ doas_pam(char *name, int interactive, int nopass) } exit(status); - return 0; }