diff options
-rw-r--r-- | src/firejail/profile.c | 52 | ||||
-rw-r--r-- | test/profiles/cond1.profile | 1 | ||||
-rw-r--r-- | test/profiles/cond2.profile | 1 | ||||
-rw-r--r-- | test/profiles/cond3.profile | 1 | ||||
-rwxr-xr-x | test/profiles/conditional.exp | 47 | ||||
-rwxr-xr-x | test/profiles/profiles.sh | 3 |
6 files changed, 88 insertions, 17 deletions
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index a6d619f38..83caef199 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -34,11 +34,12 @@ static int profile_find(const char *name, const char *dir, int add_ext) { | |||
34 | int rv = 0; | 34 | int rv = 0; |
35 | DIR *dp; | 35 | DIR *dp; |
36 | char *pname = NULL; | 36 | char *pname = NULL; |
37 | if (add_ext) | 37 | if (add_ext) { |
38 | if (asprintf(&pname, "%s.profile", name) == -1) | 38 | if (asprintf(&pname, "%s.profile", name) == -1) |
39 | errExit("asprintf"); | 39 | errExit("asprintf"); |
40 | else | 40 | else |
41 | name = pname; | 41 | name = pname; |
42 | } | ||
42 | 43 | ||
43 | dp = opendir (dir); | 44 | dp = opendir (dir); |
44 | if (dp != NULL) { | 45 | if (dp != NULL) { |
@@ -133,40 +134,54 @@ void profile_add_ignore(const char *str) { | |||
133 | } | 134 | } |
134 | } | 135 | } |
135 | 136 | ||
137 | typedef struct cond_t { | ||
138 | const char *name; // conditional name | ||
139 | int (*check)(void); // true if set | ||
140 | } Cond; | ||
141 | |||
142 | static int check_appimage(void) { | ||
143 | return arg_appimage != 0; | ||
144 | } | ||
145 | |||
146 | static int check_nodbus(void) { | ||
147 | return arg_nodbus != 0; | ||
148 | } | ||
149 | |||
150 | static int check_disable_u2f(void) { | ||
151 | return checkcfg(CFG_BROWSER_DISABLE_U2F) != 0; | ||
152 | } | ||
153 | |||
154 | Cond conditionals[] = { | ||
155 | {"HAS_APPIMAGE", check_appimage}, | ||
156 | {"HAS_NODBUS", check_nodbus}, | ||
157 | {"BROWSER_DISABLE_U2F", check_disable_u2f}, | ||
158 | { NULL, NULL } | ||
159 | }; | ||
136 | 160 | ||
137 | int profile_check_conditional(char *ptr, int lineno, const char *fname) { | 161 | int profile_check_conditional(char *ptr, int lineno, const char *fname) { |
138 | struct cond_t { | ||
139 | char *name; // conditional name | ||
140 | size_t len; // length of name | ||
141 | bool value; // true if set | ||
142 | } conditionals[] = { | ||
143 | {"HAS_APPIMAGE", strlen("HAS_APPIMAGE"), arg_appimage!=0}, | ||
144 | {"HAS_NODBUS", strlen("HAS_NODBUS"), arg_nodbus!=0}, | ||
145 | {"BROWSER_DISABLE_U2F", strlen("BROWSER_DISABLE_U2F"), checkcfg(CFG_BROWSER_DISABLE_U2F)!=0}, | ||
146 | NULL | ||
147 | }, *cond = conditionals; | ||
148 | char *tmp = ptr, *msg = NULL; | 162 | char *tmp = ptr, *msg = NULL; |
149 | 163 | ||
150 | if (*ptr++ != '?') | 164 | if (*ptr++ != '?') |
151 | return 1; | 165 | return 1; |
152 | 166 | ||
167 | Cond *cond = conditionals; | ||
153 | while (cond->name) { | 168 | while (cond->name) { |
154 | // continue if not this conditional | 169 | // continue if not this conditional |
155 | if (strncmp(ptr, cond->name, cond->len) != 0) { | 170 | if (strncmp(ptr, cond->name, strlen(cond->name)) != 0) { |
156 | cond++; | 171 | cond++; |
157 | continue; | 172 | continue; |
158 | } | 173 | } |
159 | ptr += cond->len; | 174 | ptr += strlen(cond->name); |
160 | 175 | ||
161 | if (*ptr == ' ') | 176 | if (*ptr == ' ') |
162 | ptr++; | 177 | ptr++; |
163 | if (*ptr++ != ':') { | 178 | if (*ptr++ != ':') { |
164 | msg = "invalid syntax: colon must come after conditional"; | 179 | msg = "invalid conditional syntax: colon must come after conditional"; |
165 | ptr = tmp; | 180 | ptr = tmp; |
166 | goto error; | 181 | goto error; |
167 | } | 182 | } |
168 | if (*ptr == '\0') { | 183 | if (*ptr == '\0') { |
169 | msg = "invalid conditional line: no profile line after conditional"; | 184 | msg = "invalid conditional syntax: no profile line after conditional"; |
170 | ptr = tmp; | 185 | ptr = tmp; |
171 | goto error; | 186 | goto error; |
172 | } | 187 | } |
@@ -174,7 +189,8 @@ int profile_check_conditional(char *ptr, int lineno, const char *fname) { | |||
174 | ptr++; | 189 | ptr++; |
175 | 190 | ||
176 | // if set, continue processing statement in caller | 191 | // if set, continue processing statement in caller |
177 | if (cond->value) { | 192 | int value = cond->check(); |
193 | if (value) { | ||
178 | // move ptr to start of profile line | 194 | // move ptr to start of profile line |
179 | ptr = strdup(ptr); | 195 | ptr = strdup(ptr); |
180 | if (!ptr) | 196 | if (!ptr) |
@@ -184,13 +200,15 @@ int profile_check_conditional(char *ptr, int lineno, const char *fname) { | |||
184 | // quiet or include directives | 200 | // quiet or include directives |
185 | if ((strncmp(ptr, "quiet", 5) == 0) || | 201 | if ((strncmp(ptr, "quiet", 5) == 0) || |
186 | (strncmp(ptr, "include", 7) == 0)) { | 202 | (strncmp(ptr, "include", 7) == 0)) { |
187 | msg = "invalid profile line: quiet and include not allowed in conditionals"; | 203 | msg = "invalid conditional syntax: quiet and include not allowed in conditionals"; |
188 | ptr = tmp; | 204 | ptr = tmp; |
189 | goto error; | 205 | goto error; |
190 | } | 206 | } |
191 | free(tmp); | 207 | free(tmp); |
192 | 208 | ||
193 | // verify syntax, exit in case of error | 209 | // verify syntax, exit in case of error |
210 | if (arg_debug) | ||
211 | printf("conditional %s, %s\n", cond->name, ptr); | ||
194 | if (profile_check_line(ptr, lineno, fname)) | 212 | if (profile_check_line(ptr, lineno, fname)) |
195 | profile_add(ptr); | 213 | profile_add(ptr); |
196 | } | 214 | } |
diff --git a/test/profiles/cond1.profile b/test/profiles/cond1.profile new file mode 100644 index 000000000..207914d66 --- /dev/null +++ b/test/profiles/cond1.profile | |||
@@ -0,0 +1 @@ | |||
?HAS_NODBUS: private | |||
diff --git a/test/profiles/cond2.profile b/test/profiles/cond2.profile new file mode 100644 index 000000000..078efe161 --- /dev/null +++ b/test/profiles/cond2.profile | |||
@@ -0,0 +1 @@ | |||
?HAS_NODBUSprivate | |||
diff --git a/test/profiles/cond3.profile b/test/profiles/cond3.profile new file mode 100644 index 000000000..7cc9ac1e0 --- /dev/null +++ b/test/profiles/cond3.profile | |||
@@ -0,0 +1 @@ | |||
?HAS_NODBUS | |||
diff --git a/test/profiles/conditional.exp b/test/profiles/conditional.exp new file mode 100755 index 000000000..537fb361e --- /dev/null +++ b/test/profiles/conditional.exp | |||
@@ -0,0 +1,47 @@ | |||
1 | #!/usr/bin/expect -f | ||
2 | # This file is part of Firejail project | ||
3 | # Copyright (C) 2014-2018 Firejail Authors | ||
4 | # License GPL v2 | ||
5 | |||
6 | set timeout 10 | ||
7 | spawn $env(SHELL) | ||
8 | match_max 100000 | ||
9 | |||
10 | send -- "firejail --debug --nodbus --profile=cond1.profile\r" | ||
11 | expect { | ||
12 | timeout {puts "TESTING ERROR 0\n";exit} | ||
13 | "conditional HAS_NODBUS, private" | ||
14 | } | ||
15 | expect { | ||
16 | timeout {puts "TESTING ERROR 1\n";exit} | ||
17 | "Child process initialized" | ||
18 | } | ||
19 | after 100 | ||
20 | send -- "exit\r" | ||
21 | sleep 1 | ||
22 | |||
23 | send -- "firejail --debug --profile=cond1.profile\r" | ||
24 | expect { | ||
25 | timeout {puts "TESTING ERROR 2\n";exit} | ||
26 | "conditional HAS_NODBUS, private" {puts "TESTING ERROR 3\n";exit} | ||
27 | "Child process initialized" | ||
28 | } | ||
29 | after 100 | ||
30 | send -- "exit\r" | ||
31 | sleep 1 | ||
32 | |||
33 | send -- "firejail --profile=cond2.profile\r" | ||
34 | expect { | ||
35 | timeout {puts "TESTING ERROR 4\n";exit} | ||
36 | "invalid conditional syntax" | ||
37 | } | ||
38 | after 100 | ||
39 | |||
40 | send -- "firejail --profile=cond3.profile\r" | ||
41 | expect { | ||
42 | timeout {puts "TESTING ERROR 5\n";exit} | ||
43 | "invalid conditional syntax" | ||
44 | } | ||
45 | after 100 | ||
46 | |||
47 | puts "\nall done\n" | ||
diff --git a/test/profiles/profiles.sh b/test/profiles/profiles.sh index a3d24ac0c..33729927c 100755 --- a/test/profiles/profiles.sh +++ b/test/profiles/profiles.sh | |||
@@ -6,6 +6,9 @@ | |||
6 | export MALLOC_CHECK_=3 | 6 | export MALLOC_CHECK_=3 |
7 | export MALLOC_PERTURB_=$(($RANDOM % 255 + 1)) | 7 | export MALLOC_PERTURB_=$(($RANDOM % 255 + 1)) |
8 | 8 | ||
9 | echo "TESTING: profile conditional (test/profiles/conditional.exp)" | ||
10 | ./conditional.exp | ||
11 | |||
9 | echo "TESTING: profile recursivity (test/profiles/profile_recursivity.exp)" | 12 | echo "TESTING: profile recursivity (test/profiles/profile_recursivity.exp)" |
10 | ./profile_recursivity.exp | 13 | ./profile_recursivity.exp |
11 | 14 | ||