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