i3 - improved tiling WM


Run authentification in different process

Patch status: merged

Patch by koebi

Long description:

fixes #895

To apply this patch, use:
curl http://cr.i3wm.org/patch/222/raw.patch | git am

b/i3lock.c

14
@@ -22,6 +22,7 @@
15
 #include <string.h>
16
 #include <ev.h>
17
 #include <sys/mman.h>
18
+#include <sys/wait.h>
19
 #include <X11/XKBlib.h>
20
 #include <X11/extensions/XKBfile.h>
21
 #include <xkbcommon/xkbcommon.h>
22
@@ -199,27 +200,11 @@ static void clear_input(void) {
23
     unlock_state = STATE_KEY_PRESSED;
24
 }
25
 
26
-static void input_done(void) {
27
-    if (clear_pam_wrong_timeout) {
28
-        ev_timer_stop(main_loop, clear_pam_wrong_timeout);
29
-        free(clear_pam_wrong_timeout);
30
-        clear_pam_wrong_timeout = NULL;
31
-    }
32
-
33
-    pam_state = STATE_PAM_VERIFY;
34
-    redraw_screen();
35
-
36
-    if (pam_authenticate(pam_handle, 0) == PAM_SUCCESS) {
37
-        DEBUG("successfully authenticated\n");
38
-        clear_password_memory();
39
-        exit(0);
40
-    }
41
-
42
+static void auth_failed(void) {
43
     if (debug_mode)
44
         fprintf(stderr, "Authentication failure\n");
45
-
46
+    
47
     pam_state = STATE_PAM_WRONG;
48
-    clear_input();
49
     redraw_screen();
50
 
51
     /* Clear this state after 2 seconds (unless the user enters another
52
@@ -241,6 +226,54 @@ static void input_done(void) {
53
     }
54
 }
55
 
56
+static void child_cb(EV_P_ ev_child *child_watcher, int revents) {
57
+    if (child_watcher->rstatus != 0) {
58
+        DEBUG("Authentication successfull\n");
59
+        clear_password_memory();
60
+
61
+        exit(0);
62
+    } else {
63
+        auth_failed();
64
+    }
65
+    ev_child_stop(main_loop, child_watcher);
66
+    free(child_watcher);
67
+}
68
+
69
+static void input_done(void) {
70
+    if (pam_state == STATE_PAM_VERIFY) {
71
+        return;
72
+    }
73
+
74
+    if (clear_pam_wrong_timeout) {
75
+        ev_timer_stop(main_loop, clear_pam_wrong_timeout);
76
+        free(clear_pam_wrong_timeout);
77
+        clear_pam_wrong_timeout = NULL;
78
+    }
79
+
80
+    pam_state = STATE_PAM_VERIFY;
81
+    redraw_screen();
82
+    
83
+    /* fork to unblock pam_authenticate */
84
+    pid_t cpid = fork();
85
+    if (cpid == 0) {
86
+        exit(pam_authenticate(pam_handle, 0) == PAM_SUCCESS);
87
+    } else if (cpid > 0) {
88
+        clear_input();
89
+        struct ev_child *child_watcher = calloc(sizeof(struct ev_io), 1);
90
+        ev_child_init(child_watcher, child_cb, cpid, 0);
91
+        ev_child_set(child_watcher, cpid, 0);
92
+        ev_child_start(EV_DEFAULT_ child_watcher);
93
+    } else if (cpid < 0) {
94
+        DEBUG("Could not fork");
95
+        if (pam_authenticate(pam_handle, 0) == PAM_SUCCESS) {
96
+            DEBUG("successfully authenticated\n");
97
+            clear_password_memory();
98
+            exit(0);
99
+        }
100
+        auth_failed();
101
+    }
102
+}
103
+
104
 /*
105
  * Called when the user releases a key. We need to leave the Mode_switch
106
  * state when the user releases the Mode_switch key.