diff options
author | netblue30 <netblue30@protonmail.com> | 2023-12-04 09:11:08 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-04 09:11:08 -0500 |
commit | 2033e98e79721c82cb704dcc46b37cdb58afd986 (patch) | |
tree | dea825dcf577e7c178f2f4f9bf8d0741cab6f147 /src/firecfg | |
parent | RELNOTES: add modif, bugfix, build and contrib items (diff) | |
parent | firecfg: add ignore command and docs (diff) | |
download | firejail-2033e98e79721c82cb704dcc46b37cdb58afd986.tar.gz firejail-2033e98e79721c82cb704dcc46b37cdb58afd986.tar.zst firejail-2033e98e79721c82cb704dcc46b37cdb58afd986.zip |
Merge pull request #5876 from kmk3/firecfg-add-confdir-ignore
feature: firecfg: add firecfg.d & add ignore command
Diffstat (limited to 'src/firecfg')
-rw-r--r-- | src/firecfg/firecfg.h | 10 | ||||
-rw-r--r-- | src/firecfg/main.c | 145 |
2 files changed, 106 insertions, 49 deletions
diff --git a/src/firecfg/firecfg.h b/src/firecfg/firecfg.h index 8f74a1198..11e3ebc67 100644 --- a/src/firecfg/firecfg.h +++ b/src/firecfg/firecfg.h | |||
@@ -37,6 +37,16 @@ | |||
37 | #include "../include/common.h" | 37 | #include "../include/common.h" |
38 | #define MAX_BUF 4096 | 38 | #define MAX_BUF 4096 |
39 | 39 | ||
40 | // config files | ||
41 | #define FIRECFG_CFGFILE SYSCONFDIR "/firecfg.config" | ||
42 | #define FIRECFG_CONF_GLOB SYSCONFDIR "/firecfg.d/*.conf" | ||
43 | |||
44 | // programs | ||
45 | #define FIREJAIL_EXEC PREFIX "/bin/firejail" | ||
46 | #define FIREJAIL_WELCOME_SH LIBDIR "/firejail/firejail-welcome.sh" | ||
47 | #define FZENITY_EXEC LIBDIR "/firejail/fzenity" | ||
48 | #define ZENITY_EXEC "/usr/bin/zenity" | ||
49 | #define SUDO_EXEC "sudo" | ||
40 | 50 | ||
41 | // main.c | 51 | // main.c |
42 | extern int arg_debug; | 52 | extern int arg_debug; |
diff --git a/src/firecfg/main.c b/src/firecfg/main.c index 4ec81c5b3..604b12633 100644 --- a/src/firecfg/main.c +++ b/src/firecfg/main.c | |||
@@ -20,6 +20,8 @@ | |||
20 | 20 | ||
21 | #include "firecfg.h" | 21 | #include "firecfg.h" |
22 | #include "../include/firejail_user.h" | 22 | #include "../include/firejail_user.h" |
23 | #include <glob.h> | ||
24 | |||
23 | int arg_debug = 0; | 25 | int arg_debug = 0; |
24 | char *arg_bindir = "/usr/local/bin"; | 26 | char *arg_bindir = "/usr/local/bin"; |
25 | int arg_guide = 0; | 27 | int arg_guide = 0; |
@@ -76,10 +78,6 @@ static void list(void) { | |||
76 | exit(1); | 78 | exit(1); |
77 | } | 79 | } |
78 | 80 | ||
79 | char *firejail_exec; | ||
80 | if (asprintf(&firejail_exec, "%s/bin/firejail", PREFIX) == -1) | ||
81 | errExit("asprintf"); | ||
82 | |||
83 | struct dirent *entry; | 81 | struct dirent *entry; |
84 | while ((entry = readdir(dir)) != NULL) { | 82 | while ((entry = readdir(dir)) != NULL) { |
85 | if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) | 83 | if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) |
@@ -92,7 +90,7 @@ static void list(void) { | |||
92 | if (is_link(fullname)) { | 90 | if (is_link(fullname)) { |
93 | char* fname = realpath(fullname, NULL); | 91 | char* fname = realpath(fullname, NULL); |
94 | if (fname) { | 92 | if (fname) { |
95 | if (strcmp(fname, firejail_exec) == 0) | 93 | if (strcmp(fname, FIREJAIL_EXEC) == 0) |
96 | printf("%s\n", fullname); | 94 | printf("%s\n", fullname); |
97 | free(fname); | 95 | free(fname); |
98 | } | 96 | } |
@@ -101,7 +99,6 @@ static void list(void) { | |||
101 | } | 99 | } |
102 | 100 | ||
103 | closedir(dir); | 101 | closedir(dir); |
104 | free(firejail_exec); | ||
105 | } | 102 | } |
106 | 103 | ||
107 | static void clean(void) { | 104 | static void clean(void) { |
@@ -114,10 +111,6 @@ static void clean(void) { | |||
114 | exit(1); | 111 | exit(1); |
115 | } | 112 | } |
116 | 113 | ||
117 | char *firejail_exec; | ||
118 | if (asprintf(&firejail_exec, "%s/bin/firejail", PREFIX) == -1) | ||
119 | errExit("asprintf"); | ||
120 | |||
121 | struct dirent *entry; | 114 | struct dirent *entry; |
122 | while ((entry = readdir(dir)) != NULL) { | 115 | while ((entry = readdir(dir)) != NULL) { |
123 | if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) | 116 | if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) |
@@ -130,7 +123,7 @@ static void clean(void) { | |||
130 | if (is_link(fullname)) { | 123 | if (is_link(fullname)) { |
131 | char* fname = realpath(fullname, NULL); | 124 | char* fname = realpath(fullname, NULL); |
132 | if (fname) { | 125 | if (fname) { |
133 | if (strcmp(fname, firejail_exec) == 0) { | 126 | if (strcmp(fname, FIREJAIL_EXEC) == 0) { |
134 | char *ptr = strrchr(fullname, '/'); | 127 | char *ptr = strrchr(fullname, '/'); |
135 | assert(ptr); | 128 | assert(ptr); |
136 | ptr++; | 129 | ptr++; |
@@ -147,10 +140,43 @@ static void clean(void) { | |||
147 | } | 140 | } |
148 | 141 | ||
149 | closedir(dir); | 142 | closedir(dir); |
150 | free(firejail_exec); | ||
151 | printf("\n"); | 143 | printf("\n"); |
152 | } | 144 | } |
153 | 145 | ||
146 | #define ignorelist_maxlen 2048 | ||
147 | static const char *ignorelist[ignorelist_maxlen]; | ||
148 | static int ignorelist_len = 0; | ||
149 | |||
150 | static int append_ignorelist(const char *const str) { | ||
151 | assert(str); | ||
152 | if (ignorelist_len >= ignorelist_maxlen) { | ||
153 | fprintf(stderr, "Warning: Ignore list is full (%d/%d), skipping %s\n", | ||
154 | ignorelist_len, ignorelist_maxlen, str); | ||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | printf(" ignoring '%s'\n", str); | ||
159 | const char *const dup = strdup(str); | ||
160 | if (!dup) | ||
161 | errExit("strdup"); | ||
162 | |||
163 | ignorelist[ignorelist_len] = dup; | ||
164 | ignorelist_len++; | ||
165 | |||
166 | return 1; | ||
167 | } | ||
168 | |||
169 | static int in_ignorelist(const char *const str) { | ||
170 | assert(str); | ||
171 | int i; | ||
172 | for (i = 0; i < ignorelist_len; i++) { | ||
173 | if (strcmp(str, ignorelist[i]) == 0) | ||
174 | return 1; | ||
175 | } | ||
176 | |||
177 | return 0; | ||
178 | } | ||
179 | |||
154 | static void set_file(const char *name, const char *firejail_exec) { | 180 | static void set_file(const char *name, const char *firejail_exec) { |
155 | if (which(name) == 0) | 181 | if (which(name) == 0) |
156 | return; | 182 | return; |
@@ -165,35 +191,26 @@ static void set_file(const char *name, const char *firejail_exec) { | |||
165 | if (rv) { | 191 | if (rv) { |
166 | fprintf(stderr, "Error: cannot create %s symbolic link\n", fname); | 192 | fprintf(stderr, "Error: cannot create %s symbolic link\n", fname); |
167 | perror("symlink"); | 193 | perror("symlink"); |
168 | } | 194 | } else { |
169 | else | ||
170 | printf(" %s created\n", name); | 195 | printf(" %s created\n", name); |
171 | } | 196 | } |
172 | else { | 197 | } else { |
173 | fprintf(stderr, "Warning: cannot create %s - already exists! Skipping...\n", fname); | 198 | fprintf(stderr, "Warning: cannot create %s - already exists! Skipping...\n", fname); |
174 | } | 199 | } |
175 | 200 | ||
176 | free(fname); | 201 | free(fname); |
177 | } | 202 | } |
178 | 203 | ||
179 | // parse /etc/firejail/firecfg.config file | 204 | // parse a single config file |
180 | static void set_links_firecfg(void) { | 205 | static void set_links_firecfg(const char *cfgfile) { |
181 | char *cfgfile; | 206 | printf("Configuring symlinks in %s based on %s\n", arg_bindir, cfgfile); |
182 | if (asprintf(&cfgfile, "%s/firecfg.config", SYSCONFDIR) == -1) | ||
183 | errExit("asprintf"); | ||
184 | |||
185 | char *firejail_exec; | ||
186 | if (asprintf(&firejail_exec, "%s/bin/firejail", PREFIX) == -1) | ||
187 | errExit("asprintf"); | ||
188 | 207 | ||
189 | // parse /etc/firejail/firecfg.config file | ||
190 | FILE *fp = fopen(cfgfile, "r"); | 208 | FILE *fp = fopen(cfgfile, "r"); |
191 | if (!fp) { | 209 | if (!fp) { |
192 | perror("fopen"); | 210 | perror("fopen"); |
193 | fprintf(stderr, "Error: cannot open %s\n", cfgfile); | 211 | fprintf(stderr, "Error: cannot open %s\n", cfgfile); |
194 | exit(1); | 212 | exit(1); |
195 | } | 213 | } |
196 | printf("Configuring symlinks in %s based on firecfg.config\n", arg_bindir); | ||
197 | 214 | ||
198 | char buf[MAX_BUF]; | 215 | char buf[MAX_BUF]; |
199 | int lineno = 0; | 216 | int lineno = 0; |
@@ -223,13 +240,43 @@ static void set_links_firecfg(void) { | |||
223 | if (*start == '\0') | 240 | if (*start == '\0') |
224 | continue; | 241 | continue; |
225 | 242 | ||
243 | // handle ignore command | ||
244 | if (*start == '!') { | ||
245 | append_ignorelist(start + 1); | ||
246 | continue; | ||
247 | } | ||
248 | |||
226 | // set link | 249 | // set link |
227 | set_file(start, firejail_exec); | 250 | if (!in_ignorelist(start)) |
251 | set_file(start, FIREJAIL_EXEC); | ||
252 | else | ||
253 | printf(" %s ignored\n", start); | ||
228 | } | 254 | } |
229 | 255 | ||
230 | fclose(fp); | 256 | fclose(fp); |
231 | free(cfgfile); | 257 | printf("\n"); |
232 | free(firejail_exec); | 258 | } |
259 | |||
260 | // parse all config files matching pattern | ||
261 | static void set_links_firecfg_glob(const char *pattern) { | ||
262 | printf("Looking for config files in %s\n", pattern); | ||
263 | |||
264 | glob_t globbuf; | ||
265 | int globerr = glob(pattern, 0, NULL, &globbuf); | ||
266 | if (globerr == GLOB_NOMATCH) { | ||
267 | fprintf(stderr, "No matches for glob pattern %s\n", pattern); | ||
268 | goto out; | ||
269 | } else if (globerr != 0) { | ||
270 | fprintf(stderr, "Warning: Failed to match glob pattern %s: %s\n", | ||
271 | pattern, strerror(errno)); | ||
272 | goto out; | ||
273 | } | ||
274 | |||
275 | size_t i; | ||
276 | for (i = 0; i < globbuf.gl_pathc; i++) | ||
277 | set_links_firecfg(globbuf.gl_pathv[i]); | ||
278 | out: | ||
279 | globfree(&globbuf); | ||
233 | } | 280 | } |
234 | 281 | ||
235 | // parse ~/.config/firejail/ directory | 282 | // parse ~/.config/firejail/ directory |
@@ -246,10 +293,6 @@ static void set_links_homedir(const char *homedir) { | |||
246 | return; | 293 | return; |
247 | } | 294 | } |
248 | 295 | ||
249 | char *firejail_exec; | ||
250 | if (asprintf(&firejail_exec, "%s/bin/firejail", PREFIX) == -1) | ||
251 | errExit("asprintf"); | ||
252 | |||
253 | // parse ~/.config/firejail/ directory | 296 | // parse ~/.config/firejail/ directory |
254 | printf("\nConfiguring symlinks in %s based on local firejail config directory\n", arg_bindir); | 297 | printf("\nConfiguring symlinks in %s based on local firejail config directory\n", arg_bindir); |
255 | 298 | ||
@@ -260,6 +303,7 @@ static void set_links_homedir(const char *homedir) { | |||
260 | free(dirname); | 303 | free(dirname); |
261 | return; | 304 | return; |
262 | } | 305 | } |
306 | free(dirname); | ||
263 | 307 | ||
264 | struct dirent *entry; | 308 | struct dirent *entry; |
265 | while ((entry = readdir(dir))) { | 309 | while ((entry = readdir(dir))) { |
@@ -280,12 +324,10 @@ static void set_links_homedir(const char *homedir) { | |||
280 | } | 324 | } |
281 | 325 | ||
282 | *ptr = '\0'; | 326 | *ptr = '\0'; |
283 | set_file(exec, firejail_exec); | 327 | set_file(exec, FIREJAIL_EXEC); |
284 | free(exec); | 328 | free(exec); |
285 | } | 329 | } |
286 | closedir(dir); | 330 | closedir(dir); |
287 | |||
288 | free(firejail_exec); | ||
289 | } | 331 | } |
290 | 332 | ||
291 | static const char *get_sudo_user(void) { | 333 | static const char *get_sudo_user(void) { |
@@ -449,18 +491,20 @@ int main(int argc, char **argv) { | |||
449 | } | 491 | } |
450 | 492 | ||
451 | if (arg_guide) { | 493 | if (arg_guide) { |
494 | const char *zenity_exec; | ||
495 | if (arg_debug) | ||
496 | zenity_exec = FZENITY_EXEC; | ||
497 | else | ||
498 | zenity_exec = ZENITY_EXEC; | ||
499 | |||
452 | char *cmd; | 500 | char *cmd; |
453 | if (arg_debug) { | 501 | if (asprintf(&cmd, "%s %s %s %s %s", |
454 | if (asprintf(&cmd, "sudo %s/firejail/firejail-welcome.sh /usr/lib/firejail/fzenity %s %s", LIBDIR, SYSCONFDIR, user) == -1) | 502 | SUDO_EXEC, FIREJAIL_WELCOME_SH, zenity_exec, SYSCONFDIR, user) == -1) |
455 | errExit("asprintf"); | 503 | errExit("asprintf"); |
456 | } | 504 | |
457 | else { | ||
458 | if (asprintf(&cmd, "sudo %s/firejail/firejail-welcome.sh /usr/bin/zenity %s %s", LIBDIR, SYSCONFDIR, user) == -1) | ||
459 | errExit("asprintf"); | ||
460 | } | ||
461 | int status = system(cmd); | 505 | int status = system(cmd); |
462 | if (status == -1) { | 506 | if (status == -1) { |
463 | fprintf(stderr, "Error: cannot run firejail-welcome.sh\n"); | 507 | fprintf(stderr, "Error: cannot run %s\n", FIREJAIL_WELCOME_SH); |
464 | exit(1); | 508 | exit(1); |
465 | } | 509 | } |
466 | free(cmd); | 510 | free(cmd); |
@@ -474,12 +518,15 @@ else { | |||
474 | // clear all symlinks | 518 | // clear all symlinks |
475 | clean(); | 519 | clean(); |
476 | 520 | ||
477 | // set new symlinks based on /etc/firejail/firecfg.config | 521 | // set new symlinks based on .conf files |
478 | set_links_firecfg(); | 522 | set_links_firecfg_glob(FIRECFG_CONF_GLOB); |
523 | |||
524 | // set new symlinks based on firecfg.config | ||
525 | set_links_firecfg(FIRECFG_CFGFILE); | ||
479 | 526 | ||
480 | if (getuid() == 0) { | 527 | if (getuid() == 0) { |
481 | // add user to firejail access database - only for root | 528 | // add user to firejail access database - only for root |
482 | printf("\nAdding user %s to Firejail access database in %s/firejail.users\n", user, SYSCONFDIR); | 529 | printf("Adding user %s to Firejail access database in %s/firejail.users\n", user, SYSCONFDIR); |
483 | // temporarily set the umask, access database must be world-readable | 530 | // temporarily set the umask, access database must be world-readable |
484 | mode_t orig_umask = umask(022); | 531 | mode_t orig_umask = umask(022); |
485 | firejail_user_add(user); | 532 | firejail_user_add(user); |