summaryrefslogtreecommitdiff
path: root/multi_auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'multi_auth.c')
-rw-r--r--multi_auth.c38
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;