aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2018-04-03 14:49:56 -0400
committerDrew DeVault <sir@cmpwn.com>2018-04-04 18:47:48 -0400
commite902de34db2354335c1cbd6baf2fcf7e82509b63 (patch)
tree1cdc1fbdd0694971c4f58b28577452626f29aaec
parent066143adef7adc6e76e43e1990db2f75fe984b42 (diff)
Verify passwords
-rw-r--r--swaylock/password.c58
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 @@
#include <assert.h>
+#include <pwd.h>
+#include <security/pam_appl.h>
#include <stdlib.h>
#include <unistd.h>
#include <wlr/util/log.h>
@@ -7,6 +9,58 @@
#include "swaylock/seat.h"
#include "unicode.h"
+static int function_conversation(int num_msg, const struct pam_message **msg,
+ struct pam_response **resp, void *data) {
+ struct swaylock_password *pw = data;
+ /* PAM expects an array of responses, one for each message */
+ struct pam_response *pam_reply = calloc(
+ num_msg, sizeof(struct pam_response));
+ *resp = pam_reply;
+ for (int i = 0; i < num_msg; ++i) {
+ switch (msg[i]->msg_style) {
+ case PAM_PROMPT_ECHO_OFF:
+ case PAM_PROMPT_ECHO_ON:
+ pam_reply[i].resp = pw->buffer;
+ break;
+ case PAM_ERROR_MSG:
+ case PAM_TEXT_INFO:
+ break;
+ }
+ }
+ return PAM_SUCCESS;
+}
+
+static bool attempt_password(struct swaylock_password *pw) {
+ struct passwd *passwd = getpwuid(getuid());
+ char *username = passwd->pw_name;
+ const struct pam_conv local_conversation = {
+ function_conversation, pw
+ };
+ pam_handle_t *local_auth_handle = NULL;
+ int pam_err;
+ if ((pam_err = pam_start("swaylock", username,
+ &local_conversation, &local_auth_handle)) != PAM_SUCCESS) {
+ wlr_log(L_ERROR, "PAM returned error %d", pam_err);
+ }
+ if ((pam_err = pam_authenticate(local_auth_handle, 0)) != PAM_SUCCESS) {
+ wlr_log(L_ERROR, "pam_authenticate failed");
+ goto fail;
+ }
+ if ((pam_err = pam_end(local_auth_handle, pam_err)) != PAM_SUCCESS) {
+ wlr_log(L_ERROR, "pam_end failed");
+ goto fail;
+ }
+ // PAM freed this
+ pw->buffer = NULL;
+ pw->len = pw->size = 0;
+ return true;
+fail:
+ // PAM freed this
+ pw->buffer = NULL;
+ pw->len = pw->size = 0;
+ return false;
+}
+
static void backspace(struct swaylock_password *pw) {
if (pw->len != 0) {
pw->buffer[--pw->len] = 0;
@@ -43,7 +97,9 @@ void swaylock_handle_key(struct swaylock_state *state,
switch (keysym) {
case XKB_KEY_KP_Enter: /* fallthrough */
case XKB_KEY_Return:
- // TODO: Attempt password
+ if (attempt_password(&state->password)) {
+ exit(0);
+ }
break;
case XKB_KEY_BackSpace:
backspace(&state->password);