mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Add support for building swaylock without PAM
This involves setuid'ing swaylock, which then forks and drops perms on the parent process. The child process remains root and listens on a pipe for requests to validate passwords against /etc/shadow.
This commit is contained in:
		
							parent
							
								
									58af001517
								
							
						
					
					
						commit
						c977349120
					
				
					 7 changed files with 233 additions and 76 deletions
				
			
		| 
						 | 
					@ -101,5 +101,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);
 | 
				
			||||||
 | 
					void initialize_pw_backend(void);
 | 
				
			||||||
 | 
					bool attempt_password(struct swaylock_password *pw);
 | 
				
			||||||
 | 
					void clear_password_buffer(struct swaylock_password *pw);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										10
									
								
								meson.build
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								meson.build
									
										
									
									
									
								
							| 
						 | 
					@ -74,6 +74,11 @@ if elogind.found()
 | 
				
			||||||
	swayidle_deps += elogind
 | 
						swayidle_deps += elogind
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if not systemd.found() and not elogind.found()
 | 
				
			||||||
 | 
					    warning('The sway binary must be setuid when compiled without (e)logind')
 | 
				
			||||||
 | 
					    warning('You must do this manually post-install: chmod a+s /path/to/sway')
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
scdoc = find_program('scdoc', required: false)
 | 
					scdoc = find_program('scdoc', required: false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if scdoc.found()
 | 
					if scdoc.found()
 | 
				
			||||||
| 
						 | 
					@ -139,10 +144,7 @@ subdir('swaybg')
 | 
				
			||||||
subdir('swaybar')
 | 
					subdir('swaybar')
 | 
				
			||||||
subdir('swayidle')
 | 
					subdir('swayidle')
 | 
				
			||||||
subdir('swaynag')
 | 
					subdir('swaynag')
 | 
				
			||||||
 | 
					subdir('swaylock')
 | 
				
			||||||
if libpam.found()
 | 
					 | 
				
			||||||
    subdir('swaylock')
 | 
					 | 
				
			||||||
endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
config = configuration_data()
 | 
					config = configuration_data()
 | 
				
			||||||
config.set('sysconfdir', join_paths(prefix, sysconfdir))
 | 
					config.set('sysconfdir', join_paths(prefix, sysconfdir))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -845,6 +845,9 @@ static int load_config(char *path, struct swaylock_state *state,
 | 
				
			||||||
static struct swaylock_state state;
 | 
					static struct swaylock_state state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char **argv) {
 | 
					int main(int argc, char **argv) {
 | 
				
			||||||
 | 
						wlr_log_init(WLR_DEBUG, NULL);
 | 
				
			||||||
 | 
						initialize_pw_backend();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	enum line_mode line_mode = LM_LINE;
 | 
						enum line_mode line_mode = LM_LINE;
 | 
				
			||||||
	state.args = (struct swaylock_args){
 | 
						state.args = (struct swaylock_args){
 | 
				
			||||||
		.mode = BACKGROUND_MODE_SOLID_COLOR,
 | 
							.mode = BACKGROUND_MODE_SOLID_COLOR,
 | 
				
			||||||
| 
						 | 
					@ -857,8 +860,6 @@ int main(int argc, char **argv) {
 | 
				
			||||||
	wl_list_init(&state.images);
 | 
						wl_list_init(&state.images);
 | 
				
			||||||
	set_default_colors(&state.args.colors);
 | 
						set_default_colors(&state.args.colors);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wlr_log_init(WLR_DEBUG, NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	char *config_path = NULL;
 | 
						char *config_path = NULL;
 | 
				
			||||||
	int result = parse_options(argc, argv, NULL, NULL, &config_path);
 | 
						int result = parse_options(argc, argv, NULL, NULL, &config_path);
 | 
				
			||||||
	if (result != 0) {
 | 
						if (result != 0) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,25 +1,37 @@
 | 
				
			||||||
sysconfdir = get_option('sysconfdir')
 | 
					sysconfdir = get_option('sysconfdir')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
executable(
 | 
					dependencies = [
 | 
				
			||||||
	'swaylock', [
 | 
					    cairo,
 | 
				
			||||||
		'main.c',
 | 
					    client_protos,
 | 
				
			||||||
		'password.c',
 | 
					    gdk_pixbuf,
 | 
				
			||||||
		'render.c',
 | 
					    math,
 | 
				
			||||||
		'seat.c'
 | 
					    pango,
 | 
				
			||||||
	],
 | 
					    pangocairo,
 | 
				
			||||||
 | 
					    xkbcommon,
 | 
				
			||||||
 | 
					    wayland_client,
 | 
				
			||||||
 | 
					    wlroots,
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sources = [
 | 
				
			||||||
 | 
					    'main.c',
 | 
				
			||||||
 | 
					    'password.c',
 | 
				
			||||||
 | 
					    'render.c',
 | 
				
			||||||
 | 
					    'seat.c'
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if libpam.found()
 | 
				
			||||||
 | 
					    sources += ['pam.c']
 | 
				
			||||||
 | 
					    dependencies += [libpam]
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					    warning('The swaylock binary must be setuid when compiled without libpam')
 | 
				
			||||||
 | 
					    warning('You must do this manually post-install: chmod a+s /path/to/swaylock')
 | 
				
			||||||
 | 
					    sources += ['shadow.c']
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					executable('swaylock',
 | 
				
			||||||
 | 
					    sources,
 | 
				
			||||||
	include_directories: [sway_inc],
 | 
						include_directories: [sway_inc],
 | 
				
			||||||
	dependencies: [
 | 
						dependencies: dependencies,
 | 
				
			||||||
		cairo,
 | 
					 | 
				
			||||||
		client_protos,
 | 
					 | 
				
			||||||
		gdk_pixbuf,
 | 
					 | 
				
			||||||
		libpam,
 | 
					 | 
				
			||||||
		math,
 | 
					 | 
				
			||||||
		pango,
 | 
					 | 
				
			||||||
		pangocairo,
 | 
					 | 
				
			||||||
		xkbcommon,
 | 
					 | 
				
			||||||
		wayland_client,
 | 
					 | 
				
			||||||
		wlroots,
 | 
					 | 
				
			||||||
	],
 | 
					 | 
				
			||||||
	link_with: [lib_sway_common, lib_sway_client],
 | 
						link_with: [lib_sway_common, lib_sway_client],
 | 
				
			||||||
	install: true
 | 
						install: true
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										62
									
								
								swaylock/pam.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								swaylock/pam.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,62 @@
 | 
				
			||||||
 | 
					#define _XOPEN_SOURCE 500
 | 
				
			||||||
 | 
					#include <pwd.h>
 | 
				
			||||||
 | 
					#include <security/pam_appl.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <wlr/util/log.h>
 | 
				
			||||||
 | 
					#include "swaylock/swaylock.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void initialize_pw_backend(void) {
 | 
				
			||||||
 | 
						// TODO: only call pam_start once. keep the same handle the whole time
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int function_conversation(int num_msg, const struct pam_message **msg,
 | 
				
			||||||
 | 
							struct pam_response **resp, void *data) {
 | 
				
			||||||
 | 
						struct swaylock_password *pw = data;
 | 
				
			||||||
 | 
						/* PAM expects an array of responses, one for each message */
 | 
				
			||||||
 | 
						struct pam_response *pam_reply = calloc(
 | 
				
			||||||
 | 
								num_msg, sizeof(struct pam_response));
 | 
				
			||||||
 | 
						*resp = pam_reply;
 | 
				
			||||||
 | 
						for (int i = 0; i < num_msg; ++i) {
 | 
				
			||||||
 | 
							switch (msg[i]->msg_style) {
 | 
				
			||||||
 | 
							case PAM_PROMPT_ECHO_OFF:
 | 
				
			||||||
 | 
							case PAM_PROMPT_ECHO_ON:
 | 
				
			||||||
 | 
								pam_reply[i].resp = strdup(pw->buffer); // PAM clears and frees this
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case PAM_ERROR_MSG:
 | 
				
			||||||
 | 
							case PAM_TEXT_INFO:
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return PAM_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool attempt_password(struct swaylock_password *pw) {
 | 
				
			||||||
 | 
						struct passwd *passwd = getpwuid(getuid());
 | 
				
			||||||
 | 
						char *username = passwd->pw_name;
 | 
				
			||||||
 | 
						const struct pam_conv local_conversation = {
 | 
				
			||||||
 | 
							function_conversation, pw
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						pam_handle_t *local_auth_handle = NULL;
 | 
				
			||||||
 | 
						int pam_err;
 | 
				
			||||||
 | 
						if ((pam_err = pam_start("swaylock", username,
 | 
				
			||||||
 | 
										&local_conversation, &local_auth_handle)) != PAM_SUCCESS) {
 | 
				
			||||||
 | 
							wlr_log(WLR_ERROR, "PAM returned error %d", pam_err);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if ((pam_err = pam_authenticate(local_auth_handle, 0)) != PAM_SUCCESS) {
 | 
				
			||||||
 | 
							wlr_log(WLR_ERROR, "pam_authenticate failed");
 | 
				
			||||||
 | 
							goto fail;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// TODO: only call pam_end once we succeed at authing. refresh tokens beforehand
 | 
				
			||||||
 | 
						if ((pam_err = pam_end(local_auth_handle, pam_err)) != PAM_SUCCESS) {
 | 
				
			||||||
 | 
							wlr_log(WLR_ERROR, "pam_end failed");
 | 
				
			||||||
 | 
							goto fail;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						clear_password_buffer(pw);
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					fail:
 | 
				
			||||||
 | 
						clear_password_buffer(pw);
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,6 @@
 | 
				
			||||||
#define _XOPEN_SOURCE 500
 | 
					#define _XOPEN_SOURCE 500
 | 
				
			||||||
#include <assert.h>
 | 
					#include <assert.h>
 | 
				
			||||||
#include <pwd.h>
 | 
					#include <pwd.h>
 | 
				
			||||||
#include <security/pam_appl.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
| 
						 | 
					@ -11,27 +10,6 @@
 | 
				
			||||||
#include "swaylock/seat.h"
 | 
					#include "swaylock/seat.h"
 | 
				
			||||||
#include "unicode.h"
 | 
					#include "unicode.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int function_conversation(int num_msg, const struct pam_message **msg,
 | 
					 | 
				
			||||||
		struct pam_response **resp, void *data) {
 | 
					 | 
				
			||||||
	struct swaylock_password *pw = data;
 | 
					 | 
				
			||||||
	/* PAM expects an array of responses, one for each message */
 | 
					 | 
				
			||||||
	struct pam_response *pam_reply = calloc(
 | 
					 | 
				
			||||||
			num_msg, sizeof(struct pam_response));
 | 
					 | 
				
			||||||
	*resp = pam_reply;
 | 
					 | 
				
			||||||
	for (int i = 0; i < num_msg; ++i) {
 | 
					 | 
				
			||||||
		switch (msg[i]->msg_style) {
 | 
					 | 
				
			||||||
		case PAM_PROMPT_ECHO_OFF:
 | 
					 | 
				
			||||||
		case PAM_PROMPT_ECHO_ON:
 | 
					 | 
				
			||||||
			pam_reply[i].resp = strdup(pw->buffer); // PAM clears and frees this
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case PAM_ERROR_MSG:
 | 
					 | 
				
			||||||
		case PAM_TEXT_INFO:
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return PAM_SUCCESS;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void clear_password_buffer(struct swaylock_password *pw) {
 | 
					void clear_password_buffer(struct swaylock_password *pw) {
 | 
				
			||||||
	// Use volatile keyword so so compiler can't optimize this out.
 | 
						// Use volatile keyword so so compiler can't optimize this out.
 | 
				
			||||||
	volatile char *buffer = pw->buffer;
 | 
						volatile char *buffer = pw->buffer;
 | 
				
			||||||
| 
						 | 
					@ -42,35 +20,6 @@ void clear_password_buffer(struct swaylock_password *pw) {
 | 
				
			||||||
	pw->len = 0;
 | 
						pw->len = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool attempt_password(struct swaylock_password *pw) {
 | 
					 | 
				
			||||||
	struct passwd *passwd = getpwuid(getuid());
 | 
					 | 
				
			||||||
	char *username = passwd->pw_name;
 | 
					 | 
				
			||||||
	const struct pam_conv local_conversation = {
 | 
					 | 
				
			||||||
		function_conversation, pw
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	pam_handle_t *local_auth_handle = NULL;
 | 
					 | 
				
			||||||
	int pam_err;
 | 
					 | 
				
			||||||
	// TODO: only call pam_start once. keep the same handle the whole time
 | 
					 | 
				
			||||||
	if ((pam_err = pam_start("swaylock", username,
 | 
					 | 
				
			||||||
					&local_conversation, &local_auth_handle)) != PAM_SUCCESS) {
 | 
					 | 
				
			||||||
		wlr_log(WLR_ERROR, "PAM returned error %d", pam_err);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if ((pam_err = pam_authenticate(local_auth_handle, 0)) != PAM_SUCCESS) {
 | 
					 | 
				
			||||||
		wlr_log(WLR_ERROR, "pam_authenticate failed");
 | 
					 | 
				
			||||||
		goto fail;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// TODO: only call pam_end once we succeed at authing. refresh tokens beforehand
 | 
					 | 
				
			||||||
	if ((pam_err = pam_end(local_auth_handle, pam_err)) != PAM_SUCCESS) {
 | 
					 | 
				
			||||||
		wlr_log(WLR_ERROR, "pam_end failed");
 | 
					 | 
				
			||||||
		goto fail;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	clear_password_buffer(pw);
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
fail:
 | 
					 | 
				
			||||||
	clear_password_buffer(pw);
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool backspace(struct swaylock_password *pw) {
 | 
					static bool backspace(struct swaylock_password *pw) {
 | 
				
			||||||
	if (pw->len != 0) {
 | 
						if (pw->len != 0) {
 | 
				
			||||||
		pw->buffer[--pw->len] = 0;
 | 
							pw->buffer[--pw->len] = 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										128
									
								
								swaylock/shadow.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								swaylock/shadow.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,128 @@
 | 
				
			||||||
 | 
					#define _XOPEN_SOURCE
 | 
				
			||||||
 | 
					#include <pwd.h>
 | 
				
			||||||
 | 
					#include <shadow.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <wlr/util/log.h>
 | 
				
			||||||
 | 
					#include "swaylock/swaylock.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int comm[2][2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void run_child(void) {
 | 
				
			||||||
 | 
						/* This code runs as root */
 | 
				
			||||||
 | 
						struct passwd *pwent = getpwuid(getuid());
 | 
				
			||||||
 | 
						if (!pwent) {
 | 
				
			||||||
 | 
							wlr_log_errno(WLR_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) {
 | 
				
			||||||
 | 
								wlr_log_errno(WLR_ERROR, "failed to getspnam");
 | 
				
			||||||
 | 
								exit(EXIT_FAILURE);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							encpw = swent->sp_pwdp;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wlr_log(WLR_DEBUG, "prepared to authorize user %s", pwent->pw_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t size;
 | 
				
			||||||
 | 
						char *buf;
 | 
				
			||||||
 | 
						while (1) {
 | 
				
			||||||
 | 
							ssize_t amt;
 | 
				
			||||||
 | 
							amt = read(comm[0][0], &size, sizeof(size));
 | 
				
			||||||
 | 
							if (amt == 0) {
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							} else if (amt < 0) {
 | 
				
			||||||
 | 
								wlr_log_errno(WLR_ERROR, "read pw request");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							wlr_log(WLR_DEBUG, "received pw check request");
 | 
				
			||||||
 | 
							buf = malloc(size);
 | 
				
			||||||
 | 
							if (!buf) {
 | 
				
			||||||
 | 
								wlr_log_errno(WLR_ERROR, "failed to malloc pw buffer");
 | 
				
			||||||
 | 
								exit(EXIT_FAILURE);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							size_t offs = 0;
 | 
				
			||||||
 | 
							do {
 | 
				
			||||||
 | 
								amt = read(comm[0][0], &buf[offs], size - offs);
 | 
				
			||||||
 | 
								if (amt <= 0) {
 | 
				
			||||||
 | 
									wlr_log_errno(WLR_ERROR, "failed to read pw");
 | 
				
			||||||
 | 
									exit(EXIT_FAILURE);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								offs += (size_t)amt;
 | 
				
			||||||
 | 
							} while (offs < size);
 | 
				
			||||||
 | 
							bool result = false;
 | 
				
			||||||
 | 
							char *c = crypt(buf, encpw);
 | 
				
			||||||
 | 
							if (c == NULL) {
 | 
				
			||||||
 | 
								wlr_log_errno(WLR_ERROR, "crypt");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							result = strcmp(c, encpw) == 0;
 | 
				
			||||||
 | 
							if (write(comm[1][1], &result, sizeof(result)) != sizeof(result)) {
 | 
				
			||||||
 | 
								wlr_log_errno(WLR_ERROR, "failed to write pw check result");
 | 
				
			||||||
 | 
								exit(EXIT_FAILURE);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							free(buf);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						exit(EXIT_SUCCESS);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void initialize_pw_backend(void) {
 | 
				
			||||||
 | 
						if (geteuid() != 0) {
 | 
				
			||||||
 | 
							wlr_log(WLR_ERROR, "swaylock needs to be setuid to read /etc/shadow");
 | 
				
			||||||
 | 
							exit(EXIT_FAILURE);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (pipe(comm[0]) != 0) {
 | 
				
			||||||
 | 
							wlr_log_errno(WLR_ERROR, "failed to create pipe");
 | 
				
			||||||
 | 
							exit(EXIT_FAILURE);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (pipe(comm[1]) != 0) {
 | 
				
			||||||
 | 
							wlr_log_errno(WLR_ERROR, "failed to create pipe");
 | 
				
			||||||
 | 
							exit(EXIT_FAILURE);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pid_t child = fork();
 | 
				
			||||||
 | 
						if (child == 0) {
 | 
				
			||||||
 | 
							close(comm[0][1]);
 | 
				
			||||||
 | 
							close(comm[1][0]);
 | 
				
			||||||
 | 
							run_child();
 | 
				
			||||||
 | 
						} else if (child < 0) {
 | 
				
			||||||
 | 
							wlr_log_errno(WLR_ERROR, "failed to fork");
 | 
				
			||||||
 | 
							exit(EXIT_FAILURE);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						close(comm[0][0]);
 | 
				
			||||||
 | 
						close(comm[1][1]);
 | 
				
			||||||
 | 
						if (setgid(getgid()) != 0) {
 | 
				
			||||||
 | 
							wlr_log_errno(WLR_ERROR, "Unable to drop root");
 | 
				
			||||||
 | 
							exit(EXIT_FAILURE);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (setuid(getuid()) != 0) {
 | 
				
			||||||
 | 
							wlr_log_errno(WLR_ERROR, "Unable to drop root");
 | 
				
			||||||
 | 
							exit(EXIT_FAILURE);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool attempt_password(struct swaylock_password *pw) {
 | 
				
			||||||
 | 
						bool result = false;
 | 
				
			||||||
 | 
						size_t len = pw->len + 1;
 | 
				
			||||||
 | 
						size_t offs = 0;
 | 
				
			||||||
 | 
						if (write(comm[0][1], &len, sizeof(len)) < 0) {
 | 
				
			||||||
 | 
							wlr_log_errno(WLR_ERROR, "Failed to request pw check");
 | 
				
			||||||
 | 
							goto ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							ssize_t amt = write(comm[0][1], &pw->buffer[offs], len - offs);
 | 
				
			||||||
 | 
							if (amt < 0) {
 | 
				
			||||||
 | 
								wlr_log_errno(WLR_ERROR, "Failed to write pw buffer");
 | 
				
			||||||
 | 
								goto ret;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							offs += amt;
 | 
				
			||||||
 | 
						} while (offs < len);
 | 
				
			||||||
 | 
						if (read(comm[1][0], &result, sizeof(result)) != sizeof(result)) {
 | 
				
			||||||
 | 
							wlr_log_errno(WLR_ERROR, "Failed to read pw result");
 | 
				
			||||||
 | 
							goto ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wlr_log(WLR_DEBUG, "pw result: %d", result);
 | 
				
			||||||
 | 
					ret:
 | 
				
			||||||
 | 
						clear_password_buffer(pw);
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue