]>
Commit | Line | Data |
---|---|---|
b08f2be6 RC |
1 | /*** |
2 | This file is part of systemd | |
3 | ||
4 | Copyright 2014 Ronny Chevalier | |
5 | ||
6 | systemd is free software; you can redistribute it and/or modify it | |
7 | under the terms of the GNU Lesser General Public License as published by | |
8 | the Free Software Foundation; either version 2.1 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | systemd is distributed in the hope that it will be useful, but | |
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | Lesser General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU Lesser General Public License | |
17 | along with systemd; If not, see <http://www.gnu.org/licenses/>. | |
18 | ***/ | |
19 | ||
c465a29f FS |
20 | #include <stdio.h> |
21 | #include <sys/types.h> | |
22 | #include <unistd.h> | |
23 | ||
d1bddcec | 24 | #include "sd-id128.h" |
07630cea | 25 | |
b5efdb8a | 26 | #include "alloc-util.h" |
07630cea LP |
27 | #include "apparmor-util.h" |
28 | #include "architecture.h" | |
430f0182 | 29 | #include "audit-util.h" |
07630cea LP |
30 | #include "condition.h" |
31 | #include "hostname-util.h" | |
40a23924 | 32 | #include "id128-util.h" |
015df1f7 | 33 | #include "ima-util.h" |
07630cea LP |
34 | #include "log.h" |
35 | #include "macro.h" | |
36 | #include "selinux-util.h" | |
015df1f7 | 37 | #include "smack-util.h" |
239a5707 ZJS |
38 | #include "strv.h" |
39 | #include "virt.h" | |
07630cea | 40 | #include "util.h" |
c465a29f | 41 | #include "user-util.h" |
d1bddcec | 42 | |
015df1f7 | 43 | static void test_condition_test_path(void) { |
d1bddcec LP |
44 | Condition *condition; |
45 | ||
46 | condition = condition_new(CONDITION_PATH_EXISTS, "/bin/sh", false, false); | |
4d548a7d | 47 | assert_se(condition); |
d1bddcec LP |
48 | assert_se(condition_test(condition)); |
49 | condition_free(condition); | |
50 | ||
b80ba1da | 51 | condition = condition_new(CONDITION_PATH_EXISTS, "/bin/s?", false, false); |
4d548a7d | 52 | assert_se(condition); |
b80ba1da LP |
53 | assert_se(!condition_test(condition)); |
54 | condition_free(condition); | |
55 | ||
56 | condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, false); | |
4d548a7d | 57 | assert_se(condition); |
b80ba1da LP |
58 | assert_se(condition_test(condition)); |
59 | condition_free(condition); | |
60 | ||
61 | condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, true); | |
4d548a7d | 62 | assert_se(condition); |
b80ba1da LP |
63 | assert_se(!condition_test(condition)); |
64 | condition_free(condition); | |
65 | ||
d1bddcec | 66 | condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, false); |
4d548a7d | 67 | assert_se(condition); |
d1bddcec LP |
68 | assert_se(!condition_test(condition)); |
69 | condition_free(condition); | |
70 | ||
71 | condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, true); | |
4d548a7d | 72 | assert_se(condition); |
d1bddcec LP |
73 | assert_se(condition_test(condition)); |
74 | condition_free(condition); | |
b80ba1da LP |
75 | |
76 | condition = condition_new(CONDITION_PATH_IS_DIRECTORY, "/bin", false, false); | |
4d548a7d | 77 | assert_se(condition); |
b80ba1da LP |
78 | assert_se(condition_test(condition)); |
79 | condition_free(condition); | |
80 | ||
81 | condition = condition_new(CONDITION_DIRECTORY_NOT_EMPTY, "/bin", false, false); | |
4d548a7d | 82 | assert_se(condition); |
b80ba1da LP |
83 | assert_se(condition_test(condition)); |
84 | condition_free(condition); | |
85 | ||
86 | condition = condition_new(CONDITION_FILE_NOT_EMPTY, "/bin/sh", false, false); | |
4d548a7d | 87 | assert_se(condition); |
b80ba1da LP |
88 | assert_se(condition_test(condition)); |
89 | condition_free(condition); | |
90 | ||
91 | condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/bin/sh", false, false); | |
4d548a7d | 92 | assert_se(condition); |
b80ba1da LP |
93 | assert_se(condition_test(condition)); |
94 | condition_free(condition); | |
95 | ||
96 | condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/etc/passwd", false, false); | |
4d548a7d | 97 | assert_se(condition); |
b80ba1da LP |
98 | assert_se(!condition_test(condition)); |
99 | condition_free(condition); | |
100 | ||
101 | condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/proc", false, false); | |
4d548a7d | 102 | assert_se(condition); |
b80ba1da LP |
103 | assert_se(condition_test(condition)); |
104 | condition_free(condition); | |
105 | ||
106 | condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/", false, false); | |
4d548a7d | 107 | assert_se(condition); |
b80ba1da LP |
108 | assert_se(condition_test(condition)); |
109 | condition_free(condition); | |
110 | ||
111 | condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/bin", false, false); | |
4d548a7d | 112 | assert_se(condition); |
b80ba1da LP |
113 | assert_se(!condition_test(condition)); |
114 | condition_free(condition); | |
015df1f7 RC |
115 | |
116 | condition = condition_new(CONDITION_PATH_IS_READ_WRITE, "/tmp", false, false); | |
4d548a7d | 117 | assert_se(condition); |
015df1f7 RC |
118 | assert_se(condition_test(condition)); |
119 | condition_free(condition); | |
120 | ||
121 | condition = condition_new(CONDITION_PATH_IS_SYMBOLIC_LINK, "/dev/stdout", false, false); | |
4d548a7d | 122 | assert_se(condition); |
015df1f7 RC |
123 | assert_se(condition_test(condition)); |
124 | condition_free(condition); | |
d1bddcec | 125 | } |
b08f2be6 RC |
126 | |
127 | static void test_condition_test_ac_power(void) { | |
128 | Condition *condition; | |
129 | ||
130 | condition = condition_new(CONDITION_AC_POWER, "true", false, false); | |
4d548a7d | 131 | assert_se(condition); |
d1bddcec | 132 | assert_se(condition_test(condition) == on_ac_power()); |
b08f2be6 RC |
133 | condition_free(condition); |
134 | ||
135 | condition = condition_new(CONDITION_AC_POWER, "false", false, false); | |
4d548a7d | 136 | assert_se(condition); |
d1bddcec | 137 | assert_se(condition_test(condition) != on_ac_power()); |
b08f2be6 RC |
138 | condition_free(condition); |
139 | ||
140 | condition = condition_new(CONDITION_AC_POWER, "false", false, true); | |
4d548a7d | 141 | assert_se(condition); |
d1bddcec | 142 | assert_se(condition_test(condition) == on_ac_power()); |
b08f2be6 RC |
143 | condition_free(condition); |
144 | } | |
145 | ||
146 | static void test_condition_test_host(void) { | |
4d548a7d LP |
147 | _cleanup_free_ char *hostname = NULL; |
148 | char sid[SD_ID128_STRING_MAX]; | |
b08f2be6 RC |
149 | Condition *condition; |
150 | sd_id128_t id; | |
151 | int r; | |
b08f2be6 RC |
152 | |
153 | r = sd_id128_get_machine(&id); | |
154 | assert_se(r >= 0); | |
155 | assert_se(sd_id128_to_string(id, sid)); | |
156 | ||
157 | condition = condition_new(CONDITION_HOST, sid, false, false); | |
4d548a7d | 158 | assert_se(condition); |
d1bddcec | 159 | assert_se(condition_test(condition)); |
b08f2be6 RC |
160 | condition_free(condition); |
161 | ||
162 | condition = condition_new(CONDITION_HOST, "garbage value jjjjjjjjjjjjjj", false, false); | |
4d548a7d | 163 | assert_se(condition); |
d1bddcec | 164 | assert_se(!condition_test(condition)); |
b08f2be6 RC |
165 | condition_free(condition); |
166 | ||
167 | condition = condition_new(CONDITION_HOST, sid, false, true); | |
4d548a7d | 168 | assert_se(condition); |
d1bddcec | 169 | assert_se(!condition_test(condition)); |
b08f2be6 RC |
170 | condition_free(condition); |
171 | ||
172 | hostname = gethostname_malloc(); | |
173 | assert_se(hostname); | |
174 | ||
40a23924 | 175 | /* if hostname looks like an id128 then skip testing it */ |
ce5fcc69 | 176 | if (id128_is_valid(hostname)) |
40a23924 | 177 | log_notice("hostname is an id128, skipping test"); |
ce5fcc69 | 178 | else { |
40a23924 | 179 | condition = condition_new(CONDITION_HOST, hostname, false, false); |
4d548a7d | 180 | assert_se(condition); |
40a23924 SM |
181 | assert_se(condition_test(condition)); |
182 | condition_free(condition); | |
183 | } | |
b08f2be6 RC |
184 | } |
185 | ||
186 | static void test_condition_test_architecture(void) { | |
187 | Condition *condition; | |
b08f2be6 | 188 | const char *sa; |
592fd144 | 189 | int a; |
b08f2be6 RC |
190 | |
191 | a = uname_architecture(); | |
192 | assert_se(a >= 0); | |
193 | ||
194 | sa = architecture_to_string(a); | |
195 | assert_se(sa); | |
196 | ||
197 | condition = condition_new(CONDITION_ARCHITECTURE, sa, false, false); | |
4d548a7d | 198 | assert_se(condition); |
2cb62395 | 199 | assert_se(condition_test(condition) > 0); |
b08f2be6 RC |
200 | condition_free(condition); |
201 | ||
202 | condition = condition_new(CONDITION_ARCHITECTURE, "garbage value", false, false); | |
4d548a7d | 203 | assert_se(condition); |
2cb62395 | 204 | assert_se(condition_test(condition) == 0); |
b08f2be6 RC |
205 | condition_free(condition); |
206 | ||
207 | condition = condition_new(CONDITION_ARCHITECTURE, sa, false, true); | |
4d548a7d | 208 | assert_se(condition); |
2cb62395 | 209 | assert_se(condition_test(condition) == 0); |
b08f2be6 RC |
210 | condition_free(condition); |
211 | } | |
212 | ||
07318c29 LP |
213 | static void test_condition_test_kernel_command_line(void) { |
214 | Condition *condition; | |
215 | ||
216 | condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "thisreallyshouldntbeonthekernelcommandline", false, false); | |
4d548a7d | 217 | assert_se(condition); |
d1bddcec | 218 | assert_se(!condition_test(condition)); |
07318c29 LP |
219 | condition_free(condition); |
220 | ||
221 | condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "andthis=neither", false, false); | |
4d548a7d | 222 | assert_se(condition); |
d1bddcec | 223 | assert_se(!condition_test(condition)); |
07318c29 LP |
224 | condition_free(condition); |
225 | } | |
226 | ||
b80ba1da LP |
227 | static void test_condition_test_null(void) { |
228 | Condition *condition; | |
229 | ||
230 | condition = condition_new(CONDITION_NULL, NULL, false, false); | |
4d548a7d | 231 | assert_se(condition); |
b80ba1da LP |
232 | assert_se(condition_test(condition)); |
233 | condition_free(condition); | |
234 | ||
235 | condition = condition_new(CONDITION_NULL, NULL, false, true); | |
4d548a7d | 236 | assert_se(condition); |
b80ba1da LP |
237 | assert_se(!condition_test(condition)); |
238 | condition_free(condition); | |
239 | } | |
240 | ||
015df1f7 RC |
241 | static void test_condition_test_security(void) { |
242 | Condition *condition; | |
243 | ||
244 | condition = condition_new(CONDITION_SECURITY, "garbage oifdsjfoidsjoj", false, false); | |
4d548a7d | 245 | assert_se(condition); |
015df1f7 RC |
246 | assert_se(!condition_test(condition)); |
247 | condition_free(condition); | |
248 | ||
249 | condition = condition_new(CONDITION_SECURITY, "selinux", false, true); | |
4d548a7d | 250 | assert_se(condition); |
6d395665 | 251 | assert_se(condition_test(condition) != mac_selinux_use()); |
015df1f7 RC |
252 | condition_free(condition); |
253 | ||
254 | condition = condition_new(CONDITION_SECURITY, "ima", false, false); | |
4d548a7d | 255 | assert_se(condition); |
015df1f7 RC |
256 | assert_se(condition_test(condition) == use_ima()); |
257 | condition_free(condition); | |
258 | ||
259 | condition = condition_new(CONDITION_SECURITY, "apparmor", false, false); | |
4d548a7d | 260 | assert_se(condition); |
015df1f7 RC |
261 | assert_se(condition_test(condition) == mac_apparmor_use()); |
262 | condition_free(condition); | |
263 | ||
264 | condition = condition_new(CONDITION_SECURITY, "smack", false, false); | |
4d548a7d | 265 | assert_se(condition); |
015df1f7 RC |
266 | assert_se(condition_test(condition) == mac_smack_use()); |
267 | condition_free(condition); | |
268 | ||
269 | condition = condition_new(CONDITION_SECURITY, "audit", false, false); | |
4d548a7d | 270 | assert_se(condition); |
015df1f7 RC |
271 | assert_se(condition_test(condition) == use_audit()); |
272 | condition_free(condition); | |
273 | } | |
274 | ||
239a5707 ZJS |
275 | static void test_condition_test_virtualization(void) { |
276 | Condition *condition; | |
277 | const char *virt; | |
278 | int r; | |
279 | ||
280 | condition = condition_new(CONDITION_VIRTUALIZATION, "garbage oifdsjfoidsjoj", false, false); | |
281 | assert_se(condition); | |
282 | r = condition_test(condition); | |
283 | log_info("ConditionVirtualization=garbage → %i", r); | |
284 | assert_se(r == 0); | |
285 | condition_free(condition); | |
286 | ||
287 | condition = condition_new(CONDITION_VIRTUALIZATION, "container", false, false); | |
288 | assert_se(condition); | |
289 | r = condition_test(condition); | |
290 | log_info("ConditionVirtualization=container → %i", r); | |
291 | assert_se(r == !!detect_container()); | |
292 | condition_free(condition); | |
293 | ||
294 | condition = condition_new(CONDITION_VIRTUALIZATION, "vm", false, false); | |
295 | assert_se(condition); | |
296 | r = condition_test(condition); | |
297 | log_info("ConditionVirtualization=vm → %i", r); | |
298 | assert_se(r == (detect_vm() && !detect_container())); | |
299 | condition_free(condition); | |
300 | ||
301 | condition = condition_new(CONDITION_VIRTUALIZATION, "private-users", false, false); | |
302 | assert_se(condition); | |
303 | r = condition_test(condition); | |
304 | log_info("ConditionVirtualization=private-users → %i", r); | |
305 | assert_se(r == !!running_in_userns()); | |
306 | condition_free(condition); | |
307 | ||
308 | NULSTR_FOREACH(virt, | |
309 | "kvm\0" | |
310 | "qemu\0" | |
311 | "bochs\0" | |
312 | "xen\0" | |
313 | "uml\0" | |
314 | "vmware\0" | |
315 | "oracle\0" | |
316 | "microsoft\0" | |
317 | "zvm\0" | |
318 | "parallels\0" | |
319 | "bhyve\0" | |
320 | "vm_other\0") { | |
321 | ||
322 | condition = condition_new(CONDITION_VIRTUALIZATION, virt, false, false); | |
323 | assert_se(condition); | |
324 | r = condition_test(condition); | |
325 | log_info("ConditionVirtualization=%s → %i", virt, r); | |
326 | assert_se(r >= 0); | |
327 | condition_free(condition); | |
328 | } | |
329 | } | |
330 | ||
c465a29f FS |
331 | static void test_condition_test_user(void) { |
332 | Condition *condition; | |
333 | char* uid; | |
334 | char* username; | |
335 | int r; | |
336 | ||
337 | condition = condition_new(CONDITION_USER, "garbage oifdsjfoidsjoj", false, false); | |
338 | assert_se(condition); | |
339 | r = condition_test(condition); | |
340 | log_info("ConditionUser=garbage → %i", r); | |
341 | assert_se(r == 0); | |
342 | condition_free(condition); | |
343 | ||
344 | assert_se(asprintf(&uid, "%"PRIu32, UINT32_C(0xFFFF)) > 0); | |
345 | condition = condition_new(CONDITION_USER, uid, false, false); | |
346 | assert_se(condition); | |
347 | r = condition_test(condition); | |
348 | log_info("ConditionUser=%s → %i", uid, r); | |
349 | assert_se(r == 0); | |
350 | condition_free(condition); | |
351 | free(uid); | |
352 | ||
353 | assert_se(asprintf(&uid, "%u", (unsigned)getuid()) > 0); | |
354 | condition = condition_new(CONDITION_USER, uid, false, false); | |
355 | assert_se(condition); | |
356 | r = condition_test(condition); | |
357 | log_info("ConditionUser=%s → %i", uid, r); | |
358 | assert_se(r > 0); | |
359 | condition_free(condition); | |
360 | free(uid); | |
361 | ||
362 | assert_se(asprintf(&uid, "%u", (unsigned)getuid()+1) > 0); | |
363 | condition = condition_new(CONDITION_USER, uid, false, false); | |
364 | assert_se(condition); | |
365 | r = condition_test(condition); | |
366 | log_info("ConditionUser=%s → %i", uid, r); | |
367 | assert_se(r == 0); | |
368 | condition_free(condition); | |
369 | free(uid); | |
370 | ||
371 | username = getusername_malloc(); | |
372 | assert_se(username); | |
373 | condition = condition_new(CONDITION_USER, username, false, false); | |
374 | assert_se(condition); | |
375 | r = condition_test(condition); | |
376 | log_info("ConditionUser=%s → %i", username, r); | |
377 | assert_se(r > 0); | |
378 | condition_free(condition); | |
379 | free(username); | |
380 | ||
381 | username = (char*)(geteuid() == 0 ? NOBODY_USER_NAME : "root"); | |
382 | condition = condition_new(CONDITION_USER, username, false, false); | |
383 | assert_se(condition); | |
384 | r = condition_test(condition); | |
385 | log_info("ConditionUser=%s → %i", username, r); | |
386 | assert_se(r == 0); | |
387 | condition_free(condition); | |
534bab66 FS |
388 | |
389 | condition = condition_new(CONDITION_USER, "@system", false, false); | |
390 | assert_se(condition); | |
391 | r = condition_test(condition); | |
392 | log_info("ConditionUser=@system → %i", r); | |
393 | if (geteuid() == 0) | |
394 | assert_se(r > 0); | |
395 | else | |
396 | assert_se(r == 0); | |
397 | condition_free(condition); | |
c465a29f FS |
398 | } |
399 | ||
400 | static void test_condition_test_group(void) { | |
401 | Condition *condition; | |
402 | char* gid; | |
403 | char* groupname; | |
404 | gid_t *gids, max_gid; | |
405 | int ngroups_max, r, i; | |
406 | ||
407 | assert_se(0 < asprintf(&gid, "%u", UINT32_C(0xFFFF))); | |
408 | condition = condition_new(CONDITION_GROUP, gid, false, false); | |
409 | assert_se(condition); | |
410 | r = condition_test(condition); | |
411 | log_info("ConditionGroup=%s → %i", gid, r); | |
412 | assert_se(r == 0); | |
413 | condition_free(condition); | |
414 | free(gid); | |
415 | ||
416 | assert_se(0 < asprintf(&gid, "%u", getgid())); | |
417 | condition = condition_new(CONDITION_GROUP, gid, false, false); | |
418 | assert_se(condition); | |
419 | r = condition_test(condition); | |
420 | log_info("ConditionGroup=%s → %i", gid, r); | |
421 | assert_se(r > 0); | |
422 | condition_free(condition); | |
423 | free(gid); | |
424 | ||
425 | ngroups_max = sysconf(_SC_NGROUPS_MAX); | |
426 | assert(ngroups_max > 0); | |
427 | ||
428 | gids = alloca(sizeof(gid_t) * ngroups_max); | |
429 | ||
430 | r = getgroups(ngroups_max, gids); | |
431 | assert(r >= 0); | |
432 | ||
433 | max_gid = getgid(); | |
434 | for (i = 0; i < r; i++) { | |
435 | assert_se(0 < asprintf(&gid, "%u", gids[i])); | |
436 | condition = condition_new(CONDITION_GROUP, gid, false, false); | |
437 | assert_se(condition); | |
438 | r = condition_test(condition); | |
439 | log_info("ConditionGroup=%s → %i", gid, r); | |
440 | assert_se(r > 0); | |
441 | condition_free(condition); | |
442 | free(gid); | |
443 | max_gid = gids[i] > max_gid ? gids[i] : max_gid; | |
444 | ||
445 | groupname = gid_to_name(gids[i]); | |
446 | assert_se(groupname); | |
447 | condition = condition_new(CONDITION_GROUP, groupname, false, false); | |
448 | assert_se(condition); | |
449 | r = condition_test(condition); | |
450 | log_info("ConditionGroup=%s → %i", groupname, r); | |
451 | assert_se(r > 0); | |
452 | condition_free(condition); | |
453 | free(groupname); | |
454 | max_gid = gids[i] > max_gid ? gids[i] : max_gid; | |
455 | } | |
456 | ||
457 | assert_se(0 < asprintf(&gid, "%u", max_gid+1)); | |
458 | condition = condition_new(CONDITION_GROUP, gid, false, false); | |
459 | assert_se(condition); | |
460 | r = condition_test(condition); | |
461 | log_info("ConditionGroup=%s → %i", gid, r); | |
462 | assert_se(r == 0); | |
463 | condition_free(condition); | |
464 | free(gid); | |
465 | ||
466 | groupname = (char*)(geteuid() == 0 ? NOBODY_GROUP_NAME : "root"); | |
467 | condition = condition_new(CONDITION_GROUP, groupname, false, false); | |
468 | assert_se(condition); | |
469 | r = condition_test(condition); | |
470 | log_info("ConditionGroup=%s → %i", groupname, r); | |
471 | assert_se(r == 0); | |
472 | condition_free(condition); | |
473 | } | |
474 | ||
b08f2be6 | 475 | int main(int argc, char *argv[]) { |
239a5707 | 476 | log_set_max_level(LOG_DEBUG); |
b08f2be6 RC |
477 | log_parse_environment(); |
478 | log_open(); | |
479 | ||
015df1f7 | 480 | test_condition_test_path(); |
b08f2be6 RC |
481 | test_condition_test_ac_power(); |
482 | test_condition_test_host(); | |
483 | test_condition_test_architecture(); | |
07318c29 | 484 | test_condition_test_kernel_command_line(); |
b80ba1da | 485 | test_condition_test_null(); |
015df1f7 | 486 | test_condition_test_security(); |
239a5707 | 487 | test_condition_test_virtualization(); |
c465a29f FS |
488 | test_condition_test_user(); |
489 | test_condition_test_group(); | |
b08f2be6 RC |
490 | |
491 | return 0; | |
492 | } |