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