Show PAM messages
This commit is contained in:
parent
bd2dfec9ae
commit
532a29816b
10
comm.c
10
comm.c
@ -38,8 +38,8 @@ ssize_t read_comm_request(char **buf_ptr) {
|
||||
return size;
|
||||
}
|
||||
|
||||
bool write_comm_reply(bool success) {
|
||||
if (write(comm[1][1], &success, sizeof(success)) != sizeof(success)) {
|
||||
bool write_comm_reply(struct comm_reply reply) {
|
||||
if (write(comm[1][1], &reply, sizeof(reply)) != sizeof(reply)) {
|
||||
swaylock_log_errno(LOG_ERROR, "failed to write pw check result");
|
||||
return false;
|
||||
}
|
||||
@ -95,11 +95,11 @@ out:
|
||||
return result;
|
||||
}
|
||||
|
||||
bool read_comm_reply(void) {
|
||||
bool result = false;
|
||||
struct comm_reply read_comm_reply(void) {
|
||||
struct comm_reply result;
|
||||
if (read(comm[1][0], &result, sizeof(result)) != sizeof(result)) {
|
||||
swaylock_log_errno(LOG_ERROR, "Failed to read pw result");
|
||||
result = false;
|
||||
result.kind = REPLY_AUTH_ERR;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -5,13 +5,25 @@
|
||||
|
||||
struct swaylock_password;
|
||||
|
||||
enum conn_reply_kind {
|
||||
REPLY_SUCCESS,
|
||||
REPLY_AUTH_ERR,
|
||||
REPLY_CONTINUE,
|
||||
REPLY_MSG,
|
||||
};
|
||||
|
||||
struct comm_reply {
|
||||
enum conn_reply_kind kind;
|
||||
char pam_msg[256];
|
||||
};
|
||||
|
||||
bool spawn_comm_child(void);
|
||||
ssize_t read_comm_request(char **buf_ptr);
|
||||
bool write_comm_reply(bool success);
|
||||
bool write_comm_reply(struct comm_reply reply);
|
||||
// Requests the provided password to be checked. The password is always cleared
|
||||
// when the function returns.
|
||||
bool write_comm_request(struct swaylock_password *pw);
|
||||
bool read_comm_reply(void);
|
||||
struct comm_reply read_comm_reply(void);
|
||||
// FD to poll for password authentication replies.
|
||||
int get_comm_reply_fd(void);
|
||||
|
||||
|
@ -17,6 +17,7 @@ enum auth_state {
|
||||
AUTH_STATE_BACKSPACE,
|
||||
AUTH_STATE_VALIDATING,
|
||||
AUTH_STATE_INVALID,
|
||||
AUTH_STATE_IDLE_MSG,
|
||||
};
|
||||
|
||||
struct swaylock_colorset {
|
||||
@ -93,6 +94,7 @@ struct swaylock_state {
|
||||
bool run_display, locked;
|
||||
struct ext_session_lock_manager_v1 *ext_session_lock_manager_v1;
|
||||
struct ext_session_lock_v1 *ext_session_lock_v1;
|
||||
char pam_msg[256];
|
||||
};
|
||||
|
||||
struct swaylock_surface {
|
||||
|
18
main.c
18
main.c
@ -1117,14 +1117,28 @@ static void display_in(int fd, short mask, void *data) {
|
||||
}
|
||||
|
||||
static void comm_in(int fd, short mask, void *data) {
|
||||
if (read_comm_reply()) {
|
||||
struct comm_reply reply = read_comm_reply();
|
||||
if (reply.kind == REPLY_SUCCESS) {
|
||||
// Authentication succeeded
|
||||
state.run_display = false;
|
||||
} else {
|
||||
} else if (reply.kind == REPLY_AUTH_ERR) {
|
||||
state.auth_state = AUTH_STATE_INVALID;
|
||||
schedule_indicator_clear(&state);
|
||||
++state.failed_attempts;
|
||||
damage_state(&state);
|
||||
} else if (reply.kind == REPLY_CONTINUE) {
|
||||
state.auth_state = AUTH_STATE_IDLE;
|
||||
schedule_indicator_clear(&state);
|
||||
damage_state(&state);
|
||||
} else if (reply.kind == REPLY_MSG) {
|
||||
state.auth_state = AUTH_STATE_IDLE_MSG;
|
||||
memcpy(&state.pam_msg[0], &reply.pam_msg[0], 256);
|
||||
schedule_indicator_clear(&state);
|
||||
damage_state(&state);
|
||||
}
|
||||
struct swaylock_surface *surface;
|
||||
wl_list_for_each(surface, &state.surfaces, link) {
|
||||
render_frame(surface);
|
||||
}
|
||||
}
|
||||
|
||||
|
48
pam.c
48
pam.c
@ -1,3 +1,4 @@
|
||||
#include <security/_pam_types.h>
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <pwd.h>
|
||||
#include <security/pam_appl.h>
|
||||
@ -11,6 +12,7 @@
|
||||
#include "swaylock.h"
|
||||
|
||||
static char *pw_buf = NULL;
|
||||
static bool prompt_send_response = false;
|
||||
|
||||
void initialize_pw_backend(int argc, char **argv) {
|
||||
if (getuid() != geteuid() || getgid() != getegid()) {
|
||||
@ -38,14 +40,41 @@ static int handle_conversation(int num_msg, const struct pam_message **msg,
|
||||
switch (msg[i]->msg_style) {
|
||||
case PAM_PROMPT_ECHO_OFF:
|
||||
case PAM_PROMPT_ECHO_ON:
|
||||
{
|
||||
if (prompt_send_response) {
|
||||
prompt_send_response = false;
|
||||
struct comm_reply reply;
|
||||
reply.kind = REPLY_CONTINUE;
|
||||
if (!write_comm_reply(reply)) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
ssize_t size = read_comm_request(&pw_buf);
|
||||
if (size < 0) {
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (size == 0) {
|
||||
pam_reply[i].resp = NULL;
|
||||
} else {
|
||||
pam_reply[i].resp = strdup(pw_buf); // PAM clears and frees this
|
||||
password_buffer_destroy(pw_buf, size);
|
||||
pw_buf = NULL;
|
||||
if (pam_reply[i].resp == NULL) {
|
||||
swaylock_log(LOG_ERROR, "Allocation failed");
|
||||
return PAM_ABORT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PAM_ERROR_MSG:
|
||||
case PAM_TEXT_INFO:
|
||||
swaylock_log(LOG_DEBUG, "PAM message %s", msg[i]->msg);
|
||||
prompt_send_response = false;
|
||||
struct comm_reply reply;
|
||||
reply.kind = REPLY_MSG;
|
||||
strncpy(&reply.pam_msg[0], msg[i]->msg, 255);
|
||||
if (!write_comm_reply(reply)) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -89,16 +118,8 @@ void run_pw_backend_child(void) {
|
||||
|
||||
int pam_status = PAM_SUCCESS;
|
||||
while (1) {
|
||||
ssize_t size = read_comm_request(&pw_buf);
|
||||
if (size < 0) {
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (size == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
int pam_status = pam_authenticate(auth_handle, 0);
|
||||
password_buffer_destroy(pw_buf, size);
|
||||
pw_buf = NULL;
|
||||
prompt_send_response = false;
|
||||
|
||||
bool success = pam_status == PAM_SUCCESS;
|
||||
if (!success) {
|
||||
@ -106,7 +127,14 @@ void run_pw_backend_child(void) {
|
||||
get_pam_auth_error(pam_status));
|
||||
}
|
||||
|
||||
if (!write_comm_reply(success)) {
|
||||
struct comm_reply reply;
|
||||
if (success) {
|
||||
reply.kind = REPLY_SUCCESS;
|
||||
} else {
|
||||
reply.kind = REPLY_AUTH_ERR;
|
||||
}
|
||||
|
||||
if (!write_comm_reply(reply)) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
9
render.c
9
render.c
@ -3,6 +3,7 @@
|
||||
#include <wayland-client.h>
|
||||
#include "cairo.h"
|
||||
#include "background-image.h"
|
||||
#include "log.h"
|
||||
#include "swaylock.h"
|
||||
|
||||
#define M_PI 3.14159265358979323846
|
||||
@ -94,7 +95,8 @@ void render_frame(struct swaylock_surface *surface) {
|
||||
|
||||
char attempts[4]; // like i3lock: count no more than 999
|
||||
char *text = NULL;
|
||||
const char *layout_text = NULL;
|
||||
const char *layout_text = &state->pam_msg[0];
|
||||
swaylock_log(LOG_DEBUG, "RNDR pm %s", layout_text);
|
||||
|
||||
if (state->args.show_indicator) {
|
||||
switch (state->auth_state) {
|
||||
@ -135,7 +137,7 @@ void render_frame(struct swaylock_surface *surface) {
|
||||
++curr_layout;
|
||||
}
|
||||
// will handle invalid index if none are active
|
||||
layout_text = xkb_keymap_layout_get_name(state->xkb.keymap, curr_layout);
|
||||
// layout_text = xkb_keymap_layout_get_name(state->xkb.keymap, curr_layout);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -143,6 +145,7 @@ void render_frame(struct swaylock_surface *surface) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Compute the size of the buffer needed
|
||||
int arc_radius = state->args.radius * surface->scale;
|
||||
int arc_thickness = state->args.thickness * surface->scale;
|
||||
@ -219,7 +222,7 @@ void render_frame(struct swaylock_surface *surface) {
|
||||
float type_indicator_border_thickness =
|
||||
TYPE_INDICATOR_BORDER_THICKNESS * surface->scale;
|
||||
|
||||
if (state->args.show_indicator && (state->auth_state != AUTH_STATE_IDLE ||
|
||||
if (state->args.show_indicator && ((state->auth_state != AUTH_STATE_IDLE) ||
|
||||
state->args.indicator_idle_visible)) {
|
||||
// Fill inner circle
|
||||
cairo_set_line_width(cairo, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user