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