Check password without blocking
This commit is contained in:
parent
28c0abbc57
commit
c77f0eb4ed
33
comm.c
33
comm.c
@ -6,7 +6,7 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "swaylock.h"
|
#include "swaylock.h"
|
||||||
|
|
||||||
static int comm[2][2];
|
static int comm[2][2] = {{-1, -1}, {-1, -1}};
|
||||||
|
|
||||||
ssize_t read_comm_request(char **buf_ptr) {
|
ssize_t read_comm_request(char **buf_ptr) {
|
||||||
size_t size;
|
size_t size;
|
||||||
@ -69,28 +69,41 @@ bool spawn_comm_child(void) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool attempt_password(struct swaylock_password *pw) {
|
bool write_comm_request(struct swaylock_password *pw) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
size_t len = pw->len + 1;
|
size_t len = pw->len + 1;
|
||||||
size_t offs = 0;
|
size_t offs = 0;
|
||||||
if (write(comm[0][1], &len, sizeof(len)) < 0) {
|
if (write(comm[0][1], &len, sizeof(len)) < 0) {
|
||||||
swaylock_log_errno(LOG_ERROR, "Failed to request pw check");
|
swaylock_log_errno(LOG_ERROR, "Failed to request pw check");
|
||||||
goto ret;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ssize_t amt = write(comm[0][1], &pw->buffer[offs], len - offs);
|
ssize_t amt = write(comm[0][1], &pw->buffer[offs], len - offs);
|
||||||
if (amt < 0) {
|
if (amt < 0) {
|
||||||
swaylock_log_errno(LOG_ERROR, "Failed to write pw buffer");
|
swaylock_log_errno(LOG_ERROR, "Failed to write pw buffer");
|
||||||
goto ret;
|
goto out;
|
||||||
}
|
}
|
||||||
offs += amt;
|
offs += amt;
|
||||||
} while (offs < len);
|
} while (offs < len);
|
||||||
if (read(comm[1][0], &result, sizeof(result)) != sizeof(result)) {
|
|
||||||
swaylock_log_errno(LOG_ERROR, "Failed to read pw result");
|
result = true;
|
||||||
goto ret;
|
|
||||||
}
|
out:
|
||||||
swaylock_log(LOG_DEBUG, "pw result: %d", result);
|
|
||||||
ret:
|
|
||||||
clear_password_buffer(pw);
|
clear_password_buffer(pw);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool read_comm_reply(void) {
|
||||||
|
bool result = false;
|
||||||
|
if (read(comm[1][0], &result, sizeof(result)) != sizeof(result)) {
|
||||||
|
swaylock_log_errno(LOG_ERROR, "Failed to read pw result");
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_comm_reply_fd(void) {
|
||||||
|
return comm[1][0];
|
||||||
|
}
|
||||||
|
@ -1,8 +1,18 @@
|
|||||||
#ifndef _SWAYLOCK_COMM_H
|
#ifndef _SWAYLOCK_COMM_H
|
||||||
#define _SWAYLOCK_COMM_H
|
#define _SWAYLOCK_COMM_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
struct swaylock_password;
|
||||||
|
|
||||||
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(bool success);
|
||||||
|
// 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);
|
||||||
|
// FD to poll for password authentication replies.
|
||||||
|
int get_comm_reply_fd(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -62,7 +62,6 @@ struct swaylock_state {
|
|||||||
struct loop *eventloop;
|
struct loop *eventloop;
|
||||||
struct loop_timer *clear_indicator_timer; // clears the indicator
|
struct loop_timer *clear_indicator_timer; // clears the indicator
|
||||||
struct loop_timer *clear_password_timer; // clears the password buffer
|
struct loop_timer *clear_password_timer; // clears the password buffer
|
||||||
struct loop_timer *verify_password_timer;
|
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
struct wl_compositor *compositor;
|
struct wl_compositor *compositor;
|
||||||
struct zwlr_layer_shell_v1 *layer_shell;
|
struct zwlr_layer_shell_v1 *layer_shell;
|
||||||
@ -110,8 +109,8 @@ void render_frame(struct swaylock_surface *surface);
|
|||||||
void render_frames(struct swaylock_state *state);
|
void render_frames(struct swaylock_state *state);
|
||||||
void damage_surface(struct swaylock_surface *surface);
|
void damage_surface(struct swaylock_surface *surface);
|
||||||
void damage_state(struct swaylock_state *state);
|
void damage_state(struct swaylock_state *state);
|
||||||
bool attempt_password(struct swaylock_password *pw);
|
|
||||||
void clear_password_buffer(struct swaylock_password *pw);
|
void clear_password_buffer(struct swaylock_password *pw);
|
||||||
|
void schedule_indicator_clear(struct swaylock_state *state);
|
||||||
|
|
||||||
void initialize_pw_backend(void);
|
void initialize_pw_backend(void);
|
||||||
void run_pw_backend_child(void);
|
void run_pw_backend_child(void);
|
||||||
|
14
main.c
14
main.c
@ -17,6 +17,7 @@
|
|||||||
#include <wordexp.h>
|
#include <wordexp.h>
|
||||||
#include "background-image.h"
|
#include "background-image.h"
|
||||||
#include "cairo.h"
|
#include "cairo.h"
|
||||||
|
#include "comm.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "loop.h"
|
#include "loop.h"
|
||||||
#include "pool-buffer.h"
|
#include "pool-buffer.h"
|
||||||
@ -956,6 +957,17 @@ static void display_in(int fd, short mask, void *data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void comm_in(int fd, short mask, void *data) {
|
||||||
|
if (read_comm_reply()) {
|
||||||
|
// Authentication succeeded
|
||||||
|
state.run_display = false;
|
||||||
|
} else {
|
||||||
|
state.auth_state = AUTH_STATE_INVALID;
|
||||||
|
schedule_indicator_clear(&state);
|
||||||
|
damage_state(&state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
swaylock_log_init(LOG_ERROR);
|
swaylock_log_init(LOG_ERROR);
|
||||||
initialize_pw_backend();
|
initialize_pw_backend();
|
||||||
@ -1081,6 +1093,8 @@ int main(int argc, char **argv) {
|
|||||||
loop_add_fd(state.eventloop, wl_display_get_fd(state.display), POLLIN,
|
loop_add_fd(state.eventloop, wl_display_get_fd(state.display), POLLIN,
|
||||||
display_in, NULL);
|
display_in, NULL);
|
||||||
|
|
||||||
|
loop_add_fd(state.eventloop, get_comm_reply_fd(), POLLIN, comm_in, NULL);
|
||||||
|
|
||||||
state.run_display = true;
|
state.run_display = true;
|
||||||
while (state.run_display) {
|
while (state.run_display) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
48
password.c
48
password.c
@ -5,6 +5,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#include "comm.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "loop.h"
|
#include "loop.h"
|
||||||
#include "seat.h"
|
#include "seat.h"
|
||||||
@ -51,7 +52,7 @@ static void clear_indicator(void *data) {
|
|||||||
damage_state(state);
|
damage_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void schedule_indicator_clear(struct swaylock_state *state) {
|
void schedule_indicator_clear(struct swaylock_state *state) {
|
||||||
if (state->clear_indicator_timer) {
|
if (state->clear_indicator_timer) {
|
||||||
loop_remove_timer(state->eventloop, state->clear_indicator_timer);
|
loop_remove_timer(state->eventloop, state->clear_indicator_timer);
|
||||||
}
|
}
|
||||||
@ -76,57 +77,28 @@ static void schedule_password_clear(struct swaylock_state *state) {
|
|||||||
state->eventloop, 10000, clear_password, state);
|
state->eventloop, 10000, clear_password, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_preverify_timeout(void *data) {
|
|
||||||
struct swaylock_state *state = data;
|
|
||||||
state->verify_password_timer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void submit_password(struct swaylock_state *state) {
|
static void submit_password(struct swaylock_state *state) {
|
||||||
if (state->args.ignore_empty && state->password.len == 0) {
|
if (state->args.ignore_empty && state->password.len == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->auth_state = AUTH_STATE_VALIDATING;
|
state->auth_state = AUTH_STATE_VALIDATING;
|
||||||
damage_state(state);
|
|
||||||
|
|
||||||
// We generally want to wait until all surfaces are showing the
|
if (!write_comm_request(&state->password)) {
|
||||||
// "verifying" state before we go and verify the password, because
|
state->auth_state = AUTH_STATE_INVALID;
|
||||||
// verifying it is a blocking operation. However, if the surface is on
|
schedule_indicator_clear(state);
|
||||||
// an output with DPMS off then it won't update, so we set a timer.
|
|
||||||
state->verify_password_timer = loop_add_timer(
|
|
||||||
state->eventloop, 50, handle_preverify_timeout, state);
|
|
||||||
|
|
||||||
while (state->run_display && state->verify_password_timer) {
|
|
||||||
errno = 0;
|
|
||||||
if (wl_display_flush(state->display) == -1 && errno != EAGAIN) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
loop_poll(state->eventloop);
|
|
||||||
|
|
||||||
bool ok = 1;
|
|
||||||
struct swaylock_surface *surface;
|
|
||||||
wl_list_for_each(surface, &state->surfaces, link) {
|
|
||||||
if (surface->dirty) {
|
|
||||||
ok = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ok) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
wl_display_flush(state->display);
|
|
||||||
|
|
||||||
if (attempt_password(&state->password)) {
|
|
||||||
state->run_display = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
state->auth_state = AUTH_STATE_INVALID;
|
|
||||||
damage_state(state);
|
damage_state(state);
|
||||||
schedule_indicator_clear(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void swaylock_handle_key(struct swaylock_state *state,
|
void swaylock_handle_key(struct swaylock_state *state,
|
||||||
xkb_keysym_t keysym, uint32_t codepoint) {
|
xkb_keysym_t keysym, uint32_t codepoint) {
|
||||||
|
// Ignore input events if validating
|
||||||
|
if (state->auth_state == AUTH_STATE_VALIDATING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (keysym) {
|
switch (keysym) {
|
||||||
case XKB_KEY_KP_Enter: /* fallthrough */
|
case XKB_KEY_KP_Enter: /* fallthrough */
|
||||||
case XKB_KEY_Return:
|
case XKB_KEY_Return:
|
||||||
|
Loading…
Reference in New Issue
Block a user