diff options
Diffstat (limited to 'multi_auth.c')
-rw-r--r-- | multi_auth.c | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/multi_auth.c b/multi_auth.c index 9140036..270e773 100644 --- a/multi_auth.c +++ b/multi_auth.c @@ -1,4 +1,5 @@ #include <stdio.h> +#include <stdbool.h> #include <stdlib.h> #include <security/pam_appl.h> #include <security/pam_modules.h> @@ -27,6 +28,7 @@ struct auth_module_t { void *dl_handler; pid_t pid; + bool active; }; static @@ -95,6 +97,7 @@ static int perform_auth(void) int clone_flags = CLONE_NEWUTS|SIGCHLD; modules_g[i].pid = clone(module_auth_main, stack + STACK_SIZE, clone_flags, &mod->args); + modules_g[i].active = true; if (modules_g[i].pid == -1) { return PAM_SYSTEM_ERR; @@ -103,19 +106,40 @@ static int perform_auth(void) } siginfo_t infos; + int modules_terminated = 0; + int ret = PAM_AUTH_ERR; - /* wait for a first child to exit or be killed */ - waitid(P_ALL, 0, &infos, WEXITED); + do { + /* wait for a first child to exit or be killed */ + waitid(P_ALL, 0, &infos, WEXITED); - int ret = infos.si_status; + ++modules_terminated; + + /* find the process matching the pid */ + for (int i = 0; i < countof(modules_g); ++i) { + struct auth_module_t *mod = &modules_g[i]; + + if (mod->pid == infos.si_pid) { + mod->active = false; + break; + } + } + + if (infos.si_status == PAM_SUCCESS || infos.si_status == PAM_AUTH_ERR) { + ret = infos.si_status; + break; + } + + } while (modules_terminated < countof(modules_g)); for (int i = 0; i < countof(modules_g); ++i) { - if (modules_g[i].pid == infos.si_pid) { + struct auth_module_t *mod = &modules_g[i]; + + if (!mod->active) continue; - } - kill(modules_g[i].pid, SIGKILL); - waitpid(modules_g[i].pid, NULL, 0); + kill(mod->pid, SIGKILL); + waitpid(mod->pid, NULL, 0); } return ret; |