1 /* SPDX-License-Identifier: LGPL-2.1+ */
5 #include <sys/utsname.h>
10 #include "alloc-util.h"
11 #include "apparmor-util.h"
12 #include "architecture.h"
13 #include "audit-util.h"
14 #include "cgroup-util.h"
15 #include "condition.h"
17 #include "hostname-util.h"
18 #include "id128-util.h"
22 #include "nulstr-util.h"
23 #include "selinux-util.h"
25 #include "smack-util.h"
26 #include "string-util.h"
29 #include "tomoyo-util.h"
30 #include "user-util.h"
33 static void test_condition_test_path(void) {
36 condition
= condition_new(CONDITION_PATH_EXISTS
, "/bin/sh", false, false);
38 assert_se(condition_test(condition
));
39 condition_free(condition
);
41 condition
= condition_new(CONDITION_PATH_EXISTS
, "/bin/s?", false, false);
43 assert_se(!condition_test(condition
));
44 condition_free(condition
);
46 condition
= condition_new(CONDITION_PATH_EXISTS_GLOB
, "/bin/s?", false, false);
48 assert_se(condition_test(condition
));
49 condition_free(condition
);
51 condition
= condition_new(CONDITION_PATH_EXISTS_GLOB
, "/bin/s?", false, true);
53 assert_se(!condition_test(condition
));
54 condition_free(condition
);
56 condition
= condition_new(CONDITION_PATH_EXISTS
, "/thiscertainlywontexist", false, false);
58 assert_se(!condition_test(condition
));
59 condition_free(condition
);
61 condition
= condition_new(CONDITION_PATH_EXISTS
, "/thiscertainlywontexist", false, true);
63 assert_se(condition_test(condition
));
64 condition_free(condition
);
66 condition
= condition_new(CONDITION_PATH_IS_DIRECTORY
, "/bin", false, false);
68 assert_se(condition_test(condition
));
69 condition_free(condition
);
71 condition
= condition_new(CONDITION_DIRECTORY_NOT_EMPTY
, "/bin", false, false);
73 assert_se(condition_test(condition
));
74 condition_free(condition
);
76 condition
= condition_new(CONDITION_FILE_NOT_EMPTY
, "/bin/sh", false, false);
78 assert_se(condition_test(condition
));
79 condition_free(condition
);
81 condition
= condition_new(CONDITION_FILE_IS_EXECUTABLE
, "/bin/sh", false, false);
83 assert_se(condition_test(condition
));
84 condition_free(condition
);
86 condition
= condition_new(CONDITION_FILE_IS_EXECUTABLE
, "/etc/passwd", false, false);
88 assert_se(!condition_test(condition
));
89 condition_free(condition
);
91 condition
= condition_new(CONDITION_PATH_IS_MOUNT_POINT
, "/proc", false, false);
93 assert_se(condition_test(condition
));
94 condition_free(condition
);
96 condition
= condition_new(CONDITION_PATH_IS_MOUNT_POINT
, "/", false, false);
98 assert_se(condition_test(condition
));
99 condition_free(condition
);
101 condition
= condition_new(CONDITION_PATH_IS_MOUNT_POINT
, "/bin", false, false);
102 assert_se(condition
);
103 assert_se(!condition_test(condition
));
104 condition_free(condition
);
106 condition
= condition_new(CONDITION_PATH_IS_READ_WRITE
, "/tmp", false, false);
107 assert_se(condition
);
108 assert_se(condition_test(condition
));
109 condition_free(condition
);
111 condition
= condition_new(CONDITION_PATH_IS_SYMBOLIC_LINK
, "/dev/stdout", false, false);
112 assert_se(condition
);
113 assert_se(condition_test(condition
));
114 condition_free(condition
);
117 static void test_condition_test_control_group_controller(void) {
118 Condition
*condition
;
119 CGroupMask system_mask
;
120 CGroupController controller
;
121 _cleanup_free_
char *controller_name
= NULL
;
124 r
= cg_unified_flush();
126 log_notice_errno(r
, "Skipping ConditionControlGroupController tests: %m");
130 /* Invalid controllers are ignored */
131 condition
= condition_new(CONDITION_CONTROL_GROUP_CONTROLLER
, "thisisnotarealcontroller", false, false);
132 assert_se(condition
);
133 assert_se(condition_test(condition
));
134 condition_free(condition
);
136 condition
= condition_new(CONDITION_CONTROL_GROUP_CONTROLLER
, "thisisnotarealcontroller", false, true);
137 assert_se(condition
);
138 assert_se(!condition_test(condition
));
139 condition_free(condition
);
141 assert_se(cg_mask_supported(&system_mask
) >= 0);
143 /* Individual valid controllers one by one */
144 for (controller
= 0; controller
< _CGROUP_CONTROLLER_MAX
; controller
++) {
145 const char *local_controller_name
= cgroup_controller_to_string(controller
);
146 log_info("chosen controller is '%s'", local_controller_name
);
147 if (system_mask
& CGROUP_CONTROLLER_TO_MASK(controller
)) {
148 log_info("this controller is available");
149 condition
= condition_new(CONDITION_CONTROL_GROUP_CONTROLLER
, local_controller_name
, false, false);
150 assert_se(condition
);
151 assert_se(condition_test(condition
));
152 condition_free(condition
);
154 condition
= condition_new(CONDITION_CONTROL_GROUP_CONTROLLER
, local_controller_name
, false, true);
155 assert_se(condition
);
156 assert_se(!condition_test(condition
));
157 condition_free(condition
);
159 log_info("this controller is unavailable");
160 condition
= condition_new(CONDITION_CONTROL_GROUP_CONTROLLER
, local_controller_name
, false, false);
161 assert_se(condition
);
162 assert_se(!condition_test(condition
));
163 condition_free(condition
);
165 condition
= condition_new(CONDITION_CONTROL_GROUP_CONTROLLER
, local_controller_name
, false, true);
166 assert_se(condition
);
167 assert_se(condition_test(condition
));
168 condition_free(condition
);
172 /* Multiple valid controllers at the same time */
173 assert_se(cg_mask_to_string(system_mask
, &controller_name
) >= 0);
175 condition
= condition_new(CONDITION_CONTROL_GROUP_CONTROLLER
, strempty(controller_name
), false, false);
176 assert_se(condition
);
177 assert_se(condition_test(condition
));
178 condition_free(condition
);
180 condition
= condition_new(CONDITION_CONTROL_GROUP_CONTROLLER
, strempty(controller_name
), false, true);
181 assert_se(condition
);
182 assert_se(!condition_test(condition
));
183 condition_free(condition
);
186 static void test_condition_test_ac_power(void) {
187 Condition
*condition
;
189 condition
= condition_new(CONDITION_AC_POWER
, "true", false, false);
190 assert_se(condition
);
191 assert_se(condition_test(condition
) == on_ac_power());
192 condition_free(condition
);
194 condition
= condition_new(CONDITION_AC_POWER
, "false", false, false);
195 assert_se(condition
);
196 assert_se(condition_test(condition
) != on_ac_power());
197 condition_free(condition
);
199 condition
= condition_new(CONDITION_AC_POWER
, "false", false, true);
200 assert_se(condition
);
201 assert_se(condition_test(condition
) == on_ac_power());
202 condition_free(condition
);
205 static void test_condition_test_host(void) {
206 _cleanup_free_
char *hostname
= NULL
;
207 char sid
[SD_ID128_STRING_MAX
];
208 Condition
*condition
;
212 r
= sd_id128_get_machine(&id
);
214 assert_se(sd_id128_to_string(id
, sid
));
216 condition
= condition_new(CONDITION_HOST
, sid
, false, false);
217 assert_se(condition
);
218 assert_se(condition_test(condition
));
219 condition_free(condition
);
221 condition
= condition_new(CONDITION_HOST
, "garbage value jjjjjjjjjjjjjj", false, false);
222 assert_se(condition
);
223 assert_se(!condition_test(condition
));
224 condition_free(condition
);
226 condition
= condition_new(CONDITION_HOST
, sid
, false, true);
227 assert_se(condition
);
228 assert_se(!condition_test(condition
));
229 condition_free(condition
);
231 hostname
= gethostname_malloc();
234 /* if hostname looks like an id128 then skip testing it */
235 if (id128_is_valid(hostname
))
236 log_notice("hostname is an id128, skipping test");
238 condition
= condition_new(CONDITION_HOST
, hostname
, false, false);
239 assert_se(condition
);
240 assert_se(condition_test(condition
));
241 condition_free(condition
);
245 static void test_condition_test_architecture(void) {
246 Condition
*condition
;
250 a
= uname_architecture();
253 sa
= architecture_to_string(a
);
256 condition
= condition_new(CONDITION_ARCHITECTURE
, sa
, false, false);
257 assert_se(condition
);
258 assert_se(condition_test(condition
) > 0);
259 condition_free(condition
);
261 condition
= condition_new(CONDITION_ARCHITECTURE
, "garbage value", false, false);
262 assert_se(condition
);
263 assert_se(condition_test(condition
) == 0);
264 condition_free(condition
);
266 condition
= condition_new(CONDITION_ARCHITECTURE
, sa
, false, true);
267 assert_se(condition
);
268 assert_se(condition_test(condition
) == 0);
269 condition_free(condition
);
272 static void test_condition_test_kernel_command_line(void) {
273 Condition
*condition
;
275 condition
= condition_new(CONDITION_KERNEL_COMMAND_LINE
, "thisreallyshouldntbeonthekernelcommandline", false, false);
276 assert_se(condition
);
277 assert_se(!condition_test(condition
));
278 condition_free(condition
);
280 condition
= condition_new(CONDITION_KERNEL_COMMAND_LINE
, "andthis=neither", false, false);
281 assert_se(condition
);
282 assert_se(!condition_test(condition
));
283 condition_free(condition
);
286 static void test_condition_test_kernel_version(void) {
287 Condition
*condition
;
291 condition
= condition_new(CONDITION_KERNEL_VERSION
, "*thisreallyshouldntbeinthekernelversion*", false, false);
292 assert_se(condition
);
293 assert_se(!condition_test(condition
));
294 condition_free(condition
);
296 condition
= condition_new(CONDITION_KERNEL_VERSION
, "*", false, false);
297 assert_se(condition
);
298 assert_se(condition_test(condition
));
299 condition_free(condition
);
301 condition
= condition_new(CONDITION_KERNEL_VERSION
, "", false, false);
302 assert_se(condition
);
303 assert_se(!condition_test(condition
));
304 condition_free(condition
);
306 assert_se(uname(&u
) >= 0);
308 condition
= condition_new(CONDITION_KERNEL_VERSION
, u
.release
, false, false);
309 assert_se(condition
);
310 assert_se(condition_test(condition
));
311 condition_free(condition
);
313 strshorten(u
.release
, 4);
314 strcpy(strchr(u
.release
, 0), "*");
316 condition
= condition_new(CONDITION_KERNEL_VERSION
, u
.release
, false, false);
317 assert_se(condition
);
318 assert_se(condition_test(condition
));
319 condition_free(condition
);
321 /* 0.1.2 would be a very very very old kernel */
322 condition
= condition_new(CONDITION_KERNEL_VERSION
, "> 0.1.2", false, false);
323 assert_se(condition
);
324 assert_se(condition_test(condition
));
325 condition_free(condition
);
327 condition
= condition_new(CONDITION_KERNEL_VERSION
, ">= 0.1.2", false, false);
328 assert_se(condition
);
329 assert_se(condition_test(condition
));
330 condition_free(condition
);
332 condition
= condition_new(CONDITION_KERNEL_VERSION
, "< 0.1.2", false, false);
333 assert_se(condition
);
334 assert_se(!condition_test(condition
));
335 condition_free(condition
);
337 condition
= condition_new(CONDITION_KERNEL_VERSION
, "<= 0.1.2", false, false);
338 assert_se(condition
);
339 assert_se(!condition_test(condition
));
340 condition_free(condition
);
342 condition
= condition_new(CONDITION_KERNEL_VERSION
, "= 0.1.2", false, false);
343 assert_se(condition
);
344 assert_se(!condition_test(condition
));
345 condition_free(condition
);
347 /* 4711.8.15 is a very very very future kernel */
348 condition
= condition_new(CONDITION_KERNEL_VERSION
, "< 4711.8.15", false, false);
349 assert_se(condition
);
350 assert_se(condition_test(condition
));
351 condition_free(condition
);
353 condition
= condition_new(CONDITION_KERNEL_VERSION
, "<= 4711.8.15", false, false);
354 assert_se(condition
);
355 assert_se(condition_test(condition
));
356 condition_free(condition
);
358 condition
= condition_new(CONDITION_KERNEL_VERSION
, "= 4711.8.15", false, false);
359 assert_se(condition
);
360 assert_se(!condition_test(condition
));
361 condition_free(condition
);
363 condition
= condition_new(CONDITION_KERNEL_VERSION
, "> 4711.8.15", false, false);
364 assert_se(condition
);
365 assert_se(!condition_test(condition
));
366 condition_free(condition
);
368 condition
= condition_new(CONDITION_KERNEL_VERSION
, ">= 4711.8.15", false, false);
369 assert_se(condition
);
370 assert_se(!condition_test(condition
));
371 condition_free(condition
);
373 assert_se(uname(&u
) >= 0);
375 v
= strjoina(">=", u
.release
);
376 condition
= condition_new(CONDITION_KERNEL_VERSION
, v
, false, false);
377 assert_se(condition
);
378 assert_se(condition_test(condition
));
379 condition_free(condition
);
381 v
= strjoina("= ", u
.release
);
382 condition
= condition_new(CONDITION_KERNEL_VERSION
, v
, false, false);
383 assert_se(condition
);
384 assert_se(condition_test(condition
));
385 condition_free(condition
);
387 v
= strjoina("<=", u
.release
);
388 condition
= condition_new(CONDITION_KERNEL_VERSION
, v
, false, false);
389 assert_se(condition
);
390 assert_se(condition_test(condition
));
391 condition_free(condition
);
393 v
= strjoina("> ", u
.release
);
394 condition
= condition_new(CONDITION_KERNEL_VERSION
, v
, false, false);
395 assert_se(condition
);
396 assert_se(!condition_test(condition
));
397 condition_free(condition
);
399 v
= strjoina("< ", u
.release
);
400 condition
= condition_new(CONDITION_KERNEL_VERSION
, v
, false, false);
401 assert_se(condition
);
402 assert_se(!condition_test(condition
));
403 condition_free(condition
);
406 static void test_condition_test_null(void) {
407 Condition
*condition
;
409 condition
= condition_new(CONDITION_NULL
, NULL
, false, false);
410 assert_se(condition
);
411 assert_se(condition_test(condition
));
412 condition_free(condition
);
414 condition
= condition_new(CONDITION_NULL
, NULL
, false, true);
415 assert_se(condition
);
416 assert_se(!condition_test(condition
));
417 condition_free(condition
);
420 static void test_condition_test_security(void) {
421 Condition
*condition
;
423 condition
= condition_new(CONDITION_SECURITY
, "garbage oifdsjfoidsjoj", false, false);
424 assert_se(condition
);
425 assert_se(!condition_test(condition
));
426 condition_free(condition
);
428 condition
= condition_new(CONDITION_SECURITY
, "selinux", false, true);
429 assert_se(condition
);
430 assert_se(condition_test(condition
) != mac_selinux_use());
431 condition_free(condition
);
433 condition
= condition_new(CONDITION_SECURITY
, "apparmor", false, false);
434 assert_se(condition
);
435 assert_se(condition_test(condition
) == mac_apparmor_use());
436 condition_free(condition
);
438 condition
= condition_new(CONDITION_SECURITY
, "tomoyo", false, false);
439 assert_se(condition
);
440 assert_se(condition_test(condition
) == mac_tomoyo_use());
441 condition_free(condition
);
443 condition
= condition_new(CONDITION_SECURITY
, "ima", false, false);
444 assert_se(condition
);
445 assert_se(condition_test(condition
) == use_ima());
446 condition_free(condition
);
448 condition
= condition_new(CONDITION_SECURITY
, "smack", false, false);
449 assert_se(condition
);
450 assert_se(condition_test(condition
) == mac_smack_use());
451 condition_free(condition
);
453 condition
= condition_new(CONDITION_SECURITY
, "audit", false, false);
454 assert_se(condition
);
455 assert_se(condition_test(condition
) == use_audit());
456 condition_free(condition
);
458 condition
= condition_new(CONDITION_SECURITY
, "uefi-secureboot", false, false);
459 assert_se(condition
);
460 assert_se(condition_test(condition
) == is_efi_secure_boot());
461 condition_free(condition
);
464 static void print_securities(void) {
465 log_info("------ enabled security technologies ------");
466 log_info("SELinux: %s", yes_no(mac_selinux_use()));
467 log_info("AppArmor: %s", yes_no(mac_apparmor_use()));
468 log_info("Tomoyo: %s", yes_no(mac_tomoyo_use()));
469 log_info("IMA: %s", yes_no(use_ima()));
470 log_info("SMACK: %s", yes_no(mac_smack_use()));
471 log_info("Audit: %s", yes_no(use_audit()));
472 log_info("UEFI secure boot: %s", yes_no(is_efi_secure_boot()));
473 log_info("-------------------------------------------");
476 static void test_condition_test_virtualization(void) {
477 Condition
*condition
;
481 condition
= condition_new(CONDITION_VIRTUALIZATION
, "garbage oifdsjfoidsjoj", false, false);
482 assert_se(condition
);
483 r
= condition_test(condition
);
484 log_info("ConditionVirtualization=garbage → %i", r
);
486 condition_free(condition
);
488 condition
= condition_new(CONDITION_VIRTUALIZATION
, "container", false, false);
489 assert_se(condition
);
490 r
= condition_test(condition
);
491 log_info("ConditionVirtualization=container → %i", r
);
492 assert_se(r
== !!detect_container());
493 condition_free(condition
);
495 condition
= condition_new(CONDITION_VIRTUALIZATION
, "vm", false, false);
496 assert_se(condition
);
497 r
= condition_test(condition
);
498 log_info("ConditionVirtualization=vm → %i", r
);
499 assert_se(r
== (detect_vm() && !detect_container()));
500 condition_free(condition
);
502 condition
= condition_new(CONDITION_VIRTUALIZATION
, "private-users", false, false);
503 assert_se(condition
);
504 r
= condition_test(condition
);
505 log_info("ConditionVirtualization=private-users → %i", r
);
506 assert_se(r
== !!running_in_userns());
507 condition_free(condition
);
523 condition
= condition_new(CONDITION_VIRTUALIZATION
, virt
, false, false);
524 assert_se(condition
);
525 r
= condition_test(condition
);
526 log_info("ConditionVirtualization=%s → %i", virt
, r
);
528 condition_free(condition
);
532 static void test_condition_test_user(void) {
533 Condition
*condition
;
538 condition
= condition_new(CONDITION_USER
, "garbage oifdsjfoidsjoj", false, false);
539 assert_se(condition
);
540 r
= condition_test(condition
);
541 log_info("ConditionUser=garbage → %i", r
);
543 condition_free(condition
);
545 assert_se(asprintf(&uid
, "%"PRIu32
, UINT32_C(0xFFFF)) > 0);
546 condition
= condition_new(CONDITION_USER
, uid
, false, false);
547 assert_se(condition
);
548 r
= condition_test(condition
);
549 log_info("ConditionUser=%s → %i", uid
, r
);
551 condition_free(condition
);
554 assert_se(asprintf(&uid
, "%u", (unsigned)getuid()) > 0);
555 condition
= condition_new(CONDITION_USER
, uid
, false, false);
556 assert_se(condition
);
557 r
= condition_test(condition
);
558 log_info("ConditionUser=%s → %i", uid
, r
);
560 condition_free(condition
);
563 assert_se(asprintf(&uid
, "%u", (unsigned)getuid()+1) > 0);
564 condition
= condition_new(CONDITION_USER
, uid
, false, false);
565 assert_se(condition
);
566 r
= condition_test(condition
);
567 log_info("ConditionUser=%s → %i", uid
, r
);
569 condition_free(condition
);
572 username
= getusername_malloc();
574 condition
= condition_new(CONDITION_USER
, username
, false, false);
575 assert_se(condition
);
576 r
= condition_test(condition
);
577 log_info("ConditionUser=%s → %i", username
, r
);
579 condition_free(condition
);
582 username
= (char*)(geteuid() == 0 ? NOBODY_USER_NAME
: "root");
583 condition
= condition_new(CONDITION_USER
, username
, false, false);
584 assert_se(condition
);
585 r
= condition_test(condition
);
586 log_info("ConditionUser=%s → %i", username
, r
);
588 condition_free(condition
);
590 condition
= condition_new(CONDITION_USER
, "@system", false, false);
591 assert_se(condition
);
592 r
= condition_test(condition
);
593 log_info("ConditionUser=@system → %i", r
);
594 if (uid_is_system(getuid()) || uid_is_system(geteuid()))
598 condition_free(condition
);
601 static void test_condition_test_group(void) {
602 Condition
*condition
;
605 gid_t
*gids
, max_gid
;
606 int ngroups_max
, ngroups
, r
, i
;
608 assert_se(0 < asprintf(&gid
, "%u", UINT32_C(0xFFFF)));
609 condition
= condition_new(CONDITION_GROUP
, gid
, false, false);
610 assert_se(condition
);
611 r
= condition_test(condition
);
612 log_info("ConditionGroup=%s → %i", gid
, r
);
614 condition_free(condition
);
617 assert_se(0 < asprintf(&gid
, "%u", getgid()));
618 condition
= condition_new(CONDITION_GROUP
, gid
, false, false);
619 assert_se(condition
);
620 r
= condition_test(condition
);
621 log_info("ConditionGroup=%s → %i", gid
, r
);
623 condition_free(condition
);
626 ngroups_max
= sysconf(_SC_NGROUPS_MAX
);
627 assert(ngroups_max
> 0);
629 gids
= newa(gid_t
, ngroups_max
);
631 ngroups
= getgroups(ngroups_max
, gids
);
632 assert(ngroups
>= 0);
635 for (i
= 0; i
< ngroups
; i
++) {
636 assert_se(0 < asprintf(&gid
, "%u", gids
[i
]));
637 condition
= condition_new(CONDITION_GROUP
, gid
, false, false);
638 assert_se(condition
);
639 r
= condition_test(condition
);
640 log_info("ConditionGroup=%s → %i", gid
, r
);
642 condition_free(condition
);
644 max_gid
= gids
[i
] > max_gid
? gids
[i
] : max_gid
;
646 groupname
= gid_to_name(gids
[i
]);
647 assert_se(groupname
);
648 condition
= condition_new(CONDITION_GROUP
, groupname
, false, false);
649 assert_se(condition
);
650 r
= condition_test(condition
);
651 log_info("ConditionGroup=%s → %i", groupname
, r
);
653 condition_free(condition
);
655 max_gid
= gids
[i
] > max_gid
? gids
[i
] : max_gid
;
658 assert_se(0 < asprintf(&gid
, "%u", max_gid
+1));
659 condition
= condition_new(CONDITION_GROUP
, gid
, false, false);
660 assert_se(condition
);
661 r
= condition_test(condition
);
662 log_info("ConditionGroup=%s → %i", gid
, r
);
664 condition_free(condition
);
667 groupname
= (char*)(geteuid() == 0 ? NOBODY_GROUP_NAME
: "root");
668 condition
= condition_new(CONDITION_GROUP
, groupname
, false, false);
669 assert_se(condition
);
670 r
= condition_test(condition
);
671 log_info("ConditionGroup=%s → %i", groupname
, r
);
673 condition_free(condition
);
676 int main(int argc
, char *argv
[]) {
677 test_setup_logging(LOG_DEBUG
);
679 test_condition_test_path();
680 test_condition_test_ac_power();
681 test_condition_test_host();
682 test_condition_test_architecture();
683 test_condition_test_kernel_command_line();
684 test_condition_test_kernel_version();
685 test_condition_test_null();
686 test_condition_test_security();
688 test_condition_test_virtualization();
689 test_condition_test_user();
690 test_condition_test_group();
691 test_condition_test_control_group_controller();