summaryrefslogtreecommitdiff
path: root/security/pam-pwauth_suid/files/pam_pwauth_suid.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/pam-pwauth_suid/files/pam_pwauth_suid.c')
-rw-r--r--security/pam-pwauth_suid/files/pam_pwauth_suid.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/security/pam-pwauth_suid/files/pam_pwauth_suid.c b/security/pam-pwauth_suid/files/pam_pwauth_suid.c
index 0cd0643e140..4144a263a78 100644
--- a/security/pam-pwauth_suid/files/pam_pwauth_suid.c
+++ b/security/pam-pwauth_suid/files/pam_pwauth_suid.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pam_pwauth_suid.c,v 1.1.1.1 2007/01/08 18:39:44 drochner Exp $ */
+/* $NetBSD: pam_pwauth_suid.c,v 1.2 2007/09/05 20:29:05 drochner Exp $ */
#include <sys/types.h>
#include <security/pam_appl.h>
@@ -8,23 +8,32 @@
#include <string.h>
#include <sys/wait.h>
#include <errno.h>
+#include <signal.h>
static int
askhelper(const char *user, const char *pass)
{
int fd[2];
+ sigset_t chldsig, omask;
pid_t pid, rpid;
ssize_t res;
size_t pwlen;
- int s;
+ int err, s;
if (pipe(fd) < 0)
return errno;
+ /* make sure only we get the exit status of the helper */
+ sigemptyset(&chldsig);
+ sigaddset(&chldsig, SIGCHLD);
+ if (sigprocmask(SIG_BLOCK, &chldsig, &omask) < 0)
+ return errno;
+
pid = vfork();
switch (pid) {
case -1:
- return errno;
+ err = errno;
+ goto error;
case 0: /* child, feed it through its stdin */
(void)dup2(fd[0], STDIN_FILENO);
(void)close(fd[0]);
@@ -38,18 +47,25 @@ askhelper(const char *user, const char *pass)
pwlen = strlen(pass);
res = write(fd[1], pass, pwlen);
- if (res != pwlen)
- return (res == -1 ? errno : EIO);
+ if (res != pwlen) {
+ err = (res == -1 ? errno : EIO);
+ goto error;
+ }
(void)close(fd[1]); /* now child gets an EOF */
rpid = waitpid(pid, &s, 0);
+ sigprocmask(SIG_SETMASK, &omask, 0);
if (rpid != pid)
return errno;
if (!WIFEXITED(s) || WEXITSTATUS(s))
return EAUTH;
return 0;
+
+error:
+ sigprocmask(SIG_SETMASK, &omask, 0);
+ return err;
}
PAM_EXTERN int