]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/bus-proxyd/bus-policy.c
treewide: auto-convert the simple cases to log_*_errno()
[thirdparty/systemd.git] / src / bus-proxyd / bus-policy.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "xml.h"
23 #include "fileio.h"
24 #include "strv.h"
25 #include "conf-files.h"
26 #include "bus-internal.h"
27 #include "bus-message.h"
28 #include "bus-policy.h"
29
30 static void policy_item_free(PolicyItem *i) {
31 assert(i);
32
33 free(i->interface);
34 free(i->member);
35 free(i->error);
36 free(i->name);
37 free(i->path);
38 free(i);
39 }
40
41 DEFINE_TRIVIAL_CLEANUP_FUNC(PolicyItem*, policy_item_free);
42
43 static void item_append(PolicyItem *i, PolicyItem **list) {
44
45 PolicyItem *tail;
46
47 LIST_FIND_TAIL(items, *list, tail);
48 LIST_INSERT_AFTER(items, *list, tail, i);
49 }
50
51 static int file_load(Policy *p, const char *path) {
52
53 _cleanup_free_ char *c = NULL, *policy_user = NULL, *policy_group = NULL;
54 _cleanup_(policy_item_freep) PolicyItem *i = NULL;
55 void *xml_state = NULL;
56 unsigned n_other = 0;
57 const char *q;
58 int r;
59
60 enum {
61 STATE_OUTSIDE,
62 STATE_BUSCONFIG,
63 STATE_POLICY,
64 STATE_POLICY_CONTEXT,
65 STATE_POLICY_USER,
66 STATE_POLICY_GROUP,
67 STATE_POLICY_OTHER_ATTRIBUTE,
68 STATE_ALLOW_DENY,
69 STATE_ALLOW_DENY_INTERFACE,
70 STATE_ALLOW_DENY_MEMBER,
71 STATE_ALLOW_DENY_ERROR,
72 STATE_ALLOW_DENY_PATH,
73 STATE_ALLOW_DENY_MESSAGE_TYPE,
74 STATE_ALLOW_DENY_NAME,
75 STATE_ALLOW_DENY_OTHER_ATTRIBUTE,
76 STATE_OTHER,
77 } state = STATE_OUTSIDE;
78
79 enum {
80 POLICY_CATEGORY_NONE,
81 POLICY_CATEGORY_DEFAULT,
82 POLICY_CATEGORY_MANDATORY,
83 POLICY_CATEGORY_USER,
84 POLICY_CATEGORY_GROUP
85 } policy_category = POLICY_CATEGORY_NONE;
86
87 unsigned line = 0;
88
89 assert(p);
90
91 r = read_full_file(path, &c, NULL);
92 if (r < 0) {
93 if (r == -ENOENT)
94 return 0;
95 if (r == -EISDIR)
96 return r;
97
98 log_error_errno(-r, "Failed to load %s: %m", path);
99 return r;
100 }
101
102 q = c;
103 for (;;) {
104 _cleanup_free_ char *name = NULL;
105 int t;
106
107 t = xml_tokenize(&q, &name, &xml_state, &line);
108 if (t < 0) {
109 log_error_errno(-t, "XML parse failure in %s: %m", path);
110 return t;
111 }
112
113 switch (state) {
114
115 case STATE_OUTSIDE:
116
117 if (t == XML_TAG_OPEN) {
118 if (streq(name, "busconfig"))
119 state = STATE_BUSCONFIG;
120 else {
121 log_error("Unexpected tag %s at %s:%u.", name, path, line);
122 return -EINVAL;
123 }
124
125 } else if (t == XML_END)
126 return 0;
127 else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
128 log_error("Unexpected token (1) at %s:%u.", path, line);
129 return -EINVAL;
130 }
131
132 break;
133
134 case STATE_BUSCONFIG:
135
136 if (t == XML_TAG_OPEN) {
137 if (streq(name, "policy")) {
138 state = STATE_POLICY;
139 policy_category = POLICY_CATEGORY_NONE;
140 free(policy_user);
141 free(policy_group);
142 policy_user = policy_group = NULL;
143 } else {
144 state = STATE_OTHER;
145 n_other = 0;
146 }
147 } else if (t == XML_TAG_CLOSE_EMPTY ||
148 (t == XML_TAG_CLOSE && streq(name, "busconfig")))
149 state = STATE_OUTSIDE;
150 else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
151 log_error("Unexpected token (2) at %s:%u.", path, line);
152 return -EINVAL;
153 }
154
155 break;
156
157 case STATE_POLICY:
158
159 if (t == XML_ATTRIBUTE_NAME) {
160 if (streq(name, "context"))
161 state = STATE_POLICY_CONTEXT;
162 else if (streq(name, "user"))
163 state = STATE_POLICY_USER;
164 else if (streq(name, "group"))
165 state = STATE_POLICY_GROUP;
166 else {
167 if (streq(name, "at_console"))
168 log_debug("Attribute %s of <policy> tag unsupported at %s:%u, ignoring.", name, path, line);
169 else
170 log_warning("Attribute %s of <policy> tag unknown at %s:%u, ignoring.", name, path, line);
171 state = STATE_POLICY_OTHER_ATTRIBUTE;
172 }
173 } else if (t == XML_TAG_CLOSE_EMPTY ||
174 (t == XML_TAG_CLOSE && streq(name, "policy")))
175 state = STATE_BUSCONFIG;
176 else if (t == XML_TAG_OPEN) {
177 PolicyItemType it;
178
179 if (streq(name, "allow"))
180 it = POLICY_ITEM_ALLOW;
181 else if (streq(name, "deny"))
182 it = POLICY_ITEM_DENY;
183 else {
184 log_warning("Unknown tag %s in <policy> %s:%u.", name, path, line);
185 return -EINVAL;
186 }
187
188 assert(!i);
189 i = new0(PolicyItem, 1);
190 if (!i)
191 return log_oom();
192
193 i->type = it;
194 state = STATE_ALLOW_DENY;
195
196 } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
197 log_error("Unexpected token (3) at %s:%u.", path, line);
198 return -EINVAL;
199 }
200
201 break;
202
203 case STATE_POLICY_CONTEXT:
204
205 if (t == XML_ATTRIBUTE_VALUE) {
206 if (streq(name, "default")) {
207 policy_category = POLICY_CATEGORY_DEFAULT;
208 state = STATE_POLICY;
209 } else if (streq(name, "mandatory")) {
210 policy_category = POLICY_CATEGORY_MANDATORY;
211 state = STATE_POLICY;
212 } else {
213 log_error("context= parameter %s unknown for <policy> at %s:%u.", name, path, line);
214 return -EINVAL;
215 }
216 } else {
217 log_error("Unexpected token (4) at %s:%u.", path, line);
218 return -EINVAL;
219 }
220
221 break;
222
223 case STATE_POLICY_USER:
224
225 if (t == XML_ATTRIBUTE_VALUE) {
226 free(policy_user);
227 policy_user = name;
228 name = NULL;
229 policy_category = POLICY_CATEGORY_USER;
230 state = STATE_POLICY;
231 } else {
232 log_error("Unexpected token (5) in %s:%u.", path, line);
233 return -EINVAL;
234 }
235
236 break;
237
238 case STATE_POLICY_GROUP:
239
240 if (t == XML_ATTRIBUTE_VALUE) {
241 free(policy_group);
242 policy_group = name;
243 name = NULL;
244 policy_category = POLICY_CATEGORY_GROUP;
245 state = STATE_POLICY;
246 } else {
247 log_error("Unexpected token (6) at %s:%u.", path, line);
248 return -EINVAL;
249 }
250
251 break;
252
253 case STATE_POLICY_OTHER_ATTRIBUTE:
254
255 if (t == XML_ATTRIBUTE_VALUE)
256 state = STATE_POLICY;
257 else {
258 log_error("Unexpected token (7) in %s:%u.", path, line);
259 return -EINVAL;
260 }
261
262 break;
263
264 case STATE_ALLOW_DENY:
265
266 assert(i);
267
268 if (t == XML_ATTRIBUTE_NAME) {
269 PolicyItemClass ic;
270
271 if (startswith(name, "send_"))
272 ic = POLICY_ITEM_SEND;
273 else if (startswith(name, "receive_"))
274 ic = POLICY_ITEM_RECV;
275 else if (streq(name, "own"))
276 ic = POLICY_ITEM_OWN;
277 else if (streq(name, "own_prefix"))
278 ic = POLICY_ITEM_OWN_PREFIX;
279 else if (streq(name, "user"))
280 ic = POLICY_ITEM_USER;
281 else if (streq(name, "group"))
282 ic = POLICY_ITEM_GROUP;
283 else if (streq(name, "eavesdrop")) {
284 log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name, path, line);
285 i->class = POLICY_ITEM_IGNORE;
286 state = STATE_ALLOW_DENY_OTHER_ATTRIBUTE;
287 break;
288 } else {
289 log_error("Unknown attribute %s= at %s:%u, ignoring.", name, path, line);
290 state = STATE_ALLOW_DENY_OTHER_ATTRIBUTE;
291 break;
292 }
293
294 if (i->class != _POLICY_ITEM_CLASS_UNSET && ic != i->class) {
295 log_error("send_ and receive_ fields mixed on same tag at %s:%u.", path, line);
296 return -EINVAL;
297 }
298
299 i->class = ic;
300
301 if (ic == POLICY_ITEM_SEND || ic == POLICY_ITEM_RECV) {
302 const char *u;
303
304 u = strchr(name, '_');
305 assert(u);
306
307 u++;
308
309 if (streq(u, "interface"))
310 state = STATE_ALLOW_DENY_INTERFACE;
311 else if (streq(u, "member"))
312 state = STATE_ALLOW_DENY_MEMBER;
313 else if (streq(u, "error"))
314 state = STATE_ALLOW_DENY_ERROR;
315 else if (streq(u, "path"))
316 state = STATE_ALLOW_DENY_PATH;
317 else if (streq(u, "type"))
318 state = STATE_ALLOW_DENY_MESSAGE_TYPE;
319 else if ((streq(u, "destination") && ic == POLICY_ITEM_SEND) ||
320 (streq(u, "sender") && ic == POLICY_ITEM_RECV))
321 state = STATE_ALLOW_DENY_NAME;
322 else {
323 if (streq(u, "requested_reply"))
324 log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name, path, line);
325 else
326 log_error("Unknown attribute %s= at %s:%u, ignoring.", name, path, line);
327 state = STATE_ALLOW_DENY_OTHER_ATTRIBUTE;
328 break;
329 }
330 } else
331 state = STATE_ALLOW_DENY_NAME;
332
333 } else if (t == XML_TAG_CLOSE_EMPTY ||
334 (t == XML_TAG_CLOSE && streq(name, i->type == POLICY_ITEM_ALLOW ? "allow" : "deny"))) {
335
336 if (i->class == _POLICY_ITEM_CLASS_UNSET) {
337 log_error("Policy not set at %s:%u.", path, line);
338 return -EINVAL;
339 }
340
341 if (policy_category == POLICY_CATEGORY_DEFAULT)
342 item_append(i, &p->default_items);
343 else if (policy_category == POLICY_CATEGORY_MANDATORY)
344 item_append(i, &p->mandatory_items);
345 else if (policy_category == POLICY_CATEGORY_USER) {
346 const char *u = policy_user;
347
348 assert_cc(sizeof(uid_t) == sizeof(uint32_t));
349
350 r = hashmap_ensure_allocated(&p->user_items, NULL);
351 if (r < 0)
352 return log_oom();
353
354 if (!u) {
355 log_error("User policy without name");
356 return -EINVAL;
357 }
358
359 r = get_user_creds(&u, &i->uid, NULL, NULL, NULL);
360 if (r < 0) {
361 log_error_errno(-r, "Failed to resolve user %s, ignoring policy: %m", u);
362 free(i);
363 } else {
364 PolicyItem *first;
365
366 first = hashmap_get(p->user_items, UINT32_TO_PTR(i->uid));
367 item_append(i, &first);
368 i->uid_valid = true;
369
370 r = hashmap_replace(p->user_items, UINT32_TO_PTR(i->uid), first);
371 if (r < 0) {
372 LIST_REMOVE(items, first, i);
373 return log_oom();
374 }
375 }
376
377 } else if (policy_category == POLICY_CATEGORY_GROUP) {
378 const char *g = policy_group;
379
380 assert_cc(sizeof(gid_t) == sizeof(uint32_t));
381
382 r = hashmap_ensure_allocated(&p->group_items, NULL);
383 if (r < 0)
384 return log_oom();
385
386 if (!g) {
387 log_error("Group policy without name");
388 return -EINVAL;
389 }
390
391 r = get_group_creds(&g, &i->gid);
392 if (r < 0) {
393 log_error_errno(-r, "Failed to resolve group %s, ignoring policy: %m", g);
394 free(i);
395 } else {
396 PolicyItem *first;
397
398 first = hashmap_get(p->group_items, UINT32_TO_PTR(i->gid));
399 item_append(i, &first);
400 i->gid_valid = true;
401
402 r = hashmap_replace(p->group_items, UINT32_TO_PTR(i->gid), first);
403 if (r < 0) {
404 LIST_REMOVE(items, first, i);
405 return log_oom();
406 }
407 }
408 }
409
410 state = STATE_POLICY;
411 i = NULL;
412
413 } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
414 log_error("Unexpected token (8) at %s:%u.", path, line);
415 return -EINVAL;
416 }
417
418 break;
419
420 case STATE_ALLOW_DENY_INTERFACE:
421
422 if (t == XML_ATTRIBUTE_VALUE) {
423 assert(i);
424 if (i->interface) {
425 log_error("Duplicate interface at %s:%u.", path, line);
426 return -EINVAL;
427 }
428
429 i->interface = name;
430 name = NULL;
431 state = STATE_ALLOW_DENY;
432 } else {
433 log_error("Unexpected token (9) at %s:%u.", path, line);
434 return -EINVAL;
435 }
436
437 break;
438
439 case STATE_ALLOW_DENY_MEMBER:
440
441 if (t == XML_ATTRIBUTE_VALUE) {
442 assert(i);
443 if (i->member) {
444 log_error("Duplicate member in %s:%u.", path, line);
445 return -EINVAL;
446 }
447
448 i->member = name;
449 name = NULL;
450 state = STATE_ALLOW_DENY;
451 } else {
452 log_error("Unexpected token (10) in %s:%u.", path, line);
453 return -EINVAL;
454 }
455
456 break;
457
458 case STATE_ALLOW_DENY_ERROR:
459
460 if (t == XML_ATTRIBUTE_VALUE) {
461 assert(i);
462 if (i->error) {
463 log_error("Duplicate error in %s:%u.", path, line);
464 return -EINVAL;
465 }
466
467 i->error = name;
468 name = NULL;
469 state = STATE_ALLOW_DENY;
470 } else {
471 log_error("Unexpected token (11) in %s:%u.", path, line);
472 return -EINVAL;
473 }
474
475 break;
476
477 case STATE_ALLOW_DENY_PATH:
478
479 if (t == XML_ATTRIBUTE_VALUE) {
480 assert(i);
481 if (i->path) {
482 log_error("Duplicate path in %s:%u.", path, line);
483 return -EINVAL;
484 }
485
486 i->path = name;
487 name = NULL;
488 state = STATE_ALLOW_DENY;
489 } else {
490 log_error("Unexpected token (12) in %s:%u.", path, line);
491 return -EINVAL;
492 }
493
494 break;
495
496 case STATE_ALLOW_DENY_MESSAGE_TYPE:
497
498 if (t == XML_ATTRIBUTE_VALUE) {
499 assert(i);
500
501 if (i->message_type != 0) {
502 log_error("Duplicate message type in %s:%u.", path, line);
503 return -EINVAL;
504 }
505
506 r = bus_message_type_from_string(name, &i->message_type);
507 if (r < 0) {
508 log_error("Invalid message type in %s:%u.", path, line);
509 return -EINVAL;
510 }
511
512 state = STATE_ALLOW_DENY;
513 } else {
514 log_error("Unexpected token (13) in %s:%u.", path, line);
515 return -EINVAL;
516 }
517
518 break;
519
520 case STATE_ALLOW_DENY_NAME:
521
522 if (t == XML_ATTRIBUTE_VALUE) {
523 assert(i);
524 if (i->name) {
525 log_error("Duplicate name in %s:%u.", path, line);
526 return -EINVAL;
527 }
528
529 switch (i->class) {
530 case POLICY_ITEM_USER:
531 if (!streq(name, "*")) {
532 const char *u = name;
533
534 r = get_user_creds(&u, &i->uid, NULL, NULL, NULL);
535 if (r < 0)
536 log_error_errno(-r, "Failed to resolve user %s: %m", name);
537 else
538 i->uid_valid = true;
539 }
540 break;
541 case POLICY_ITEM_GROUP:
542 if (!streq(name, "*")) {
543 const char *g = name;
544
545 r = get_group_creds(&g, &i->gid);
546 if (r < 0)
547 log_error_errno(-r, "Failed to resolve group %s: %m", name);
548 else
549 i->gid_valid = true;
550 }
551 break;
552 default:
553 break;
554 }
555
556 i->name = name;
557 name = NULL;
558
559 state = STATE_ALLOW_DENY;
560 } else {
561 log_error("Unexpected token (14) in %s:%u.", path, line);
562 return -EINVAL;
563 }
564
565 break;
566
567 case STATE_ALLOW_DENY_OTHER_ATTRIBUTE:
568
569 if (t == XML_ATTRIBUTE_VALUE)
570 state = STATE_ALLOW_DENY;
571 else {
572 log_error("Unexpected token (15) in %s:%u.", path, line);
573 return -EINVAL;
574 }
575
576 break;
577
578 case STATE_OTHER:
579
580 if (t == XML_TAG_OPEN)
581 n_other++;
582 else if (t == XML_TAG_CLOSE || t == XML_TAG_CLOSE_EMPTY) {
583
584 if (n_other == 0)
585 state = STATE_BUSCONFIG;
586 else
587 n_other--;
588 }
589
590 break;
591 }
592 }
593 }
594
595 enum {
596 DENY,
597 ALLOW,
598 DUNNO,
599 };
600
601 static const char *verdict_to_string(int v) {
602 switch (v) {
603
604 case DENY:
605 return "DENY";
606 case ALLOW:
607 return "ALLOW";
608 case DUNNO:
609 return "DUNNO";
610 }
611
612 return NULL;
613 }
614
615 struct policy_check_filter {
616 PolicyItemClass class;
617 uid_t uid;
618 gid_t gid;
619 int message_type;
620 const char *name;
621 const char *interface;
622 const char *path;
623 const char *member;
624 };
625
626 static int is_permissive(PolicyItem *i) {
627
628 assert(i);
629
630 return (i->type == POLICY_ITEM_ALLOW) ? ALLOW : DENY;
631 }
632
633 static int check_policy_item(PolicyItem *i, const struct policy_check_filter *filter) {
634
635 assert(i);
636 assert(filter);
637
638 switch (i->class) {
639 case POLICY_ITEM_SEND:
640 case POLICY_ITEM_RECV:
641
642 if (i->name && !streq_ptr(i->name, filter->name))
643 break;
644
645 if ((i->message_type != 0) && (i->message_type != filter->message_type))
646 break;
647
648 if (i->path && !streq_ptr(i->path, filter->path))
649 break;
650
651 if (i->member && !streq_ptr(i->member, filter->member))
652 break;
653
654 if (i->interface && !streq_ptr(i->interface, filter->interface))
655 break;
656
657 return is_permissive(i);
658
659 case POLICY_ITEM_OWN:
660 assert(filter->name);
661
662 if (streq(i->name, "*") || streq(i->name, filter->name))
663 return is_permissive(i);
664 break;
665
666 case POLICY_ITEM_OWN_PREFIX:
667 assert(filter->name);
668
669 if (streq(i->name, "*") || service_name_startswith(filter->name, i->name))
670 return is_permissive(i);
671 break;
672
673 case POLICY_ITEM_USER:
674 if (filter->uid != (uid_t) -1)
675 if ((streq_ptr(i->name, "*") || (i->uid_valid && i->uid == filter->uid)))
676 return is_permissive(i);
677 break;
678
679 case POLICY_ITEM_GROUP:
680 if (filter->gid != (gid_t) -1)
681 if ((streq_ptr(i->name, "*") || (i->gid_valid && i->gid == filter->gid)))
682 return is_permissive(i);
683 break;
684
685 case POLICY_ITEM_IGNORE:
686 default:
687 break;
688 }
689
690 return DUNNO;
691 }
692
693 static int check_policy_items(PolicyItem *items, const struct policy_check_filter *filter) {
694
695 PolicyItem *i;
696 int verdict = DUNNO;
697
698 assert(filter);
699
700 /* Check all policies in a set - a broader one might be followed by a more specific one,
701 * and the order of rules in policy definitions matters */
702 LIST_FOREACH(items, i, items) {
703 int v;
704
705 if (i->class != filter->class &&
706 !(i->class == POLICY_ITEM_OWN_PREFIX && filter->class == POLICY_ITEM_OWN))
707 continue;
708
709 v = check_policy_item(i, filter);
710 if (v != DUNNO)
711 verdict = v;
712 }
713
714 return verdict;
715 }
716
717 static int policy_check(Policy *p, const struct policy_check_filter *filter) {
718
719 PolicyItem *items;
720 int verdict, v;
721
722 assert(p);
723 assert(filter);
724
725 assert(IN_SET(filter->class, POLICY_ITEM_SEND, POLICY_ITEM_RECV, POLICY_ITEM_OWN, POLICY_ITEM_USER, POLICY_ITEM_GROUP));
726
727 /*
728 * The policy check is implemented by the following logic:
729 *
730 * 1. Check default items
731 * 2. Check group items
732 * 3. Check user items
733 * 4. Check mandatory items
734 *
735 * Later rules override earlier rules.
736 */
737
738 verdict = check_policy_items(p->default_items, filter);
739
740 if (filter->gid != (gid_t) -1) {
741 items = hashmap_get(p->group_items, UINT32_TO_PTR(filter->gid));
742 if (items) {
743 v = check_policy_items(items, filter);
744 if (v != DUNNO)
745 verdict = v;
746 }
747 }
748
749 if (filter->uid != (uid_t) -1) {
750 items = hashmap_get(p->user_items, UINT32_TO_PTR(filter->uid));
751 if (items) {
752 v = check_policy_items(items, filter);
753 if (v != DUNNO)
754 verdict = v;
755 }
756 }
757
758 v = check_policy_items(p->mandatory_items, filter);
759 if (v != DUNNO)
760 verdict = v;
761
762 return verdict;
763 }
764
765 bool policy_check_own(Policy *p, uid_t uid, gid_t gid, const char *name) {
766
767 struct policy_check_filter filter = {
768 .class = POLICY_ITEM_OWN,
769 .uid = uid,
770 .gid = gid,
771 .name = name,
772 };
773
774 int verdict;
775
776 assert(p);
777 assert(name);
778
779 verdict = policy_check(p, &filter);
780
781 log_full(LOG_AUTH | (verdict != ALLOW ? LOG_WARNING : LOG_DEBUG),
782 "Ownership permission check for uid=" UID_FMT " gid=" GID_FMT" name=%s: %s",
783 uid, gid, strna(name), strna(verdict_to_string(verdict)));
784
785 return verdict == ALLOW;
786 }
787
788 bool policy_check_hello(Policy *p, uid_t uid, gid_t gid) {
789
790 struct policy_check_filter filter = {
791 .uid = uid,
792 .gid = gid,
793 };
794 int verdict;
795
796 assert(p);
797
798 filter.class = POLICY_ITEM_USER;
799 verdict = policy_check(p, &filter);
800
801 if (verdict != DENY) {
802 int v;
803
804 filter.class = POLICY_ITEM_GROUP;
805 v = policy_check(p, &filter);
806 if (v != DUNNO)
807 verdict = v;
808 }
809
810 log_full(LOG_AUTH | (verdict != ALLOW ? LOG_WARNING : LOG_DEBUG),
811 "Hello permission check for uid=" UID_FMT " gid=" GID_FMT": %s",
812 uid, gid, strna(verdict_to_string(verdict)));
813
814 return verdict == ALLOW;
815 }
816
817 bool policy_check_recv(Policy *p,
818 uid_t uid,
819 gid_t gid,
820 int message_type,
821 const char *name,
822 const char *path,
823 const char *interface,
824 const char *member) {
825
826 struct policy_check_filter filter = {
827 .class = POLICY_ITEM_RECV,
828 .uid = uid,
829 .gid = gid,
830 .message_type = message_type,
831 .name = name,
832 .interface = interface,
833 .path = path,
834 .member = member,
835 };
836
837 int verdict;
838
839 assert(p);
840
841 verdict = policy_check(p, &filter);
842
843 log_full(LOG_AUTH | (verdict != ALLOW ? LOG_WARNING : LOG_DEBUG),
844 "Recieve permission check for uid=" UID_FMT " gid=" GID_FMT" message=%s name=%s interface=%s path=%s member=%s: %s",
845 uid, gid, bus_message_type_to_string(message_type), strna(name), strna(path), strna(interface), strna(member), strna(verdict_to_string(verdict)));
846
847 return verdict == ALLOW;
848 }
849
850 bool policy_check_send(Policy *p,
851 uid_t uid,
852 gid_t gid,
853 int message_type,
854 const char *name,
855 const char *path,
856 const char *interface,
857 const char *member) {
858
859 struct policy_check_filter filter = {
860 .class = POLICY_ITEM_SEND,
861 .uid = uid,
862 .gid = gid,
863 .message_type = message_type,
864 .name = name,
865 .interface = interface,
866 .path = path,
867 .member = member,
868 };
869
870 int verdict;
871
872 assert(p);
873
874 verdict = policy_check(p, &filter);
875
876 log_full(LOG_AUTH | (verdict != ALLOW ? LOG_WARNING : LOG_DEBUG),
877 "Send permission check for uid=" UID_FMT " gid=" GID_FMT" message=%s name=%s interface=%s path=%s member=%s: %s",
878 uid, gid, bus_message_type_to_string(message_type), strna(name), strna(path), strna(interface), strna(member), strna(verdict_to_string(verdict)));
879
880 return verdict == ALLOW;
881 }
882
883 int policy_load(Policy *p, char **files) {
884 char **i;
885 int r;
886
887 assert(p);
888
889 STRV_FOREACH(i, files) {
890
891 r = file_load(p, *i);
892 if (r == -EISDIR) {
893 _cleanup_strv_free_ char **l = NULL;
894 char **j;
895
896 r = conf_files_list(&l, ".conf", NULL, *i, NULL);
897 if (r < 0) {
898 log_error_errno(-r, "Failed to get configuration file list: %m");
899 return r;
900 }
901
902 STRV_FOREACH(j, l)
903 file_load(p, *j);
904 }
905
906 /* We ignore all errors but EISDIR, and just proceed. */
907 }
908
909 return 0;
910 }
911
912 void policy_free(Policy *p) {
913 PolicyItem *i, *first;
914
915 if (!p)
916 return;
917
918 while ((i = p->default_items)) {
919 LIST_REMOVE(items, p->default_items, i);
920 policy_item_free(i);
921 }
922
923 while ((i = p->mandatory_items)) {
924 LIST_REMOVE(items, p->mandatory_items, i);
925 policy_item_free(i);
926 }
927
928 while ((first = hashmap_steal_first(p->user_items))) {
929
930 while ((i = first)) {
931 LIST_REMOVE(items, first, i);
932 policy_item_free(i);
933 }
934 }
935
936 while ((first = hashmap_steal_first(p->group_items))) {
937
938 while ((i = first)) {
939 LIST_REMOVE(items, first, i);
940 policy_item_free(i);
941 }
942 }
943
944 hashmap_free(p->user_items);
945 hashmap_free(p->group_items);
946
947 p->user_items = p->group_items = NULL;
948 }
949
950 static void dump_items(PolicyItem *items, const char *prefix) {
951
952 PolicyItem *i;
953
954 if (!items)
955 return;
956
957 if (!prefix)
958 prefix = "";
959
960 LIST_FOREACH(items, i, items) {
961
962 printf("%sType: %s\n"
963 "%sClass: %s\n",
964 prefix, policy_item_type_to_string(i->type),
965 prefix, policy_item_class_to_string(i->class));
966
967 if (i->interface)
968 printf("%sInterface: %s\n",
969 prefix, i->interface);
970
971 if (i->member)
972 printf("%sMember: %s\n",
973 prefix, i->member);
974
975 if (i->error)
976 printf("%sError: %s\n",
977 prefix, i->error);
978
979 if (i->path)
980 printf("%sPath: %s\n",
981 prefix, i->path);
982
983 if (i->name)
984 printf("%sName: %s\n",
985 prefix, i->name);
986
987 if (i->message_type != 0)
988 printf("%sMessage Type: %s\n",
989 prefix, bus_message_type_to_string(i->message_type));
990
991 if (i->uid_valid) {
992 _cleanup_free_ char *user;
993
994 user = uid_to_name(i->uid);
995
996 printf("%sUser: %s (%d)\n",
997 prefix, strna(user), i->uid);
998 }
999
1000 if (i->gid_valid) {
1001 _cleanup_free_ char *group;
1002
1003 group = gid_to_name(i->gid);
1004
1005 printf("%sGroup: %s (%d)\n",
1006 prefix, strna(group), i->gid);
1007 }
1008 printf("%s-\n", prefix);
1009 }
1010 }
1011
1012 static void dump_hashmap_items(Hashmap *h) {
1013 PolicyItem *i;
1014 Iterator j;
1015 void *k;
1016
1017 HASHMAP_FOREACH_KEY(i, k, h, j) {
1018 printf("\t%s Item for %u:\n", draw_special_char(DRAW_ARROW), PTR_TO_UINT(k));
1019 dump_items(i, "\t\t");
1020 }
1021 }
1022
1023 void policy_dump(Policy *p) {
1024
1025 printf("%s Default Items:\n", draw_special_char(DRAW_ARROW));
1026 dump_items(p->default_items, "\t");
1027
1028 printf("%s Group Items:\n", draw_special_char(DRAW_ARROW));
1029 dump_hashmap_items(p->group_items);
1030
1031 printf("%s User Items:\n", draw_special_char(DRAW_ARROW));
1032 dump_hashmap_items(p->user_items);
1033
1034 printf("%s Mandatory Items:\n", draw_special_char(DRAW_ARROW));
1035 dump_items(p->mandatory_items, "\t");
1036 }
1037
1038 static const char* const policy_item_type_table[_POLICY_ITEM_TYPE_MAX] = {
1039 [_POLICY_ITEM_TYPE_UNSET] = "unset",
1040 [POLICY_ITEM_ALLOW] = "allow",
1041 [POLICY_ITEM_DENY] = "deny",
1042 };
1043 DEFINE_STRING_TABLE_LOOKUP(policy_item_type, PolicyItemType);
1044
1045 static const char* const policy_item_class_table[_POLICY_ITEM_CLASS_MAX] = {
1046 [_POLICY_ITEM_CLASS_UNSET] = "unset",
1047 [POLICY_ITEM_SEND] = "send",
1048 [POLICY_ITEM_RECV] = "recv",
1049 [POLICY_ITEM_OWN] = "own",
1050 [POLICY_ITEM_OWN_PREFIX] = "own-prefix",
1051 [POLICY_ITEM_USER] = "user",
1052 [POLICY_ITEM_GROUP] = "group",
1053 [POLICY_ITEM_IGNORE] = "ignore",
1054 };
1055 DEFINE_STRING_TABLE_LOOKUP(policy_item_class, PolicyItemClass);