chiark / gitweb /
treewide: no need to negate errno for log_*_errno()
[elogind.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);