diff options
-rw-r--r-- | src/firecfg/main.c | 85 | ||||
-rw-r--r-- | src/man/firecfg.txt | 21 | ||||
-rw-r--r-- | src/man/firejail.txt | 2 |
3 files changed, 63 insertions, 45 deletions
diff --git a/src/firecfg/main.c b/src/firecfg/main.c index 6b69dd130..04ccbf2c3 100644 --- a/src/firecfg/main.c +++ b/src/firecfg/main.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <string.h> | 29 | #include <string.h> |
30 | #include <errno.h> | 30 | #include <errno.h> |
31 | #include <sys/mman.h> | 31 | #include <sys/mman.h> |
32 | #include <pwd.h> | ||
33 | |||
32 | #include "../include/common.h" | 34 | #include "../include/common.h" |
33 | static int arg_debug = 0; | 35 | static int arg_debug = 0; |
34 | 36 | ||
@@ -45,7 +47,6 @@ static void usage(void) { | |||
45 | printf(" --debug - print debug messages.\n\n"); | 47 | printf(" --debug - print debug messages.\n\n"); |
46 | printf(" --help, -? - this help screen.\n\n"); | 48 | printf(" --help, -? - this help screen.\n\n"); |
47 | printf(" --list - list all firejail symbolic links.\n\n"); | 49 | printf(" --list - list all firejail symbolic links.\n\n"); |
48 | printf(" --fix - fix .desktop files.\n\n"); | ||
49 | printf(" --version - print program version and exit.\n\n"); | 50 | printf(" --version - print program version and exit.\n\n"); |
50 | printf("Example:\n\n"); | 51 | printf("Example:\n\n"); |
51 | printf(" $ sudo firecfg\n"); | 52 | printf(" $ sudo firecfg\n"); |
@@ -60,10 +61,6 @@ static void usage(void) { | |||
60 | printf(" /usr/local/bin/firefox removed\n"); | 61 | printf(" /usr/local/bin/firefox removed\n"); |
61 | printf(" /usr/local/bin/vlc removed\n"); | 62 | printf(" /usr/local/bin/vlc removed\n"); |
62 | printf(" [...]\n"); | 63 | printf(" [...]\n"); |
63 | printf(" $ firecfg --fix\n"); | ||
64 | printf(" /home/user/.local/share/applications/chromium.desktop created\n"); | ||
65 | printf(" /home/user/.local/share/applications/vlc.desktop created\n"); | ||
66 | printf(" [...]\n"); | ||
67 | printf("\n"); | 64 | printf("\n"); |
68 | printf("License GPL version 2 or later\n"); | 65 | printf("License GPL version 2 or later\n"); |
69 | printf("Homepage: http://firejail.wordpress.com\n\n"); | 66 | printf("Homepage: http://firejail.wordpress.com\n\n"); |
@@ -221,7 +218,7 @@ static void set_file(const char *name, const char *firejail_exec) { | |||
221 | 218 | ||
222 | struct stat s; | 219 | struct stat s; |
223 | if (stat(fname, &s) == 0) { | 220 | if (stat(fname, &s) == 0) { |
224 | printf("%s is already present, skipping...\n", fname); | 221 | printf(" %s is already present, skipping...\n", name); |
225 | } | 222 | } |
226 | else { | 223 | else { |
227 | int rv = symlink(firejail_exec, fname); | 224 | int rv = symlink(firejail_exec, fname); |
@@ -230,19 +227,14 @@ static void set_file(const char *name, const char *firejail_exec) { | |||
230 | perror("symlink"); | 227 | perror("symlink"); |
231 | } | 228 | } |
232 | else | 229 | else |
233 | printf("%s created\n", fname); | 230 | printf(" %s created\n", name); |
234 | } | 231 | } |
235 | 232 | ||
236 | free(fname); | 233 | free(fname); |
237 | } | 234 | } |
238 | 235 | ||
239 | #define MAX_BUF 1024 | 236 | #define MAX_BUF 1024 |
240 | static void set(void) { | 237 | static void set_links(void) { |
241 | if (getuid() != 0) { | ||
242 | fprintf(stderr, "Error: you need to be root to run this command\n"); | ||
243 | exit(1); | ||
244 | } | ||
245 | |||
246 | char *cfgfile; | 238 | char *cfgfile; |
247 | if (asprintf(&cfgfile, "%s/firejail/firecfg.config", LIBDIR) == -1) | 239 | if (asprintf(&cfgfile, "%s/firejail/firecfg.config", LIBDIR) == -1) |
248 | errExit("asprintf"); | 240 | errExit("asprintf"); |
@@ -256,6 +248,7 @@ static void set(void) { | |||
256 | fprintf(stderr, "Error: cannot open %s\n", cfgfile); | 248 | fprintf(stderr, "Error: cannot open %s\n", cfgfile); |
257 | exit(1); | 249 | exit(1); |
258 | } | 250 | } |
251 | printf("Configuring symlinks in /usr/local/bin\n"); | ||
259 | 252 | ||
260 | char buf[MAX_BUF]; | 253 | char buf[MAX_BUF]; |
261 | int lineno = 0; | 254 | int lineno = 0; |
@@ -294,7 +287,8 @@ static void set(void) { | |||
294 | free(firejail_exec); | 287 | free(firejail_exec); |
295 | } | 288 | } |
296 | 289 | ||
297 | static void fix_desktop_files(void) { | 290 | static void fix_desktop_files(char *homedir) { |
291 | assert(homedir); | ||
298 | struct stat sb; | 292 | struct stat sb; |
299 | 293 | ||
300 | // check user | 294 | // check user |
@@ -302,9 +296,6 @@ static void fix_desktop_files(void) { | |||
302 | fprintf(stderr, "Error: this option is not supported for root user; please run as a regular user.\n"); | 296 | fprintf(stderr, "Error: this option is not supported for root user; please run as a regular user.\n"); |
303 | exit(1); | 297 | exit(1); |
304 | } | 298 | } |
305 | char *homedir = getenv("HOME"); | ||
306 | if (!homedir) | ||
307 | errExit("getenv"); | ||
308 | 299 | ||
309 | // destination | 300 | // destination |
310 | // create ~/.local/share/applications directory if necessary | 301 | // create ~/.local/share/applications directory if necessary |
@@ -333,6 +324,7 @@ static void fix_desktop_files(void) { | |||
333 | exit(1); | 324 | exit(1); |
334 | } | 325 | } |
335 | 326 | ||
327 | printf("\nFixing desktop files in ~/.local/shared/applications\n"); | ||
336 | // copy | 328 | // copy |
337 | struct dirent *entry; | 329 | struct dirent *entry; |
338 | while ((entry = readdir(dir)) != NULL) { | 330 | while ((entry = readdir(dir)) != NULL) { |
@@ -370,7 +362,7 @@ static void fix_desktop_files(void) { | |||
370 | // check format | 362 | // check format |
371 | if (strstr(buf, "[Desktop Entry]\n") == NULL) { | 363 | if (strstr(buf, "[Desktop Entry]\n") == NULL) { |
372 | if (arg_debug) | 364 | if (arg_debug) |
373 | fprintf(stderr, "/usr/share/applications/%s - SKIPPED: wrong format?\n", filename); | 365 | printf(" %s - SKIPPED: wrong format?\n", filename); |
374 | munmap(buf, sb.st_size + 1); | 366 | munmap(buf, sb.st_size + 1); |
375 | continue; | 367 | continue; |
376 | } | 368 | } |
@@ -379,7 +371,7 @@ static void fix_desktop_files(void) { | |||
379 | char *ptr1 = strstr(buf,"\nExec="); | 371 | char *ptr1 = strstr(buf,"\nExec="); |
380 | if (!ptr1 || strlen(ptr1) < 7) { | 372 | if (!ptr1 || strlen(ptr1) < 7) { |
381 | if (arg_debug) | 373 | if (arg_debug) |
382 | fprintf(stderr, "/usr/share/applications/%s - SKIPPED: wrong format?\n", filename); | 374 | printf(" %s - SKIPPED: wrong format?\n", filename); |
383 | munmap(buf, sb.st_size + 1); | 375 | munmap(buf, sb.st_size + 1); |
384 | continue; | 376 | continue; |
385 | } | 377 | } |
@@ -390,13 +382,13 @@ static void fix_desktop_files(void) { | |||
390 | // or with the name of the executable only | 382 | // or with the name of the executable only |
391 | if (execname[0] != '/') { | 383 | if (execname[0] != '/') { |
392 | if (arg_debug) | 384 | if (arg_debug) |
393 | fprintf(stderr, "/usr/share/applications/%s - already OK\n", filename); | 385 | printf(" %s - already OK\n", filename); |
394 | continue; | 386 | continue; |
395 | } | 387 | } |
396 | // executable name can be quoted, this is rare and currently unsupported, TODO | 388 | // executable name can be quoted, this is rare and currently unsupported, TODO |
397 | if (execname[0] == '"') { | 389 | if (execname[0] == '"') { |
398 | if (arg_debug) | 390 | if (arg_debug) |
399 | fprintf(stderr, "/usr/share/applications/%s - skipped: path quoting unsupported\n", filename); | 391 | printf(" %s - skipped: path quoting unsupported\n", filename); |
400 | continue; | 392 | continue; |
401 | } | 393 | } |
402 | 394 | ||
@@ -423,7 +415,7 @@ static void fix_desktop_files(void) { | |||
423 | 415 | ||
424 | // check if basename in PATH | 416 | // check if basename in PATH |
425 | if (!which(bname)) { | 417 | if (!which(bname)) { |
426 | fprintf(stderr, "/usr/share/applications/%s - skipped, %s not in PATH\n", filename, bname); | 418 | printf(" %s - skipped, %s not in PATH\n", filename, bname); |
427 | continue; | 419 | continue; |
428 | } | 420 | } |
429 | 421 | ||
@@ -435,14 +427,14 @@ static void fix_desktop_files(void) { | |||
435 | free(outname); | 427 | free(outname); |
436 | 428 | ||
437 | if (fd1 == -1) { | 429 | if (fd1 == -1) { |
438 | fprintf(stderr, "%s/%s skipped: %s\n", user_apps_dir, filename, strerror(errno)); | 430 | printf(" %s skipped: %s\n", filename, strerror(errno)); |
439 | munmap(buf, sb.st_size + 1); | 431 | munmap(buf, sb.st_size + 1); |
440 | continue; | 432 | continue; |
441 | } | 433 | } |
442 | 434 | ||
443 | FILE *outfile = fdopen(fd1, "w"); | 435 | FILE *outfile = fdopen(fd1, "w"); |
444 | if (!outfile) { | 436 | if (!outfile) { |
445 | fprintf(stderr, "%s/%s skipped: %s\n", user_apps_dir, filename, strerror(errno)); | 437 | printf(" %s skipped: %s\n", filename, strerror(errno)); |
446 | munmap(buf, sb.st_size + 1); | 438 | munmap(buf, sb.st_size + 1); |
447 | close(fd1); | 439 | close(fd1); |
448 | continue; | 440 | continue; |
@@ -460,7 +452,7 @@ static void fix_desktop_files(void) { | |||
460 | fclose(outfile); | 452 | fclose(outfile); |
461 | munmap(buf, sb.st_size + 1); | 453 | munmap(buf, sb.st_size + 1); |
462 | 454 | ||
463 | printf("%s/%s created\n", user_apps_dir, filename); | 455 | printf(" %s created\n", filename); |
464 | } | 456 | } |
465 | 457 | ||
466 | closedir(dir); | 458 | closedir(dir); |
@@ -491,10 +483,6 @@ int main(int argc, char **argv) { | |||
491 | list(); | 483 | list(); |
492 | return 0; | 484 | return 0; |
493 | } | 485 | } |
494 | else if (strcmp(argv[i], "--fix") == 0) { | ||
495 | fix_desktop_files(); | ||
496 | return 0; | ||
497 | } | ||
498 | else { | 486 | else { |
499 | fprintf(stderr, "Error: invalid command line option\n"); | 487 | fprintf(stderr, "Error: invalid command line option\n"); |
500 | usage(); | 488 | usage(); |
@@ -502,8 +490,45 @@ int main(int argc, char **argv) { | |||
502 | } | 490 | } |
503 | } | 491 | } |
504 | 492 | ||
505 | set(); | 493 | // set symlinks in /usr/local/bin |
494 | if (getuid() != 0) { | ||
495 | fprintf(stderr, "Error: you need to be root to run this command\n"); | ||
496 | exit(1); | ||
497 | } | ||
498 | set_links(); | ||
499 | |||
500 | |||
501 | |||
502 | // switch to the local user, and fix desktop files | ||
503 | char *user = getlogin(); | ||
504 | if (!user) | ||
505 | goto errexit; | ||
506 | if (user) { | ||
507 | // find home directory | ||
508 | struct passwd *pw = getpwnam(user); | ||
509 | if (!pw) | ||
510 | goto errexit; | ||
511 | char *home = pw->pw_dir; | ||
512 | if (!home) | ||
513 | goto errexit; | ||
514 | |||
515 | // drop permissions | ||
516 | if (setgroups(0, NULL) < 0) | ||
517 | errExit("setgroups"); | ||
518 | // set uid/gid | ||
519 | if (setgid(pw->pw_gid) < 0) | ||
520 | errExit("setgid"); | ||
521 | if (setuid(pw->pw_uid) < 0) | ||
522 | errExit("setuid"); | ||
523 | if (arg_debug) | ||
524 | printf("%s %d %d %d %d\n", user, getuid(), getgid(), geteuid(), getegid()); | ||
525 | fix_desktop_files(home); | ||
526 | } | ||
506 | 527 | ||
507 | return 0; | 528 | return 0; |
529 | |||
530 | errexit: | ||
531 | fprintf(stderr, "Error: cannot set desktop files in ~/.local/share/applications\n"); | ||
532 | return 1; | ||
508 | } | 533 | } |
509 | 534 | ||
diff --git a/src/man/firecfg.txt b/src/man/firecfg.txt index b9d336c4c..369c3a7e0 100644 --- a/src/man/firecfg.txt +++ b/src/man/firecfg.txt | |||
@@ -5,12 +5,14 @@ Firecfg \- Desktop configuration program for Firejail software. | |||
5 | firecfg [OPTIONS] | 5 | firecfg [OPTIONS] |
6 | .SH DESCRIPTION | 6 | .SH DESCRIPTION |
7 | Firecfg is the desktop configuration utility for Firejail software. The utility | 7 | Firecfg is the desktop configuration utility for Firejail software. The utility |
8 | creates several symbolic links to firejail executable. This allows the user to | 8 | creates several symbolic links to firejail executable in /usr/local/bin. |
9 | sandbox applications automatically, just by clicking on a regular desktop | 9 | |
10 | Firecfg also checks .desktop files in /usr/share/applications/, | ||
11 | replaces the full path by program name, and writes the result to $HOME/.local/share/applications/. | ||
12 | This allows the user to sandbox applications automatically, just by clicking on regular desktop | ||
10 | menus and icons. | 13 | menus and icons. |
11 | 14 | ||
12 | The symbolic links are placed in /usr/local/bin. For more information, see | 15 | For more information, see \fBDESKTOP INTEGRATION\fR section in \fBman 1 firejail\fR. |
13 | \fBDESKTOP INTEGRATION\fR section in \fBman 1 firejail\fR. | ||
14 | 16 | ||
15 | .SH OPTIONS | 17 | .SH OPTIONS |
16 | .TP | 18 | .TP |
@@ -26,9 +28,6 @@ Print options end exit. | |||
26 | \fB\-\-list | 28 | \fB\-\-list |
27 | List all firejail symbolic links | 29 | List all firejail symbolic links |
28 | .TP | 30 | .TP |
29 | \fB\-\-fix | ||
30 | Fix .desktop files. Some .desktop files use full path to executable. Firecfg will check .desktop files in /usr/share/applications/, replace full path by name if it is in PATH, and write result to $HOME/.local/share/applications/. | ||
31 | .TP | ||
32 | \fB\-\-version | 31 | \fB\-\-version |
33 | Print program version and exit. | 32 | Print program version and exit. |
34 | 33 | ||
@@ -61,14 +60,6 @@ $ sudo firecfg --clean | |||
61 | /usr/local/bin/vlc removed | 60 | /usr/local/bin/vlc removed |
62 | .br | 61 | .br |
63 | [...] | 62 | [...] |
64 | .br | ||
65 | $ firecfg --fix | ||
66 | .br | ||
67 | /home/user/.local/share/applications/chromium.desktop created | ||
68 | .br | ||
69 | /home/user/.local/share/applications/vlc.desktop created | ||
70 | .br | ||
71 | [...] | ||
72 | 63 | ||
73 | 64 | ||
74 | .SH LICENSE | 65 | .SH LICENSE |
diff --git a/src/man/firejail.txt b/src/man/firejail.txt index bb940840c..23d34ec25 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt | |||
@@ -1985,6 +1985,8 @@ $ firejail --tree | |||
1985 | 1221:netblue:/usr/lib/firefox/firefox | 1985 | 1221:netblue:/usr/lib/firefox/firefox |
1986 | .RE | 1986 | .RE |
1987 | 1987 | ||
1988 | For more information, see \fBman 1 firecfg\fR. | ||
1989 | |||
1988 | .SH APPARMOR | 1990 | .SH APPARMOR |
1989 | .TP | 1991 | .TP |
1990 | AppArmor support is disabled by default at compile time. Use --enable-apparmor configuration option to enable it: | 1992 | AppArmor support is disabled by default at compile time. Use --enable-apparmor configuration option to enable it: |