diff options
Diffstat (limited to 'swaylock/password.c')
-rw-r--r-- | swaylock/password.c | 58 |
1 files changed, 57 insertions, 1 deletions
diff --git a/swaylock/password.c b/swaylock/password.c index da67205d..9af7fe16 100644 --- a/swaylock/password.c +++ b/swaylock/password.c | |||
@@ -1,4 +1,6 @@ | |||
1 | #include <assert.h> | 1 | #include <assert.h> |
2 | #include <pwd.h> | ||
3 | #include <security/pam_appl.h> | ||
2 | #include <stdlib.h> | 4 | #include <stdlib.h> |
3 | #include <unistd.h> | 5 | #include <unistd.h> |
4 | #include <wlr/util/log.h> | 6 | #include <wlr/util/log.h> |
@@ -7,6 +9,58 @@ | |||
7 | #include "swaylock/seat.h" | 9 | #include "swaylock/seat.h" |
8 | #include "unicode.h" | 10 | #include "unicode.h" |
9 | 11 | ||
12 | static int function_conversation(int num_msg, const struct pam_message **msg, | ||
13 | struct pam_response **resp, void *data) { | ||
14 | struct swaylock_password *pw = data; | ||
15 | /* PAM expects an array of responses, one for each message */ | ||
16 | struct pam_response *pam_reply = calloc( | ||
17 | num_msg, sizeof(struct pam_response)); | ||
18 | *resp = pam_reply; | ||
19 | for (int i = 0; i < num_msg; ++i) { | ||
20 | switch (msg[i]->msg_style) { | ||
21 | case PAM_PROMPT_ECHO_OFF: | ||
22 | case PAM_PROMPT_ECHO_ON: | ||
23 | pam_reply[i].resp = pw->buffer; | ||
24 | break; | ||
25 | case PAM_ERROR_MSG: | ||
26 | case PAM_TEXT_INFO: | ||
27 | break; | ||
28 | } | ||
29 | } | ||
30 | return PAM_SUCCESS; | ||
31 | } | ||
32 | |||
33 | static bool attempt_password(struct swaylock_password *pw) { | ||
34 | struct passwd *passwd = getpwuid(getuid()); | ||
35 | char *username = passwd->pw_name; | ||
36 | const struct pam_conv local_conversation = { | ||
37 | function_conversation, pw | ||
38 | }; | ||
39 | pam_handle_t *local_auth_handle = NULL; | ||
40 | int pam_err; | ||
41 | if ((pam_err = pam_start("swaylock", username, | ||
42 | &local_conversation, &local_auth_handle)) != PAM_SUCCESS) { | ||
43 | wlr_log(L_ERROR, "PAM returned error %d", pam_err); | ||
44 | } | ||
45 | if ((pam_err = pam_authenticate(local_auth_handle, 0)) != PAM_SUCCESS) { | ||
46 | wlr_log(L_ERROR, "pam_authenticate failed"); | ||
47 | goto fail; | ||
48 | } | ||
49 | if ((pam_err = pam_end(local_auth_handle, pam_err)) != PAM_SUCCESS) { | ||
50 | wlr_log(L_ERROR, "pam_end failed"); | ||
51 | goto fail; | ||
52 | } | ||
53 | // PAM freed this | ||
54 | pw->buffer = NULL; | ||
55 | pw->len = pw->size = 0; | ||
56 | return true; | ||
57 | fail: | ||
58 | // PAM freed this | ||
59 | pw->buffer = NULL; | ||
60 | pw->len = pw->size = 0; | ||
61 | return false; | ||
62 | } | ||
63 | |||
10 | static void backspace(struct swaylock_password *pw) { | 64 | static void backspace(struct swaylock_password *pw) { |
11 | if (pw->len != 0) { | 65 | if (pw->len != 0) { |
12 | pw->buffer[--pw->len] = 0; | 66 | pw->buffer[--pw->len] = 0; |
@@ -43,7 +97,9 @@ void swaylock_handle_key(struct swaylock_state *state, | |||
43 | switch (keysym) { | 97 | switch (keysym) { |
44 | case XKB_KEY_KP_Enter: /* fallthrough */ | 98 | case XKB_KEY_KP_Enter: /* fallthrough */ |
45 | case XKB_KEY_Return: | 99 | case XKB_KEY_Return: |
46 | // TODO: Attempt password | 100 | if (attempt_password(&state->password)) { |
101 | exit(0); | ||
102 | } | ||
47 | break; | 103 | break; |
48 | case XKB_KEY_BackSpace: | 104 | case XKB_KEY_BackSpace: |
49 | backspace(&state->password); | 105 | backspace(&state->password); |