From 2d8113990c1e8153e8e8ee4612ecd534b555a0f5 Mon Sep 17 00:00:00 2001 From: dexterlb Date: Sun, 2 Jun 2019 18:27:03 +0300 Subject: [PATCH 1/5] implement -a, -b and -n --- main.c | 31 +++++++++++++++++++++++++++---- options.c | 14 ++++++++++++-- physlock.h | 3 +++ 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/main.c b/main.c index 31056bc..dddcc01 100644 --- a/main.c +++ b/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; } diff --git a/options.c b/options.c index 6ec3634..307e071 100644 --- a/options.c +++ b/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; diff --git a/physlock.h b/physlock.h index 0eb42ee..703ba44 100644 --- a/physlock.h +++ b/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 2/5] document extra options --- README.md | 3 +++ physlock.1 | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8d7da4f..9a408c8 100644 --- a/README.md +++ b/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 diff --git a/physlock.1 b/physlock.1 index 32e8547..71b1fe2 100644 --- a/physlock.1 +++ b/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 3/5] add extra options to print_usage() --- options.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options.c b/options.c index 307e071..225b22a 100644 --- a/options.c +++ b/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 4/5] use hardcoded /bin/sh as a shell instead of relying on PATH --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.c b/main.c index dddcc01..acc7577 100644 --- a/main.c +++ b/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 5/5] don't run external commands as root --- main.c | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/main.c b/main.c index acc7577..50b7786 100644 --- a/main.c +++ b/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;