From 7583e1dac92497a64dc438d3538408ff55141a7b Mon Sep 17 00:00:00 2001 From: netblue30 Date: Sat, 23 Jan 2016 10:14:03 -0500 Subject: added --user command --- src/firejail/firejail.h | 3 ++ src/firejail/main.c | 1 + src/firejail/usage.c | 1 + src/firejail/user.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++ src/man/firejail.txt | 9 ++++ 5 files changed, 128 insertions(+) create mode 100644 src/firejail/user.c (limited to 'src') diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 21ca6c508..a2afd4a8d 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -505,5 +505,8 @@ void fs_logger_print_log(pid_t pid); // run_symlink.c void run_symlink(int argc, char **argv); +// user.c +void check_user(int argc, char **argv); + #endif diff --git a/src/firejail/main.c b/src/firejail/main.c index 2ae3213ee..7afbf9ce3 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -514,6 +514,7 @@ int main(int argc, char **argv) { else { // check --output option and execute it; check_output(argc, argv); // the function will not return if --output option was found + check_user(argc, argv); // the function will not return if --user option was found } // parse arguments diff --git a/src/firejail/usage.c b/src/firejail/usage.c index 9197baae2..d3ebefaae 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c @@ -286,6 +286,7 @@ void usage(void) { printf("\t--tracelog - add a syslog message for every access to files or\n"); printf("\t\tdirectoires blacklisted by the security profile.\n\n"); printf("\t--tree - print a tree of all sandboxed processes.\n\n"); + printf("\t--user=new_user - switch the user before starting the sandbox.\n\n"); printf("\t--version - print program version and exit.\n\n"); printf("\t--whitelist=dirname_or_filename - whitelist directory or file.\n\n"); printf("\t--zsh - use /usr/bin/zsh as default shell.\n\n"); diff --git a/src/firejail/user.c b/src/firejail/user.c new file mode 100644 index 000000000..e5f7848e8 --- /dev/null +++ b/src/firejail/user.c @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2014-2016 Firejail Authors + * + * This file is part of firejail project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "firejail.h" +#include +#include +#include +#include +#include + + +void check_user(int argc, char **argv) { + int i; + char *user = NULL; + + int found = 0; + for (i = 1; i < argc; i++) { + // check options + if (strcmp(argv[i], "--") == 0) + break; + if (strncmp(argv[i], "--", 2) != 0) + break; + + // check user option + if (strncmp(argv[i], "--user=", 7) == 0) { + found = 1; + user = argv[i] + 7; + break; + } + } + if (!found) + return; + + // check root + if (getuid() != 0) { + fprintf(stderr, "Error: you need to be root to use --user command line option\n"); + exit(1); + } + + // switch user + struct passwd *pw = getpwnam(user); + if (!pw) { + fprintf(stderr, "Error: cannot find user %s\n", user); + exit(1); + } + + printf("Switching to user %s, UID %d, GID %d\n", user, pw->pw_uid, pw->pw_gid); + int rv = initgroups(user, pw->pw_gid); + if (rv == -1) { + perror("initgroups"); + fprintf(stderr, "Error: cannot switch to user %s\n", user); + } + + rv = setgid(pw->pw_gid); + if (rv == -1) { + perror("setgid"); + fprintf(stderr, "Error: cannot switch to user %s\n", user); + } + + rv = setuid(pw->pw_uid); + if (rv == -1) { + perror("setuid"); + fprintf(stderr, "Error: cannot switch to user %s\n", user); + } + + // build the new command line + int len = 0; + for (i = 0; i < argc; i++) { + len += strlen(argv[i]) + 1; // + ' ' + } + + char *cmd = malloc(len + 1); // + '\0' + if (!cmd) + errExit("malloc"); + + char *ptr = cmd; + int first = 1; + for (i = 0; i < argc; i++) { + if (strncmp(argv[i], "--user=", 7) == 0 && first) { + first = 0; + continue; + } + + ptr += sprintf(ptr, "%s ", argv[i]); + } + + // run command + char *a[4]; + a[0] = "/bin/bash"; + a[1] = "-c"; + a[2] = cmd; + a[3] = NULL; + + execvp(a[0], a); + + perror("execvp"); + exit(1); +} diff --git a/src/man/firejail.txt b/src/man/firejail.txt index 13eccbdce..ef65530db 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt @@ -1441,6 +1441,15 @@ $ firejail \-\-tree .br 11970:netblue:transmission-gtk .TP +\fB\-\-user=new-user +Switch the user before starting the sandbox. This command should be run as root. +.br + +.br +Example: +.br +# firejail \-\-user=www-data +.TP \fB\-\-version Print program version and exit. .br -- cgit v1.2.3-54-g00ecf