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