diff options
author | netblue30 <netblue30@yahoo.com> | 2018-08-25 11:03:25 -0400 |
---|---|---|
committer | netblue30 <netblue30@yahoo.com> | 2018-08-25 11:03:25 -0400 |
commit | fc7a9505c56192b5fc0ca62eb51fa7f0d8b1cef8 (patch) | |
tree | d30903ff5e8d4a10ddae3a2576f363c4159e0e69 /src/firecfg | |
parent | cleanup, small improvements (diff) | |
download | firejail-fc7a9505c56192b5fc0ca62eb51fa7f0d8b1cef8.tar.gz firejail-fc7a9505c56192b5fc0ca62eb51fa7f0d8b1cef8.tar.zst firejail-fc7a9505c56192b5fc0ca62eb51fa7f0d8b1cef8.zip |
support for local user directories in firecfg (--bindir)
Diffstat (limited to 'src/firecfg')
-rw-r--r-- | src/firecfg/main.c | 178 |
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" |
23 | int arg_debug = 0; | 23 | int arg_debug = 0; |
24 | char *arg_bindir = "/usr/local/bin"; | ||
24 | 25 | ||
25 | static char *usage_str = | 26 | static 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 | ||
64 | static void list(void) { | 66 | static 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 | ||
99 | static void clean(void) { | 101 | static 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 | ||
282 | static 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 | |||
295 | static 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 | |||
310 | errexit: | ||
311 | fprintf(stderr, "Error: cannot find home directory for user %s\n", user); | ||
312 | exit(1); | ||
313 | } | ||
281 | 314 | ||
282 | int main(int argc, char **argv) { | 315 | int 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 | ||
419 | errexit: | 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 | } |