1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd
5 Copyright 2014 Ronny Chevalier
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.
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.
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/>.
22 #include <sys/types.h>
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"
38 #include "selinux-util.h"
40 #include "smack-util.h"
44 #include "user-util.h"
46 static void test_condition_test_path(void) {
49 condition
= condition_new(CONDITION_PATH_EXISTS
, "/bin/sh", false, false);
51 assert_se(condition_test(condition
));
52 condition_free(condition
);
54 condition
= condition_new(CONDITION_PATH_EXISTS
, "/bin/s?", false, false);
56 assert_se(!condition_test(condition
));
57 condition_free(condition
);
59 condition
= condition_new(CONDITION_PATH_EXISTS_GLOB
, "/bin/s?", false, false);
61 assert_se(condition_test(condition
));
62 condition_free(condition
);
64 condition
= condition_new(CONDITION_PATH_EXISTS_GLOB
, "/bin/s?", false, true);
66 assert_se(!condition_test(condition
));
67 condition_free(condition
);
69 condition
= condition_new(CONDITION_PATH_EXISTS
, "/thiscertainlywontexist", false, false);
71 assert_se(!condition_test(condition
));
72 condition_free(condition
);
74 condition
= condition_new(CONDITION_PATH_EXISTS
, "/thiscertainlywontexist", false, true);
76 assert_se(condition_test(condition
));
77 condition_free(condition
);
79 condition
= condition_new(CONDITION_PATH_IS_DIRECTORY
, "/bin", false, false);
81 assert_se(condition_test(condition
));
82 condition_free(condition
);
84 condition
= condition_new(CONDITION_DIRECTORY_NOT_EMPTY
, "/bin", false, false);
86 assert_se(condition_test(condition
));
87 condition_free(condition
);
89 condition
= condition_new(CONDITION_FILE_NOT_EMPTY
, "/bin/sh", false, false);
91 assert_se(condition_test(condition
));
92 condition_free(condition
);
94 condition
= condition_new(CONDITION_FILE_IS_EXECUTABLE
, "/bin/sh", false, false);
96 assert_se(condition_test(condition
));
97 condition_free(condition
);
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
);
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
);
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
);
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
);
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
);
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
);
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
;
137 r
= cg_unified_flush();
139 log_notice_errno(r
, "Skipping ConditionControlGroupController tests: %m");
140 return EXIT_TEST_SKIP
;
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
);
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
);
154 assert_se(cg_mask_supported(&system_mask
) >= 0);
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
);
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
);
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
);
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
);
185 /* Multiple valid controllers at the same time */
186 assert_se(cg_mask_to_string(system_mask
, &controller_name
) >= 0);
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
);
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
);
201 static void test_condition_test_ac_power(void) {
202 Condition
*condition
;
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
);
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
);
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
);
220 static void test_condition_test_host(void) {
221 _cleanup_free_
char *hostname
= NULL
;
222 char sid
[SD_ID128_STRING_MAX
];
223 Condition
*condition
;
227 r
= sd_id128_get_machine(&id
);
229 assert_se(sd_id128_to_string(id
, sid
));
231 condition
= condition_new(CONDITION_HOST
, sid
, false, false);
232 assert_se(condition
);
233 assert_se(condition_test(condition
));
234 condition_free(condition
);
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
);
241 condition
= condition_new(CONDITION_HOST
, sid
, false, true);
242 assert_se(condition
);
243 assert_se(!condition_test(condition
));
244 condition_free(condition
);
246 hostname
= gethostname_malloc();
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");
253 condition
= condition_new(CONDITION_HOST
, hostname
, false, false);
254 assert_se(condition
);
255 assert_se(condition_test(condition
));
256 condition_free(condition
);
260 static void test_condition_test_architecture(void) {
261 Condition
*condition
;
265 a
= uname_architecture();
268 sa
= architecture_to_string(a
);
271 condition
= condition_new(CONDITION_ARCHITECTURE
, sa
, false, false);
272 assert_se(condition
);
273 assert_se(condition_test(condition
) > 0);
274 condition_free(condition
);
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
);
281 condition
= condition_new(CONDITION_ARCHITECTURE
, sa
, false, true);
282 assert_se(condition
);
283 assert_se(condition_test(condition
) == 0);
284 condition_free(condition
);
287 static void test_condition_test_kernel_command_line(void) {
288 Condition
*condition
;
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
);
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
);
301 static void test_condition_test_null(void) {
302 Condition
*condition
;
304 condition
= condition_new(CONDITION_NULL
, NULL
, false, false);
305 assert_se(condition
);
306 assert_se(condition_test(condition
));
307 condition_free(condition
);
309 condition
= condition_new(CONDITION_NULL
, NULL
, false, true);
310 assert_se(condition
);
311 assert_se(!condition_test(condition
));
312 condition_free(condition
);
315 static void test_condition_test_security(void) {
316 Condition
*condition
;
318 condition
= condition_new(CONDITION_SECURITY
, "garbage oifdsjfoidsjoj", false, false);
319 assert_se(condition
);
320 assert_se(!condition_test(condition
));
321 condition_free(condition
);
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
);
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
);
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
);
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
);
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
);
349 static void test_condition_test_virtualization(void) {
350 Condition
*condition
;
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
);
359 condition_free(condition
);
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
);
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
);
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
);
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
);
401 condition_free(condition
);
405 static void test_condition_test_user(void) {
406 Condition
*condition
;
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
);
416 condition_free(condition
);
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
);
424 condition_free(condition
);
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
);
433 condition_free(condition
);
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
);
442 condition_free(condition
);
445 username
= getusername_malloc();
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
);
452 condition_free(condition
);
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
);
461 condition_free(condition
);
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()))
471 condition_free(condition
);
474 static void test_condition_test_group(void) {
475 Condition
*condition
;
478 gid_t
*gids
, max_gid
;
479 int ngroups_max
, ngroups
, r
, i
;
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
);
487 condition_free(condition
);
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
);
496 condition_free(condition
);
499 ngroups_max
= sysconf(_SC_NGROUPS_MAX
);
500 assert(ngroups_max
> 0);
502 gids
= alloca(sizeof(gid_t
) * ngroups_max
);
504 ngroups
= getgroups(ngroups_max
, gids
);
505 assert(ngroups
>= 0);
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
);
515 condition_free(condition
);
517 max_gid
= gids
[i
] > max_gid
? gids
[i
] : max_gid
;
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
);
526 condition_free(condition
);
528 max_gid
= gids
[i
] > max_gid
? gids
[i
] : max_gid
;
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
);
537 condition_free(condition
);
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
);
546 condition_free(condition
);
549 int main(int argc
, char *argv
[]) {
550 log_set_max_level(LOG_DEBUG
);
551 log_parse_environment();
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();