From 185a63267380d87728031674a68b8b80247ae3a9 Mon Sep 17 00:00:00 2001 From: Christoph Ruegge Date: Fri, 25 Oct 2019 08:22:57 +0200 Subject: [PATCH 02/11] Call pam_setcred after successful authentication --- main.c | 1 + 1 file changed, 1 insertion(+) --- main.c +++ main.c @@ -197,6 +197,7 @@ int main(int argc, char **argv) { u->pam_status = pam_authenticate(u->pamh, 0); switch (u->pam_status) { case PAM_SUCCESS: + pam_setcred(u->pamh, PAM_REFRESH_CRED); locked = 0; break; case PAM_AUTH_ERR: From 2eb17b1111d2839ba24a0ac764a50c29a03c8355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bert=20M=C3=BCnnich?= Date: Mon, 16 Dec 2019 09:36:36 +0100 Subject: [PATCH 03/11] Fix for systemd mechanism never used --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) --- Makefile +++ Makefile @@ -10,7 +10,8 @@ MANPREFIX = $(PREFIX)/share/man HAVE_SYSTEMD = 1 cflags = -Wall -pedantic $(CFLAGS) -cppflags = -I. $(CPPFLAGS) -D_XOPEN_SOURCE=500 +cppflags = -I. $(CPPFLAGS) -D_XOPEN_SOURCE=500 \ + -DHAVE_SYSTEMD=$(HAVE_SYSTEMD) lib_systemd_0 = lib_systemd_1 = -lsystemd From 3d5c3b599a2fe3f50032c1066ee46d0e047c002c Mon Sep 17 00:00:00 2001 From: travankor Date: Fri, 13 Dec 2019 13:54:19 -0700 Subject: [PATCH 04/11] Rename systemd function to logind. --- main.c | 2 +- physlock.h | 2 +- session.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) --- main.c +++ main.c @@ -134,7 +134,7 @@ int main(int argc, char **argv) { return 0; } - if (get_user_systemd(&user, oldvt) == -1 && get_user_utmp(&user, oldvt) == -1) + if (get_user_logind(&user, oldvt) == -1 && get_user_utmp(&user, oldvt) == -1) get_user_by_id(&user, owner); get_user_by_id(&root, 0); if (strcmp(user.name, root.name) != 0) --- physlock.h +++ physlock.h @@ -64,7 +64,7 @@ void parse_options(int, char**); /* session.c */ -int get_user_systemd(userinfo_t*, int); +int get_user_logind(userinfo_t*, int); int get_user_utmp(userinfo_t*, int); --- session.c +++ session.c @@ -11,7 +11,7 @@ #if HAVE_SYSTEMD #include -int get_user_systemd(userinfo_t *uinfo, int vt) { +int get_user_logind(userinfo_t *uinfo, int vt) { int ret = -1, i, n; char **sessions = NULL; unsigned int sess_vt; @@ -40,7 +40,7 @@ int get_user_systemd(userinfo_t *uinfo, int vt) { #else -int get_user_systemd(userinfo_t *uinfo, int vt) { +int get_user_logind(userinfo_t *uinfo, int vt) { (void)uinfo; (void)vt; return -1; From 454122212049f48edfc3c6d80d4c0436ea33160b Mon Sep 17 00:00:00 2001 From: travankor Date: Fri, 13 Dec 2019 14:23:48 -0700 Subject: [PATCH 05/11] Add option to use elogind. Fixes issue #85. --- Makefile | 10 +++++++--- README.md | 3 ++- session.c | 5 +++++ 3 files changed, 14 insertions(+), 4 deletions(-) --- Makefile +++ Makefile @@ -6,16 +6,20 @@ VPATH = $(srcdir) PREFIX = /usr/local MANPREFIX = $(PREFIX)/share/man -# enable user detection using libsystemd +# enable user detection using libsystemd or libelogind HAVE_SYSTEMD = 1 +HAVE_ELOGIND = 0 cflags = -Wall -pedantic $(CFLAGS) cppflags = -I. $(CPPFLAGS) -D_XOPEN_SOURCE=500 \ - -DHAVE_SYSTEMD=$(HAVE_SYSTEMD) + -DHAVE_SYSTEMD=$(HAVE_SYSTEMD) -DHAVE_ELOGIND=$(HAVE_ELOGIND) lib_systemd_0 = lib_systemd_1 = -lsystemd -ldlibs = $(LDLIBS) -lpam -lpam_misc $(lib_systemd_$(HAVE_SYSTEMD)) +lib_elogind_0 = +lib_elogind_1 = -lelogind +ldlibs = $(LDLIBS) -lpam -lpam_misc \ + $(lib_systemd_$(HAVE_SYSTEMD)) $(lib_elogind_$(HAVE_ELOGIND)) objs = main.o options.o session.o util.o vt.o --- README.md +++ README.md @@ -7,7 +7,8 @@ PAM for authentication. physlock uses 3 mechanisms to detect the user of the active session: -1. Querying systemd-logind(1) if not compiled with `HAVE_SYSTEMD=0` +1. Querying systemd-logind(1) or elogind(8) if compiled with either + `HAVE_SYSTEMD=1` or `HAVE_ELOGIND=1` 2. Searching the utmp file for an entry whose `ut_line` field is the base name of the active tty device file 3. Using the owner of the active tty device file typically set by login(1) --- session.c +++ session.c @@ -10,6 +10,11 @@ #if HAVE_SYSTEMD #include +#elif HAVE_ELOGIND +#include +#endif + +#if HAVE_SYSTEMD || HAVE_ELOGIND int get_user_logind(userinfo_t *uinfo, int vt) { int ret = -1, i, n; From 2d8113990c1e8153e8e8ee4612ecd534b555a0f5 Mon Sep 17 00:00:00 2001 From: dexterlb Date: Sun, 2 Jun 2019 18:27:03 +0300 Subject: [PATCH 07/11] implement -a, -b and -n --- main.c | 31 +++++++++++++++++++++++++++---- options.c | 14 ++++++++++++-- physlock.h | 3 +++ 3 files changed, 42 insertions(+), 6 deletions(-) --- main.c +++ main.c @@ -26,6 +26,7 @@ #include #include #include +#include #include static int oldvt; @@ -33,6 +34,7 @@ static vt_t vt; static int oldsysrq; static int oldprintk; static pid_t chpid; +static int cmdpid; static int locked; static userinfo_t root, user; @@ -67,8 +69,8 @@ CLEANUP void free_user(userinfo_t *uinfo) { } void cleanup() { - if (options->detach && chpid > 0) - /* No cleanup in parent after successful fork */ + if ((options->detach && chpid > 0) || cmdpid == 0) + /* No cleanup in parent after successful fork or in failed forked command */ return; free_user(&user); free_user(&root); @@ -98,17 +100,30 @@ void setup_signal(int signum, void (*handler)(int)) { sigact.sa_flags = 0; sigact.sa_handler = handler; sigemptyset(&sigact.sa_mask); - + if (sigaction(signum, &sigact, NULL) < 0) error(0, errno, "signal %d", signum); } +void run_command(const char* cmd) { + cmdpid = fork(); + if (cmdpid < 0) { + error(EXIT_FAILURE, errno, "fork"); + } else if (cmdpid > 0) { + wait(NULL); + } else { + execlp("sh", "sh", "-c", cmd, NULL); + error(EXIT_FAILURE, errno, "exec"); + } +} + int main(int argc, char **argv) { int try = 0, root_user = 1; uid_t owner; userinfo_t *u = &user; oldvt = oldsysrq = oldprintk = vt.nr = vt.fd = -1; + cmdpid = -1; vt.ios = NULL; error_init(2); @@ -180,11 +195,15 @@ int main(int argc, char **argv) { dup2(vt.fd, 1); dup2(vt.fd, 2); + if (options->command_before != NULL && options->command_before[0] != '\0') { + run_command(options->command_before); + } + if (options->prompt != NULL && options->prompt[0] != '\0') { fprintf(vt.ios, "%s\n\n", options->prompt); } - locked = 1; + locked = !options->no_auth; while (locked) { if (!root_user && try >= (u == &root ? 1 : 3)) { @@ -218,6 +237,10 @@ int main(int argc, char **argv) { } } + if (options->command_after != NULL && options->command_after[0] != '\0') { + run_command(options->command_after); + } + return 0; } --- options.c +++ options.c @@ -37,7 +37,7 @@ void print_version() { void parse_options(int argc, char **argv) { int opt; - + progname = strrchr(argv[0], '/'); progname = progname != NULL ? progname + 1 : argv[0]; @@ -45,8 +45,9 @@ void parse_options(int argc, char **argv) { _options.disable_sysrq = 0; _options.lock_switch = -1; _options.mute_kernel_messages = 0; + _options.no_auth = 0; - while ((opt = getopt(argc, argv, "dhLlmp:sv")) != -1) { + while ((opt = getopt(argc, argv, "dhLlmnp:svb:a:")) != -1) { switch (opt) { case '?': print_usage(); @@ -66,9 +67,18 @@ void parse_options(int argc, char **argv) { case 'm': _options.mute_kernel_messages = 1; break; + case 'n': + _options.no_auth = 1; + break; case 'p': _options.prompt = optarg; break; + case 'b': + _options.command_before = optarg; + break; + case 'a': + _options.command_after = optarg; + break; case 's': _options.disable_sysrq = 1; break; --- physlock.h +++ physlock.h @@ -54,7 +54,10 @@ typedef struct options_s { int disable_sysrq; int lock_switch; int mute_kernel_messages; + int no_auth; const char *prompt; + const char *command_before; + const char *command_after; } options_t; extern const options_t *options; From 46ad54bf65fa00c3fb1fb89c64972c0ea0fca3b7 Mon Sep 17 00:00:00 2001 From: dexterlb Date: Sun, 2 Jun 2019 18:37:24 +0300 Subject: [PATCH 08/11] document extra options --- README.md | 3 +++ physlock.1 | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) --- README.md +++ README.md @@ -58,6 +58,9 @@ The following command-line arguments are supported: -l only lock console switching -L only enable console switching -m mute kernel messages on console while physlock is running + -b CMD execute CMD before the password prompt + -a CMD execute CMD after successfully authenticating + -n don't actually authenticate: just execute commands -p MSG Display MSG before the password prompt -s disable sysrq key while physlock is running -v print version information and exit --- physlock.1 +++ physlock.1 @@ -3,9 +3,13 @@ physlock \- lock all consoles / virtual terminals .SH SYNOPSIS .B physlock -.RB [ \-dhLlmsv ] +.RB [ \-dhLlmnsv ] .RB [ \-p .IR MSG ] +.RB [ \-b +.IR CMD ] +.RB [ \-a +.IR CMD ] .SH DESCRIPTION physlock is an alternative to vlock, it is equivalent to `vlock \-an'. It is written because vlock blocks some linux kernel mechanisms like hibernate and @@ -39,6 +43,15 @@ locked. .B \-m Mute kernel messages on console while physlock is running. .TP +.B "\-b " CMD +Execute CMD before asking for password +.TP +.B "\-a " CMD +Execute CMD after asking for password +.TP +.B \-n +Don't ask for authentication: just execute commands +.TP .BI "\-p " MSG Display .I MSG From a9f968d9e331127a2ae0d548c3020874a1358689 Mon Sep 17 00:00:00 2001 From: dexterlb Date: Mon, 17 Jun 2019 17:36:23 +0300 Subject: [PATCH 09/11] add extra options to print_usage() --- options.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- options.c +++ options.c @@ -28,7 +28,7 @@ static options_t _options; const options_t *options = (const options_t*) &_options; void print_usage() { - printf("usage: physlock [-dhLlmsv] [-p MSG]\n"); + printf("usage: physlock [-dhLlmsbanv] [-p MSG]\n"); } void print_version() { From 7200a418b58b9608141c421875919798382cd504 Mon Sep 17 00:00:00 2001 From: dexterlb Date: Tue, 1 Oct 2019 11:55:11 +0300 Subject: [PATCH 10/11] use hardcoded /bin/sh as a shell instead of relying on PATH --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- main.c +++ main.c @@ -112,7 +112,7 @@ void run_command(const char* cmd) { } else if (cmdpid > 0) { wait(NULL); } else { - execlp("sh", "sh", "-c", cmd, NULL); + execl("/bin/sh", "sh", "-c", cmd, NULL); error(EXIT_FAILURE, errno, "exec"); } } From fc47a51029ea32bd575962248e11cca5fd9b550d Mon Sep 17 00:00:00 2001 From: dexterlb Date: Tue, 1 Oct 2019 12:14:04 +0300 Subject: [PATCH 11/11] don't run external commands as root --- main.c | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) --- main.c +++ main.c @@ -105,16 +105,32 @@ void setup_signal(int signum, void (*handler)(int)) { error(0, errno, "signal %d", signum); } -void run_command(const char* cmd) { - cmdpid = fork(); - if (cmdpid < 0) { - error(EXIT_FAILURE, errno, "fork"); - } else if (cmdpid > 0) { - wait(NULL); - } else { - execl("/bin/sh", "sh", "-c", cmd, NULL); - error(EXIT_FAILURE, errno, "exec"); - } +void drop_privileges(userinfo_t* user) { + struct passwd *p = getpwnam(user->name); + if (p == NULL) { + error(EXIT_FAILURE, errno, "get user passwd data"); + } + + if (setgid(p->pw_gid) != 0) { + error(EXIT_FAILURE, errno, "setgid"); + } + + if (setuid(p->pw_uid) != 0) { + error(EXIT_FAILURE, errno, "setuid"); + } +} + +void run_command(const char* cmd, userinfo_t* user) { + cmdpid = fork(); + if (cmdpid < 0) { + error(EXIT_FAILURE, errno, "fork"); + } else if (cmdpid > 0) { + wait(NULL); + } else { + drop_privileges(user); + execl("/bin/sh", "sh", "-c", cmd, NULL); + error(EXIT_FAILURE, errno, "exec"); + } } int main(int argc, char **argv) { @@ -196,7 +212,7 @@ int main(int argc, char **argv) { dup2(vt.fd, 2); if (options->command_before != NULL && options->command_before[0] != '\0') { - run_command(options->command_before); + run_command(options->command_before, &user); } if (options->prompt != NULL && options->prompt[0] != '\0') { @@ -238,7 +254,7 @@ int main(int argc, char **argv) { } if (options->command_after != NULL && options->command_after[0] != '\0') { - run_command(options->command_after); + run_command(options->command_after, &user); } return 0;