aboutsummaryrefslogtreecommitdiffstats
path: root/src/firecfg/main.c
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2018-08-25 11:03:25 -0400
committerLibravatar netblue30 <netblue30@yahoo.com>2018-08-25 11:03:25 -0400
commitfc7a9505c56192b5fc0ca62eb51fa7f0d8b1cef8 (patch)
treed30903ff5e8d4a10ddae3a2576f363c4159e0e69 /src/firecfg/main.c
parentcleanup, small improvements (diff)
downloadfirejail-fc7a9505c56192b5fc0ca62eb51fa7f0d8b1cef8.tar.gz
firejail-fc7a9505c56192b5fc0ca62eb51fa7f0d8b1cef8.tar.zst
firejail-fc7a9505c56192b5fc0ca62eb51fa7f0d8b1cef8.zip
support for local user directories in firecfg (--bindir)
Diffstat (limited to 'src/firecfg/main.c')
-rw-r--r--src/firecfg/main.c178
1 files changed, 107 insertions, 71 deletions
diff --git a/src/firecfg/main.c b/src/firecfg/main.c
index d79b8bb8e..298314d4f 100644
--- a/src/firecfg/main.c
+++ b/src/firecfg/main.c
@@ -21,6 +21,7 @@
21#include "firecfg.h" 21#include "firecfg.h"
22#include "../include/firejail_user.h" 22#include "../include/firejail_user.h"
23int arg_debug = 0; 23int arg_debug = 0;
24char *arg_bindir = "/usr/local/bin";
24 25
25static char *usage_str = 26static char *usage_str =
26 "Firecfg is the desktop configuration utility for Firejail software. The utility\n" 27 "Firecfg is the desktop configuration utility for Firejail software. The utility\n"
@@ -31,6 +32,7 @@ static char *usage_str =
31 "DESKTOP INTEGRATION section in man 1 firejail.\n\n" 32 "DESKTOP INTEGRATION section in man 1 firejail.\n\n"
32 "Usage: firecfg [OPTIONS]\n\n" 33 "Usage: firecfg [OPTIONS]\n\n"
33 " --add-users user [user] - add the users to Firejail user access database.\n\n" 34 " --add-users user [user] - add the users to Firejail user access database.\n\n"
35 " --bindir=directory - install in directory instead of /usr/local/bin.\n\n"
34 " --clean - remove all firejail symbolic links.\n\n" 36 " --clean - remove all firejail symbolic links.\n\n"
35 " --debug - print debug messages.\n\n" 37 " --debug - print debug messages.\n\n"
36 " --fix - fix .desktop files.\n\n" 38 " --fix - fix .desktop files.\n\n"
@@ -62,9 +64,9 @@ static void usage(void) {
62 64
63 65
64static void list(void) { 66static void list(void) {
65 DIR *dir = opendir("/usr/local/bin"); 67 DIR *dir = opendir(arg_bindir);
66 if (!dir) { 68 if (!dir) {
67 fprintf(stderr, "Error: cannot open /usr/local/bin directory\n"); 69 fprintf(stderr, "Error: cannot open %s directory\n", arg_bindir);
68 exit(1); 70 exit(1);
69 } 71 }
70 72
@@ -78,7 +80,7 @@ static void list(void) {
78 continue; 80 continue;
79 81
80 char *fullname; 82 char *fullname;
81 if (asprintf(&fullname, "/usr/local/bin/%s", entry->d_name) == -1) 83 if (asprintf(&fullname, "%s/%s", arg_bindir, entry->d_name) == -1)
82 errExit("asprintf"); 84 errExit("asprintf");
83 85
84 if (is_link(fullname)) { 86 if (is_link(fullname)) {
@@ -98,14 +100,10 @@ static void list(void) {
98 100
99static void clean(void) { 101static void clean(void) {
100 printf("Removing all firejail symlinks:\n"); 102 printf("Removing all firejail symlinks:\n");
101 if (getuid() != 0) {
102 fprintf(stderr, "Error: you need to be root to run this command\n");
103 exit(1);
104 }
105 103
106 DIR *dir = opendir("/usr/local/bin"); 104 DIR *dir = opendir(arg_bindir);
107 if (!dir) { 105 if (!dir) {
108 fprintf(stderr, "Error: cannot open /usr/local/bin directory\n"); 106 fprintf(stderr, "Error: cannot open %s directory\n", arg_bindir);
109 exit(1); 107 exit(1);
110 } 108 }
111 109
@@ -119,7 +117,7 @@ static void clean(void) {
119 continue; 117 continue;
120 118
121 char *fullname; 119 char *fullname;
122 if (asprintf(&fullname, "/usr/local/bin/%s", entry->d_name) == -1) 120 if (asprintf(&fullname, "%s/%s", arg_bindir, entry->d_name) == -1)
123 errExit("asprintf"); 121 errExit("asprintf");
124 122
125 if (is_link(fullname)) { 123 if (is_link(fullname)) {
@@ -129,8 +127,11 @@ static void clean(void) {
129 char *ptr = strrchr(fullname, '/'); 127 char *ptr = strrchr(fullname, '/');
130 assert(ptr); 128 assert(ptr);
131 ptr++; 129 ptr++;
132 unlink(fullname); 130 int rv = unlink(fullname);
133 printf(" %s removed\n", ptr); 131 if (rv)
132 fprintf(stderr, "Warning: cannot remove %s\n", fullname);
133 else
134 printf(" %s removed\n", ptr);
134 } 135 }
135 free(fname); 136 free(fname);
136 } 137 }
@@ -148,7 +149,7 @@ static void set_file(const char *name, const char *firejail_exec) {
148 return; 149 return;
149 150
150 char *fname; 151 char *fname;
151 if (asprintf(&fname, "/usr/local/bin/%s", name) == -1) 152 if (asprintf(&fname, "%s/%s", arg_bindir, name) == -1)
152 errExit("asprintf"); 153 errExit("asprintf");
153 154
154 struct stat s; 155 struct stat s;
@@ -184,7 +185,7 @@ static void set_links_firecfg(void) {
184 fprintf(stderr, "Error: cannot open %s\n", cfgfile); 185 fprintf(stderr, "Error: cannot open %s\n", cfgfile);
185 exit(1); 186 exit(1);
186 } 187 }
187 printf("Configuring symlinks in /usr/local/bin based on firecfg.config\n"); 188 printf("Configuring symlinks in %s based on firecfg.config\n", arg_bindir);
188 189
189 char buf[MAX_BUF]; 190 char buf[MAX_BUF];
190 int lineno = 0; 191 int lineno = 0;
@@ -242,7 +243,7 @@ static void set_links_homedir(const char *homedir) {
242 errExit("asprintf"); 243 errExit("asprintf");
243 244
244 // parse ~/.config/firejail/ directory 245 // parse ~/.config/firejail/ directory
245 printf("\nConfiguring symlinks in /usr/local/bin based on local firejail config directory\n"); 246 printf("\nConfiguring symlinks in %s based on local firejail config directory\n", arg_bindir);
246 247
247 DIR *dir = opendir(dirname); 248 DIR *dir = opendir(dirname);
248 if (!dir) { 249 if (!dir) {
@@ -278,9 +279,68 @@ static void set_links_homedir(const char *homedir) {
278 free(firejail_exec); 279 free(firejail_exec);
279} 280}
280 281
282static char *get_user(void) {
283 char *user = getlogin();
284 if (!user) {
285 user = getenv("SUDO_USER");
286 if (!user) {
287 fprintf(stderr, "Error: cannot detect login user\n");
288 exit(1);
289 }
290 }
291
292 return user;
293}
294
295static char *get_homedir(const char *user, uid_t *uid, gid_t *gid) {
296 // find home directory
297 struct passwd *pw = getpwnam(user);
298 if (!pw)
299 goto errexit;
300
301 char *home = pw->pw_dir;
302 if (!home)
303 goto errexit;
304
305 *uid = pw->pw_uid;
306 *gid = pw->pw_gid;
307
308 return home;
309
310errexit:
311 fprintf(stderr, "Error: cannot find home directory for user %s\n", user);
312 exit(1);
313}
281 314
282int main(int argc, char **argv) { 315int main(int argc, char **argv) {
283 int i; 316 int i;
317 int bindir_set = 0;
318
319 // user setup
320 char *user = get_user();
321 uid_t uid;
322 gid_t gid;
323 char *home = get_homedir(user, &uid, &gid);
324
325
326 // check for --bindir
327 for (i = i; i < argc; i++) {
328 if (strncmp(argv[i], "--bindir=", 9) == 0) {
329 if (strncmp(argv[i] + 9, "~/", 2) == 0) {
330 if (asprintf(&arg_bindir, "%s/%s", home, argv[i] + 11) == -1)
331 errExit("asprintf");
332 }
333 else
334 arg_bindir = argv[i] + 9;
335 bindir_set = 1;
336
337 // exit if the directory does not exist, or if we don't have access to it
338 if (access(arg_bindir, R_OK | W_OK | X_OK)) {
339 fprintf(stderr, "Error: directory %s not found\n", arg_bindir);
340 exit(1);
341 }
342 }
343 }
284 344
285 for (i = 1; i < argc; i++) { 345 for (i = 1; i < argc; i++) {
286 // default options 346 // default options
@@ -300,15 +360,6 @@ int main(int argc, char **argv) {
300 return 0; 360 return 0;
301 } 361 }
302 else if (strcmp(argv[i], "--fix") == 0) { 362 else if (strcmp(argv[i], "--fix") == 0) {
303 // find home directory
304 struct passwd *pw = getpwuid(getuid());
305 if (!pw) {
306 goto errexit;
307 }
308 char *home = pw->pw_dir;
309 if (!home) {
310 goto errexit;
311 }
312 fix_desktop_files(home); 363 fix_desktop_files(home);
313 return 0; 364 return 0;
314 } 365 }
@@ -334,19 +385,24 @@ int main(int argc, char **argv) {
334 return 0; 385 return 0;
335 } 386 }
336 else { 387 else {
337 fprintf(stderr, "Error: invalid command line option\n"); 388 if (strncmp(argv[i], "--bindir=", 9) != 0) { // already handled
338 usage(); 389 fprintf(stderr, "Error: invalid command line option\n");
339 return 1; 390 usage();
391 return 1;
392 }
340 } 393 }
341 } 394 }
342 395
396 if (arg_debug)
397 printf("%s %d %d %d %d\n", user, getuid(), getgid(), geteuid(), getegid());
398
343 // set symlinks in /usr/local/bin 399 // set symlinks in /usr/local/bin
344 if (getuid() != 0) { 400 if (bindir_set == 0 && getuid() != 0) {
345 fprintf(stderr, "Error: cannot set the symbolic links in /usr/local/bin\n"); 401 fprintf(stderr, "Error: cannot set the symbolic links in %s\n", arg_bindir);
346 fprintf(stderr, "The proper way to run this command is \"sudo firecfg\".\n"); 402 fprintf(stderr, "The proper way to run this command is \"sudo firecfg\".\n");
347 return 1; 403 return 1;
348 } 404 }
349 else { 405 else if (bindir_set == 0) {
350 // create /usr/local directory if it doesn't exist (Solus distro) 406 // create /usr/local directory if it doesn't exist (Solus distro)
351 struct stat s; 407 struct stat s;
352 if (stat("/usr/local", &s) != 0) { 408 if (stat("/usr/local", &s) != 0) {
@@ -357,66 +413,46 @@ int main(int argc, char **argv) {
357 return 1; 413 return 1;
358 } 414 }
359 } 415 }
360 if (stat("/usr/local/bin", &s) != 0) { 416 if (stat(arg_bindir, &s) != 0) {
361 printf("Creating /usr/local directory\n"); 417 printf("Creating /usr/local directory\n");
362 int rv = mkdir("/usr/local/bin", 0755); 418 int rv = mkdir(arg_bindir, 0755);
363 if (rv != 0) { 419 if (rv != 0) {
364 fprintf(stderr, "Error: cannot create /usr/local/bin directory\n"); 420 fprintf(stderr, "Error: cannot create %s directory\n", arg_bindir);
365 return 1; 421 return 1;
366 } 422 }
367 } 423 }
368 } 424 }
369 clean();
370 set_links_firecfg();
371
372 425
426 // clear all symlinks
427 clean();
373 428
374 // user setup 429 // set new symlinks based on /usr/lib/firejail/firecfg.cfg
375 char *user = getlogin(); 430 set_links_firecfg();
376 if (!user) {
377 user = getenv("SUDO_USER");
378 if (!user) {
379 goto errexit;
380 }
381 }
382 431
383 // add user to firejail access database 432 // add user to firejail access database - only for root
384 if (user) { 433 if (user && getuid() == 0) {
385 printf("\nAdding user %s to Firejail access database in %s/firejail.users\n", user, SYSCONFDIR); 434 printf("\nAdding user %s to Firejail access database in %s/firejail.users\n", user, SYSCONFDIR);
386 firejail_user_add(user); 435 firejail_user_add(user);
387 } 436 }
388 437
389 // switch to the local user, and fix desktop files 438 // set new symlinks based on ~/.config/firejail directory
390 if (user) { 439 set_links_homedir(home);
391 // find home directory
392 struct passwd *pw = getpwnam(user);
393 if (!pw) {
394 goto errexit;
395 }
396 char *home = pw->pw_dir;
397 if (!home) {
398 goto errexit;
399 }
400
401 // running as root
402 set_links_homedir(home);
403 440
404 // drop permissions 441 // drop permissions
442 if (getuid() == 0) {
405 if (setgroups(0, NULL) < 0) 443 if (setgroups(0, NULL) < 0)
406 errExit("setgroups"); 444 errExit("setgroups");
407 // set uid/gid 445 if (setgid(gid) < 0)
408 if (setgid(pw->pw_gid) < 0)
409 errExit("setgid"); 446 errExit("setgid");
410 if (setuid(pw->pw_uid) < 0) 447 if (setuid(uid) < 0)
411 errExit("setuid"); 448 errExit("setuid");
412 if (arg_debug)
413 printf("%s %d %d %d %d\n", user, getuid(), getgid(), geteuid(), getegid());
414 fix_desktop_files(home);
415 } 449 }
416 450
417 return 0; 451 if (arg_debug)
452 printf("%s %d %d %d %d\n", user, getuid(), getgid(), geteuid(), getegid());
418 453
419errexit: 454 // fix .desktop files in ~/.local/share/applications directory
420 fprintf(stderr, "Error: cannot detect login user in order to set desktop files in ~/.local/share/applications\n"); 455 fix_desktop_files(home);
421 return 1; 456
457 return 0;
422} 458}