Compare commits
10 Commits
376cc5fcd4
...
9b164de0cf
Author | SHA1 | Date | |
---|---|---|---|
9b164de0cf | |||
bb9eae49c2 | |||
532a29816b | |||
|
96f0a0f9c6 | ||
|
fc6fbc98fb | ||
|
cca2436ba5 | ||
|
de0731de6a | ||
|
c2dcd40c34 | ||
|
b70d85ec14 | ||
|
f9ce3f193b |
BIN
.cache/clangd/index/background-image.c.A699A680CE5AF112.idx
Normal file
BIN
.cache/clangd/index/background-image.c.A699A680CE5AF112.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/background-image.h.4A580C6582E21C1F.idx
Normal file
BIN
.cache/clangd/index/background-image.h.4A580C6582E21C1F.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/cairo.c.E344436F853F63EB.idx
Normal file
BIN
.cache/clangd/index/cairo.c.E344436F853F63EB.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/cairo.h.342E0AF4FEE3727B.idx
Normal file
BIN
.cache/clangd/index/cairo.h.342E0AF4FEE3727B.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/comm.c.73286785A4D170DD.idx
Normal file
BIN
.cache/clangd/index/comm.c.73286785A4D170DD.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/comm.h.8C272A0376851762.idx
Normal file
BIN
.cache/clangd/index/comm.h.8C272A0376851762.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/log.c.05ED616AC36DC369.idx
Normal file
BIN
.cache/clangd/index/log.c.05ED616AC36DC369.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/log.h.163B53264720A899.idx
Normal file
BIN
.cache/clangd/index/log.h.163B53264720A899.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/loop.c.329BF8B535D2F2D3.idx
Normal file
BIN
.cache/clangd/index/loop.c.329BF8B535D2F2D3.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/loop.h.C9AD589E1F926DF5.idx
Normal file
BIN
.cache/clangd/index/loop.h.C9AD589E1F926DF5.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/main.c.AF20778E2016D176.idx
Normal file
BIN
.cache/clangd/index/main.c.AF20778E2016D176.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/pam.c.0E41B2E6C8458115.idx
Normal file
BIN
.cache/clangd/index/pam.c.0E41B2E6C8458115.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/password-buffer.c.C44E0D22E8158DF6.idx
Normal file
BIN
.cache/clangd/index/password-buffer.c.C44E0D22E8158DF6.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/password-buffer.h.0E433B83B52CDA60.idx
Normal file
BIN
.cache/clangd/index/password-buffer.h.0E433B83B52CDA60.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/password.c.4F88FCB3E461FF04.idx
Normal file
BIN
.cache/clangd/index/password.c.4F88FCB3E461FF04.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/pool-buffer.c.22AB6EED079D870E.idx
Normal file
BIN
.cache/clangd/index/pool-buffer.c.22AB6EED079D870E.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/pool-buffer.h.C14AF81A129F5DB4.idx
Normal file
BIN
.cache/clangd/index/pool-buffer.h.C14AF81A129F5DB4.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/render.c.13EB6E5145CB95B7.idx
Normal file
BIN
.cache/clangd/index/render.c.13EB6E5145CB95B7.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/seat.c.38F333AB815B9F70.idx
Normal file
BIN
.cache/clangd/index/seat.c.38F333AB815B9F70.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/seat.h.CD2AD8DC89290134.idx
Normal file
BIN
.cache/clangd/index/seat.h.CD2AD8DC89290134.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/swaylock.h.95A06467DB74471E.idx
Normal file
BIN
.cache/clangd/index/swaylock.h.95A06467DB74471E.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/unicode.c.413FCBB14E30CA31.idx
Normal file
BIN
.cache/clangd/index/unicode.c.413FCBB14E30CA31.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/unicode.h.536734CA745EA333.idx
Normal file
BIN
.cache/clangd/index/unicode.h.536734CA745EA333.idx
Normal file
Binary file not shown.
@ -31,8 +31,12 @@ cairo_surface_t *load_background_image(const char *path) {
|
|||||||
err->message);
|
err->message);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf);
|
// Correct for embedded image orientation; typical images are not
|
||||||
|
// rotated and will be handled efficiently
|
||||||
|
GdkPixbuf *oriented = gdk_pixbuf_apply_embedded_orientation(pixbuf);
|
||||||
g_object_unref(pixbuf);
|
g_object_unref(pixbuf);
|
||||||
|
image = gdk_cairo_image_surface_create_from_pixbuf(oriented);
|
||||||
|
g_object_unref(oriented);
|
||||||
#else
|
#else
|
||||||
image = cairo_image_surface_create_from_png(path);
|
image = cairo_image_surface_create_from_png(path);
|
||||||
#endif // HAVE_GDK_PIXBUF
|
#endif // HAVE_GDK_PIXBUF
|
||||||
|
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);
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
// Indicator state: status of authentication attempt
|
// Indicator state: status of authentication attempt
|
||||||
enum auth_state {
|
enum auth_state {
|
||||||
AUTH_STATE_IDLE, // nothing happening
|
AUTH_STATE_IDLE, // nothing happening
|
||||||
|
AUTH_STATE_IDLE_MSG, // showing a PAM message
|
||||||
AUTH_STATE_VALIDATING, // currently validating password
|
AUTH_STATE_VALIDATING, // currently validating password
|
||||||
AUTH_STATE_INVALID, // displaying message: password was wrong
|
AUTH_STATE_INVALID, // displaying message: password was wrong
|
||||||
};
|
};
|
||||||
@ -100,6 +101,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 {
|
||||||
@ -113,12 +115,13 @@ struct swaylock_surface {
|
|||||||
struct ext_session_lock_surface_v1 *ext_session_lock_surface_v1;
|
struct ext_session_lock_surface_v1 *ext_session_lock_surface_v1;
|
||||||
struct pool_buffer indicator_buffers[2];
|
struct pool_buffer indicator_buffers[2];
|
||||||
bool created;
|
bool created;
|
||||||
bool frame_pending, dirty;
|
bool dirty;
|
||||||
uint32_t width, height;
|
uint32_t width, height;
|
||||||
int32_t scale;
|
int32_t scale;
|
||||||
enum wl_output_subpixel subpixel;
|
enum wl_output_subpixel subpixel;
|
||||||
char *output_name;
|
char *output_name;
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
|
struct wl_callback *frame;
|
||||||
// Dimensions of last wl_buffer committed to background surface
|
// Dimensions of last wl_buffer committed to background surface
|
||||||
int last_buffer_width, last_buffer_height;
|
int last_buffer_width, last_buffer_height;
|
||||||
};
|
};
|
||||||
@ -133,12 +136,12 @@ struct swaylock_image {
|
|||||||
|
|
||||||
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);
|
||||||
void render_frame_background(struct swaylock_surface *surface);
|
|
||||||
void render_frame(struct swaylock_surface *surface);
|
void render(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);
|
||||||
void clear_password_buffer(struct swaylock_password *pw);
|
void clear_password_buffer(struct swaylock_password *pw);
|
||||||
void schedule_auth_idle(struct swaylock_state *state);
|
void schedule_auth_idle(struct swaylock_state *state);
|
||||||
|
void schedule_auth_idle_msg(struct swaylock_state *state);
|
||||||
|
|
||||||
void initialize_pw_backend(int argc, char **argv);
|
void initialize_pw_backend(int argc, char **argv);
|
||||||
void run_pw_backend_child(void);
|
void run_pw_backend_child(void);
|
||||||
|
71
main.c
71
main.c
@ -163,59 +163,19 @@ static void ext_session_lock_surface_v1_handle_configure(void *data,
|
|||||||
surface->width = width;
|
surface->width = width;
|
||||||
surface->height = height;
|
surface->height = height;
|
||||||
ext_session_lock_surface_v1_ack_configure(lock_surface, serial);
|
ext_session_lock_surface_v1_ack_configure(lock_surface, serial);
|
||||||
render_frame_background(surface);
|
surface->dirty = true;
|
||||||
render_frame(surface);
|
render(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct ext_session_lock_surface_v1_listener ext_session_lock_surface_v1_listener = {
|
static const struct ext_session_lock_surface_v1_listener ext_session_lock_surface_v1_listener = {
|
||||||
.configure = ext_session_lock_surface_v1_handle_configure,
|
.configure = ext_session_lock_surface_v1_handle_configure,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct wl_callback_listener surface_frame_listener;
|
|
||||||
|
|
||||||
static void surface_frame_handle_done(void *data, struct wl_callback *callback,
|
|
||||||
uint32_t time) {
|
|
||||||
struct swaylock_surface *surface = data;
|
|
||||||
|
|
||||||
wl_callback_destroy(callback);
|
|
||||||
surface->frame_pending = false;
|
|
||||||
|
|
||||||
if (surface->dirty) {
|
|
||||||
// Schedule a frame in case the surface is damaged again
|
|
||||||
struct wl_callback *callback = wl_surface_frame(surface->surface);
|
|
||||||
wl_callback_add_listener(callback, &surface_frame_listener, surface);
|
|
||||||
surface->frame_pending = true;
|
|
||||||
|
|
||||||
render_frame(surface);
|
|
||||||
surface->dirty = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wl_callback_listener surface_frame_listener = {
|
|
||||||
.done = surface_frame_handle_done,
|
|
||||||
};
|
|
||||||
|
|
||||||
void damage_surface(struct swaylock_surface *surface) {
|
|
||||||
if (surface->width == 0 || surface->height == 0) {
|
|
||||||
// Not yet configured
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
surface->dirty = true;
|
|
||||||
if (surface->frame_pending) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wl_callback *callback = wl_surface_frame(surface->surface);
|
|
||||||
wl_callback_add_listener(callback, &surface_frame_listener, surface);
|
|
||||||
surface->frame_pending = true;
|
|
||||||
wl_surface_commit(surface->surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
void damage_state(struct swaylock_state *state) {
|
void damage_state(struct swaylock_state *state) {
|
||||||
struct swaylock_surface *surface;
|
struct swaylock_surface *surface;
|
||||||
wl_list_for_each(surface, &state->surfaces, link) {
|
wl_list_for_each(surface, &state->surfaces, link) {
|
||||||
damage_surface(surface);
|
surface->dirty = true;
|
||||||
|
render(surface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,7 +186,8 @@ static void handle_wl_output_geometry(void *data, struct wl_output *wl_output,
|
|||||||
struct swaylock_surface *surface = data;
|
struct swaylock_surface *surface = data;
|
||||||
surface->subpixel = subpixel;
|
surface->subpixel = subpixel;
|
||||||
if (surface->state->run_display) {
|
if (surface->state->run_display) {
|
||||||
damage_surface(surface);
|
surface->dirty = true;
|
||||||
|
render(surface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,7 +208,8 @@ static void handle_wl_output_scale(void *data, struct wl_output *output,
|
|||||||
struct swaylock_surface *surface = data;
|
struct swaylock_surface *surface = data;
|
||||||
surface->scale = factor;
|
surface->scale = factor;
|
||||||
if (surface->state->run_display) {
|
if (surface->state->run_display) {
|
||||||
damage_surface(surface);
|
surface->dirty = true;
|
||||||
|
render(surface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1073,14 +1035,27 @@ 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 (mask & (POLLHUP | POLLERR)) {
|
||||||
|
swaylock_log(LOG_ERROR, "Password checking subprocess crashed; exiting.");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
} else if (reply.kind == REPLY_AUTH_ERR) {
|
||||||
state.auth_state = AUTH_STATE_INVALID;
|
state.auth_state = AUTH_STATE_INVALID;
|
||||||
schedule_auth_idle(&state);
|
schedule_auth_idle(&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_auth_idle(&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_auth_idle_msg(&state);
|
||||||
|
damage_state(&state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
project(
|
project(
|
||||||
'swaylock',
|
'swaylock',
|
||||||
'c',
|
'c',
|
||||||
version: '1.7.2',
|
version: '1.8.0',
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
meson_version: '>=0.59.0',
|
meson_version: '>=0.59.0',
|
||||||
default_options: [
|
default_options: [
|
||||||
|
54
pam.c
54
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:
|
||||||
|
{
|
||||||
|
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
|
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) {
|
if (pam_reply[i].resp == NULL) {
|
||||||
swaylock_log(LOG_ERROR, "Allocation failed");
|
swaylock_log(LOG_ERROR, "Allocation failed");
|
||||||
return PAM_ABORT;
|
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,9 +127,22 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
/* Unsuccessful requests may be queued after a successful one;
|
||||||
|
* do not process them. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pam_setcred(auth_handle, PAM_REFRESH_CRED);
|
pam_setcred(auth_handle, PAM_REFRESH_CRED);
|
||||||
|
17
password.c
17
password.c
@ -60,6 +60,13 @@ static void set_auth_idle(void *data) {
|
|||||||
damage_state(state);
|
damage_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_auth_idle_msg(void *data) {
|
||||||
|
struct swaylock_state *state = data;
|
||||||
|
state->auth_idle_timer = NULL;
|
||||||
|
state->auth_state = AUTH_STATE_IDLE_MSG;
|
||||||
|
damage_state(state);
|
||||||
|
}
|
||||||
|
|
||||||
static void schedule_input_idle(struct swaylock_state *state) {
|
static void schedule_input_idle(struct swaylock_state *state) {
|
||||||
if (state->input_idle_timer) {
|
if (state->input_idle_timer) {
|
||||||
loop_remove_timer(state->eventloop, state->input_idle_timer);
|
loop_remove_timer(state->eventloop, state->input_idle_timer);
|
||||||
@ -83,6 +90,14 @@ void schedule_auth_idle(struct swaylock_state *state) {
|
|||||||
state->eventloop, 3000, set_auth_idle, state);
|
state->eventloop, 3000, set_auth_idle, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void schedule_auth_idle_msg(struct swaylock_state *state) {
|
||||||
|
if (state->auth_idle_timer) {
|
||||||
|
loop_remove_timer(state->eventloop, state->auth_idle_timer);
|
||||||
|
}
|
||||||
|
state->auth_idle_timer = loop_add_timer(
|
||||||
|
state->eventloop, 3000, set_auth_idle_msg, state);
|
||||||
|
}
|
||||||
|
|
||||||
static void clear_password(void *data) {
|
static void clear_password(void *data) {
|
||||||
struct swaylock_state *state = data;
|
struct swaylock_state *state = data;
|
||||||
state->clear_password_timer = NULL;
|
state->clear_password_timer = NULL;
|
||||||
@ -146,7 +161,7 @@ void swaylock_handle_key(struct swaylock_state *state,
|
|||||||
state->input_state = INPUT_STATE_CLEAR;
|
state->input_state = INPUT_STATE_CLEAR;
|
||||||
cancel_password_clear(state);
|
cancel_password_clear(state);
|
||||||
} else {
|
} else {
|
||||||
if (backspace(&state->password)) {
|
if (backspace(&state->password) && state->password.len != 0) {
|
||||||
state->input_state = INPUT_STATE_BACKSPACE;
|
state->input_state = INPUT_STATE_BACKSPACE;
|
||||||
schedule_password_clear(state);
|
schedule_password_clear(state);
|
||||||
update_highlight(state);
|
update_highlight(state);
|
||||||
|
56
render.c
56
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"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
@ -33,7 +34,23 @@ static void set_color_for_state(cairo_t *cairo, struct swaylock_state *state,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void render_frame_background(struct swaylock_surface *surface) {
|
static void surface_frame_handle_done(void *data, struct wl_callback *callback,
|
||||||
|
uint32_t time) {
|
||||||
|
struct swaylock_surface *surface = data;
|
||||||
|
|
||||||
|
wl_callback_destroy(callback);
|
||||||
|
surface->frame = NULL;
|
||||||
|
|
||||||
|
render(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_callback_listener surface_frame_listener = {
|
||||||
|
.done = surface_frame_handle_done,
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool render_frame(struct swaylock_surface *surface);
|
||||||
|
|
||||||
|
void render(struct swaylock_surface *surface) {
|
||||||
struct swaylock_state *state = surface->state;
|
struct swaylock_state *state = surface->state;
|
||||||
|
|
||||||
int buffer_width = surface->width * surface->scale;
|
int buffer_width = surface->width * surface->scale;
|
||||||
@ -42,11 +59,17 @@ void render_frame_background(struct swaylock_surface *surface) {
|
|||||||
return; // not yet configured
|
return; // not yet configured
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_surface_set_buffer_scale(surface->surface, surface->scale);
|
if (!surface->dirty || surface->frame) {
|
||||||
|
// Nothing to do or frame already pending
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool need_destroy = false;
|
||||||
|
struct pool_buffer buffer;
|
||||||
|
|
||||||
if (buffer_width != surface->last_buffer_width ||
|
if (buffer_width != surface->last_buffer_width ||
|
||||||
buffer_height != surface->last_buffer_height) {
|
buffer_height != surface->last_buffer_height) {
|
||||||
struct pool_buffer buffer;
|
need_destroy = true;
|
||||||
if (!create_buffer(state->shm, &buffer, buffer_width, buffer_height,
|
if (!create_buffer(state->shm, &buffer, buffer_width, buffer_height,
|
||||||
WL_SHM_FORMAT_ARGB8888)) {
|
WL_SHM_FORMAT_ARGB8888)) {
|
||||||
swaylock_log(LOG_ERROR,
|
swaylock_log(LOG_ERROR,
|
||||||
@ -69,15 +92,23 @@ void render_frame_background(struct swaylock_surface *surface) {
|
|||||||
cairo_restore(cairo);
|
cairo_restore(cairo);
|
||||||
cairo_identity_matrix(cairo);
|
cairo_identity_matrix(cairo);
|
||||||
|
|
||||||
|
wl_surface_set_buffer_scale(surface->surface, surface->scale);
|
||||||
wl_surface_attach(surface->surface, buffer.buffer, 0, 0);
|
wl_surface_attach(surface->surface, buffer.buffer, 0, 0);
|
||||||
wl_surface_damage_buffer(surface->surface, 0, 0, INT32_MAX, INT32_MAX);
|
wl_surface_damage_buffer(surface->surface, 0, 0, INT32_MAX, INT32_MAX);
|
||||||
wl_surface_commit(surface->surface);
|
need_destroy = true;
|
||||||
destroy_buffer(&buffer);
|
|
||||||
|
|
||||||
surface->last_buffer_width = buffer_width;
|
surface->last_buffer_width = buffer_width;
|
||||||
surface->last_buffer_height = buffer_height;
|
surface->last_buffer_height = buffer_height;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
render_frame(surface);
|
||||||
|
surface->dirty = false;
|
||||||
|
surface->frame = wl_surface_frame(surface->surface);
|
||||||
|
wl_callback_add_listener(surface->frame, &surface_frame_listener, surface);
|
||||||
wl_surface_commit(surface->surface);
|
wl_surface_commit(surface->surface);
|
||||||
|
|
||||||
|
if (need_destroy) {
|
||||||
|
destroy_buffer(&buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +130,7 @@ static void configure_font_drawing(cairo_t *cairo, struct swaylock_state *state,
|
|||||||
cairo_font_options_destroy(fo);
|
cairo_font_options_destroy(fo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void render_frame(struct swaylock_surface *surface) {
|
static bool render_frame(struct swaylock_surface *surface) {
|
||||||
struct swaylock_state *state = surface->state;
|
struct swaylock_state *state = surface->state;
|
||||||
|
|
||||||
// First, compute the text that will be drawn, if any, since this
|
// First, compute the text that will be drawn, if any, since this
|
||||||
@ -107,7 +138,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);
|
||||||
|
|
||||||
bool draw_indicator = state->args.show_indicator &&
|
bool draw_indicator = state->args.show_indicator &&
|
||||||
(state->auth_state != AUTH_STATE_IDLE ||
|
(state->auth_state != AUTH_STATE_IDLE ||
|
||||||
@ -148,11 +180,12 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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;
|
||||||
@ -210,7 +243,8 @@ void render_frame(struct swaylock_surface *surface) {
|
|||||||
struct pool_buffer *buffer = get_next_buffer(state->shm,
|
struct pool_buffer *buffer = get_next_buffer(state->shm,
|
||||||
surface->indicator_buffers, buffer_width, buffer_height);
|
surface->indicator_buffers, buffer_width, buffer_height);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
return;
|
swaylock_log(LOG_ERROR, "No buffer");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the buffer
|
// Render the buffer
|
||||||
@ -352,5 +386,5 @@ void render_frame(struct swaylock_surface *surface) {
|
|||||||
wl_surface_damage_buffer(surface->child, 0, 0, INT32_MAX, INT32_MAX);
|
wl_surface_damage_buffer(surface->child, 0, 0, INT32_MAX, INT32_MAX);
|
||||||
wl_surface_commit(surface->child);
|
wl_surface_commit(surface->child);
|
||||||
|
|
||||||
wl_surface_commit(surface->surface);
|
return true;
|
||||||
}
|
}
|
||||||
|
60
shadow.c
60
shadow.c
@ -1,4 +1,5 @@
|
|||||||
#define _XOPEN_SOURCE // for crypt
|
#define _XOPEN_SOURCE // for crypt
|
||||||
|
#include <assert.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <shadow.h>
|
#include <shadow.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -14,16 +15,24 @@
|
|||||||
#include "password-buffer.h"
|
#include "password-buffer.h"
|
||||||
#include "swaylock.h"
|
#include "swaylock.h"
|
||||||
|
|
||||||
|
char *encpw = NULL;
|
||||||
|
|
||||||
void initialize_pw_backend(int argc, char **argv) {
|
void initialize_pw_backend(int argc, char **argv) {
|
||||||
if (geteuid() != 0) {
|
/* This code runs as root */
|
||||||
swaylock_log(LOG_ERROR,
|
struct passwd *pwent = getpwuid(getuid());
|
||||||
"swaylock needs to be setuid to read /etc/shadow");
|
if (!pwent) {
|
||||||
|
swaylock_log_errno(LOG_ERROR, "failed to getpwuid");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
encpw = pwent->pw_passwd;
|
||||||
if (!spawn_comm_child()) {
|
if (strcmp(encpw, "x") == 0) {
|
||||||
|
struct spwd *swent = getspnam(pwent->pw_name);
|
||||||
|
if (!swent) {
|
||||||
|
swaylock_log_errno(LOG_ERROR, "failed to getspnam");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
encpw = swent->sp_pwdp;
|
||||||
|
}
|
||||||
|
|
||||||
if (setgid(getgid()) != 0) {
|
if (setgid(getgid()) != 0) {
|
||||||
swaylock_log_errno(LOG_ERROR, "Unable to drop root");
|
swaylock_log_errno(LOG_ERROR, "Unable to drop root");
|
||||||
@ -38,40 +47,21 @@ void initialize_pw_backend(int argc, char **argv) {
|
|||||||
"able to restore it after setuid/setgid)");
|
"able to restore it after setuid/setgid)");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void run_pw_backend_child(void) {
|
|
||||||
/* This code runs as root */
|
|
||||||
struct passwd *pwent = getpwuid(getuid());
|
|
||||||
if (!pwent) {
|
|
||||||
swaylock_log_errno(LOG_ERROR, "failed to getpwuid");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
char *encpw = pwent->pw_passwd;
|
|
||||||
if (strcmp(encpw, "x") == 0) {
|
|
||||||
struct spwd *swent = getspnam(pwent->pw_name);
|
|
||||||
if (!swent) {
|
|
||||||
swaylock_log_errno(LOG_ERROR, "failed to getspnam");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
encpw = swent->sp_pwdp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We don't need any additional logging here because the parent process will
|
|
||||||
* also fail here and will handle logging for us. */
|
|
||||||
if (setgid(getgid()) != 0) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
if (setuid(getuid()) != 0) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
if (setuid(0) != -1) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This code does not run as root */
|
/* This code does not run as root */
|
||||||
swaylock_log(LOG_DEBUG, "Prepared to authorize user %s", pwent->pw_name);
|
swaylock_log(LOG_DEBUG, "Prepared to authorize user %s", pwent->pw_name);
|
||||||
|
|
||||||
|
if (!spawn_comm_child()) {
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buffer is only used by the child */
|
||||||
|
clear_buffer(encpw, strlen(encpw));
|
||||||
|
encpw = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_pw_backend_child(void) {
|
||||||
|
assert(encpw != NULL);
|
||||||
while (1) {
|
while (1) {
|
||||||
char *buf;
|
char *buf;
|
||||||
ssize_t size = read_comm_request(&buf);
|
ssize_t size = read_comm_request(&buf);
|
||||||
|
Loading…
Reference in New Issue
Block a user