Compare commits
No commits in common. "9b164de0cf452002269e49329ac2520778a79170" and "376cc5fcd486a3065b4c04ee4a1573606fb09038" have entirely different histories.
9b164de0cf
...
376cc5fcd4
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -31,12 +31,8 @@ cairo_surface_t *load_background_image(const char *path) {
|
|||||||
err->message);
|
err->message);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// Correct for embedded image orientation; typical images are not
|
image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf);
|
||||||
// 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(struct comm_reply reply) {
|
bool write_comm_reply(bool success) {
|
||||||
if (write(comm[1][1], &reply, sizeof(reply)) != sizeof(reply)) {
|
if (write(comm[1][1], &success, sizeof(success)) != sizeof(success)) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct comm_reply read_comm_reply(void) {
|
bool read_comm_reply(void) {
|
||||||
struct comm_reply result;
|
bool result = false;
|
||||||
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.kind = REPLY_AUTH_ERR;
|
result = false;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -5,25 +5,13 @@
|
|||||||
|
|
||||||
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(struct comm_reply reply);
|
bool write_comm_reply(bool success);
|
||||||
// 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);
|
||||||
struct comm_reply read_comm_reply(void);
|
bool 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,7 +11,6 @@
|
|||||||
// 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
|
||||||
};
|
};
|
||||||
@ -101,7 +100,6 @@ 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 {
|
||||||
@ -115,13 +113,12 @@ 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 dirty;
|
bool frame_pending, 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;
|
||||||
};
|
};
|
||||||
@ -136,12 +133,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(struct swaylock_surface *surface);
|
void render_frame(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,19 +163,59 @@ 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);
|
||||||
surface->dirty = true;
|
render_frame_background(surface);
|
||||||
render(surface);
|
render_frame(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) {
|
||||||
surface->dirty = true;
|
damage_surface(surface);
|
||||||
render(surface);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,8 +226,7 @@ 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) {
|
||||||
surface->dirty = true;
|
damage_surface(surface);
|
||||||
render(surface);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,8 +247,7 @@ 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) {
|
||||||
surface->dirty = true;
|
damage_surface(surface);
|
||||||
render(surface);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1035,27 +1073,14 @@ 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) {
|
||||||
struct comm_reply reply = read_comm_reply();
|
if (read_comm_reply()) {
|
||||||
if (reply.kind == REPLY_SUCCESS) {
|
|
||||||
// Authentication succeeded
|
// Authentication succeeded
|
||||||
state.run_display = false;
|
state.run_display = false;
|
||||||
} else if (mask & (POLLHUP | POLLERR)) {
|
} else {
|
||||||
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.8.0',
|
version: '1.7.2',
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
meson_version: '>=0.59.0',
|
meson_version: '>=0.59.0',
|
||||||
default_options: [
|
default_options: [
|
||||||
|
62
pam.c
62
pam.c
@ -1,4 +1,3 @@
|
|||||||
#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>
|
||||||
@ -12,7 +11,6 @@
|
|||||||
#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()) {
|
||||||
@ -40,41 +38,14 @@ 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 (prompt_send_response) {
|
if (pam_reply[i].resp == NULL) {
|
||||||
prompt_send_response = false;
|
swaylock_log(LOG_ERROR, "Allocation failed");
|
||||||
struct comm_reply reply;
|
return PAM_ABORT;
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,8 +89,16 @@ 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);
|
||||||
prompt_send_response = false;
|
password_buffer_destroy(pw_buf, size);
|
||||||
|
pw_buf = NULL;
|
||||||
|
|
||||||
bool success = pam_status == PAM_SUCCESS;
|
bool success = pam_status == PAM_SUCCESS;
|
||||||
if (!success) {
|
if (!success) {
|
||||||
@ -127,22 +106,9 @@ void run_pw_backend_child(void) {
|
|||||||
get_pam_auth_error(pam_status));
|
get_pam_auth_error(pam_status));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct comm_reply reply;
|
if (!write_comm_reply(success)) {
|
||||||
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,13 +60,6 @@ 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);
|
||||||
@ -90,14 +83,6 @@ 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;
|
||||||
@ -161,7 +146,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) && state->password.len != 0) {
|
if (backspace(&state->password)) {
|
||||||
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);
|
||||||
|
58
render.c
58
render.c
@ -3,7 +3,6 @@
|
|||||||
#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"
|
||||||
|
|
||||||
@ -34,23 +33,7 @@ static void set_color_for_state(cairo_t *cairo, struct swaylock_state *state,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void surface_frame_handle_done(void *data, struct wl_callback *callback,
|
void render_frame_background(struct swaylock_surface *surface) {
|
||||||
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;
|
||||||
@ -59,17 +42,11 @@ void render(struct swaylock_surface *surface) {
|
|||||||
return; // not yet configured
|
return; // not yet configured
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!surface->dirty || surface->frame) {
|
wl_surface_set_buffer_scale(surface->surface, surface->scale);
|
||||||
// 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) {
|
||||||
need_destroy = true;
|
struct pool_buffer buffer;
|
||||||
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,
|
||||||
@ -92,23 +69,15 @@ void render(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);
|
||||||
need_destroy = true;
|
wl_surface_commit(surface->surface);
|
||||||
|
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 {
|
||||||
|
wl_surface_commit(surface->surface);
|
||||||
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);
|
|
||||||
|
|
||||||
if (need_destroy) {
|
|
||||||
destroy_buffer(&buffer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +99,7 @@ static void configure_font_drawing(cairo_t *cairo, struct swaylock_state *state,
|
|||||||
cairo_font_options_destroy(fo);
|
cairo_font_options_destroy(fo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool render_frame(struct swaylock_surface *surface) {
|
void 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
|
||||||
@ -138,8 +107,7 @@ static bool 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 = &state->pam_msg[0];
|
const char *layout_text = NULL;
|
||||||
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 ||
|
||||||
@ -180,12 +148,11 @@ static bool 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;
|
||||||
@ -243,8 +210,7 @@ static bool 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) {
|
||||||
swaylock_log(LOG_ERROR, "No buffer");
|
return;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the buffer
|
// Render the buffer
|
||||||
@ -386,5 +352,5 @@ static bool 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);
|
||||||
|
|
||||||
return true;
|
wl_surface_commit(surface->surface);
|
||||||
}
|
}
|
||||||
|
62
shadow.c
62
shadow.c
@ -1,5 +1,4 @@
|
|||||||
#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>
|
||||||
@ -15,23 +14,15 @@
|
|||||||
#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) {
|
||||||
/* This code runs as root */
|
if (geteuid() != 0) {
|
||||||
struct passwd *pwent = getpwuid(getuid());
|
swaylock_log(LOG_ERROR,
|
||||||
if (!pwent) {
|
"swaylock needs to be setuid to read /etc/shadow");
|
||||||
swaylock_log_errno(LOG_ERROR, "failed to getpwuid");
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
encpw = pwent->pw_passwd;
|
|
||||||
if (strcmp(encpw, "x") == 0) {
|
if (!spawn_comm_child()) {
|
||||||
struct spwd *swent = getspnam(pwent->pw_name);
|
exit(EXIT_FAILURE);
|
||||||
if (!swent) {
|
|
||||||
swaylock_log_errno(LOG_ERROR, "failed to getspnam");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
encpw = swent->sp_pwdp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setgid(getgid()) != 0) {
|
if (setgid(getgid()) != 0) {
|
||||||
@ -47,21 +38,40 @@ 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