1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
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.
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.
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/>.
24 #include "bus-internal.h"
25 #include "bus-xml-policy.h"
26 #include "conf-files.h"
28 #include "formats-util.h"
30 #include "string-table.h"
31 #include "string-util.h"
33 #include "user-util.h"
36 static void policy_item_free(PolicyItem
*i
) {
47 DEFINE_TRIVIAL_CLEANUP_FUNC(PolicyItem
*, policy_item_free
);
49 static void item_append(PolicyItem
*i
, PolicyItem
**list
) {
53 LIST_FIND_TAIL(items
, *list
, tail
);
54 LIST_INSERT_AFTER(items
, *list
, tail
, i
);
57 static int file_load(Policy
*p
, const char *path
) {
59 _cleanup_free_
char *c
= NULL
, *policy_user
= NULL
, *policy_group
= NULL
;
60 _cleanup_(policy_item_freep
) PolicyItem
*i
= NULL
;
61 void *xml_state
= NULL
;
74 STATE_POLICY_OTHER_ATTRIBUTE
,
76 STATE_ALLOW_DENY_INTERFACE
,
77 STATE_ALLOW_DENY_MEMBER
,
78 STATE_ALLOW_DENY_ERROR
,
79 STATE_ALLOW_DENY_PATH
,
80 STATE_ALLOW_DENY_MESSAGE_TYPE
,
81 STATE_ALLOW_DENY_NAME
,
82 STATE_ALLOW_DENY_OTHER_ATTRIBUTE
,
84 } state
= STATE_OUTSIDE
;
88 POLICY_CATEGORY_DEFAULT
,
89 POLICY_CATEGORY_MANDATORY
,
90 POLICY_CATEGORY_ON_CONSOLE
,
91 POLICY_CATEGORY_NO_CONSOLE
,
94 } policy_category
= POLICY_CATEGORY_NONE
;
100 r
= read_full_file(path
, &c
, NULL
);
107 return log_error_errno(r
, "Failed to load %s: %m", path
);
112 _cleanup_free_
char *name
= NULL
;
115 t
= xml_tokenize(&q
, &name
, &xml_state
, &line
);
117 return log_error_errno(t
, "XML parse failure in %s: %m", path
);
123 if (t
== XML_TAG_OPEN
) {
124 if (streq(name
, "busconfig"))
125 state
= STATE_BUSCONFIG
;
127 log_error("Unexpected tag %s at %s:%u.", name
, path
, line
);
131 } else if (t
== XML_END
)
133 else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
134 log_error("Unexpected token (1) at %s:%u.", path
, line
);
140 case STATE_BUSCONFIG
:
142 if (t
== XML_TAG_OPEN
) {
143 if (streq(name
, "policy")) {
144 state
= STATE_POLICY
;
145 policy_category
= POLICY_CATEGORY_NONE
;
148 policy_user
= policy_group
= NULL
;
153 } else if (t
== XML_TAG_CLOSE_EMPTY
||
154 (t
== XML_TAG_CLOSE
&& streq(name
, "busconfig")))
155 state
= STATE_OUTSIDE
;
156 else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
157 log_error("Unexpected token (2) at %s:%u.", path
, line
);
165 if (t
== XML_ATTRIBUTE_NAME
) {
166 if (streq(name
, "context"))
167 state
= STATE_POLICY_CONTEXT
;
168 else if (streq(name
, "at_console"))
169 state
= STATE_POLICY_CONSOLE
;
170 else if (streq(name
, "user"))
171 state
= STATE_POLICY_USER
;
172 else if (streq(name
, "group"))
173 state
= STATE_POLICY_GROUP
;
175 log_warning("Attribute %s of <policy> tag unknown at %s:%u, ignoring.", name
, path
, line
);
176 state
= STATE_POLICY_OTHER_ATTRIBUTE
;
178 } else if (t
== XML_TAG_CLOSE_EMPTY
||
179 (t
== XML_TAG_CLOSE
&& streq(name
, "policy")))
180 state
= STATE_BUSCONFIG
;
181 else if (t
== XML_TAG_OPEN
) {
184 if (streq(name
, "allow"))
185 it
= POLICY_ITEM_ALLOW
;
186 else if (streq(name
, "deny"))
187 it
= POLICY_ITEM_DENY
;
189 log_warning("Unknown tag %s in <policy> %s:%u.", name
, path
, line
);
194 i
= new0(PolicyItem
, 1);
199 state
= STATE_ALLOW_DENY
;
201 } else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
202 log_error("Unexpected token (3) at %s:%u.", path
, line
);
208 case STATE_POLICY_CONTEXT
:
210 if (t
== XML_ATTRIBUTE_VALUE
) {
211 if (streq(name
, "default")) {
212 policy_category
= POLICY_CATEGORY_DEFAULT
;
213 state
= STATE_POLICY
;
214 } else if (streq(name
, "mandatory")) {
215 policy_category
= POLICY_CATEGORY_MANDATORY
;
216 state
= STATE_POLICY
;
218 log_error("context= parameter %s unknown for <policy> at %s:%u.", name
, path
, line
);
222 log_error("Unexpected token (4) at %s:%u.", path
, line
);
228 case STATE_POLICY_CONSOLE
:
230 if (t
== XML_ATTRIBUTE_VALUE
) {
231 if (streq(name
, "true")) {
232 policy_category
= POLICY_CATEGORY_ON_CONSOLE
;
233 state
= STATE_POLICY
;
234 } else if (streq(name
, "false")) {
235 policy_category
= POLICY_CATEGORY_NO_CONSOLE
;
236 state
= STATE_POLICY
;
238 log_error("at_console= parameter %s unknown for <policy> at %s:%u.", name
, path
, line
);
242 log_error("Unexpected token (4.1) at %s:%u.", path
, line
);
248 case STATE_POLICY_USER
:
250 if (t
== XML_ATTRIBUTE_VALUE
) {
254 policy_category
= POLICY_CATEGORY_USER
;
255 state
= STATE_POLICY
;
257 log_error("Unexpected token (5) in %s:%u.", path
, line
);
263 case STATE_POLICY_GROUP
:
265 if (t
== XML_ATTRIBUTE_VALUE
) {
269 policy_category
= POLICY_CATEGORY_GROUP
;
270 state
= STATE_POLICY
;
272 log_error("Unexpected token (6) at %s:%u.", path
, line
);
278 case STATE_POLICY_OTHER_ATTRIBUTE
:
280 if (t
== XML_ATTRIBUTE_VALUE
)
281 state
= STATE_POLICY
;
283 log_error("Unexpected token (7) in %s:%u.", path
, line
);
289 case STATE_ALLOW_DENY
:
293 if (t
== XML_ATTRIBUTE_NAME
) {
296 if (startswith(name
, "send_"))
297 ic
= POLICY_ITEM_SEND
;
298 else if (startswith(name
, "receive_"))
299 ic
= POLICY_ITEM_RECV
;
300 else if (streq(name
, "own"))
301 ic
= POLICY_ITEM_OWN
;
302 else if (streq(name
, "own_prefix"))
303 ic
= POLICY_ITEM_OWN_PREFIX
;
304 else if (streq(name
, "user"))
305 ic
= POLICY_ITEM_USER
;
306 else if (streq(name
, "group"))
307 ic
= POLICY_ITEM_GROUP
;
308 else if (STR_IN_SET(name
, "eavesdrop", "log")) {
309 log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name
, path
, line
);
310 state
= STATE_ALLOW_DENY_OTHER_ATTRIBUTE
;
313 log_error("Unknown attribute %s= at %s:%u, ignoring.", name
, path
, line
);
314 state
= STATE_ALLOW_DENY_OTHER_ATTRIBUTE
;
318 if (i
->class != _POLICY_ITEM_CLASS_UNSET
&& ic
!= i
->class) {
319 log_error("send_, receive_/eavesdrop fields mixed on same tag at %s:%u.", path
, line
);
325 if (ic
== POLICY_ITEM_SEND
|| ic
== POLICY_ITEM_RECV
) {
328 u
= strchr(name
, '_');
333 if (streq(u
, "interface"))
334 state
= STATE_ALLOW_DENY_INTERFACE
;
335 else if (streq(u
, "member"))
336 state
= STATE_ALLOW_DENY_MEMBER
;
337 else if (streq(u
, "error"))
338 state
= STATE_ALLOW_DENY_ERROR
;
339 else if (streq(u
, "path"))
340 state
= STATE_ALLOW_DENY_PATH
;
341 else if (streq(u
, "type"))
342 state
= STATE_ALLOW_DENY_MESSAGE_TYPE
;
343 else if ((streq(u
, "destination") && ic
== POLICY_ITEM_SEND
) ||
344 (streq(u
, "sender") && ic
== POLICY_ITEM_RECV
))
345 state
= STATE_ALLOW_DENY_NAME
;
347 if (streq(u
, "requested_reply"))
348 log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name
, path
, line
);
350 log_error("Unknown attribute %s= at %s:%u, ignoring.", name
, path
, line
);
351 state
= STATE_ALLOW_DENY_OTHER_ATTRIBUTE
;
355 state
= STATE_ALLOW_DENY_NAME
;
357 } else if (t
== XML_TAG_CLOSE_EMPTY
||
358 (t
== XML_TAG_CLOSE
&& streq(name
, i
->type
== POLICY_ITEM_ALLOW
? "allow" : "deny"))) {
360 /* If the tag is fully empty so far, we consider it a recv */
361 if (i
->class == _POLICY_ITEM_CLASS_UNSET
)
362 i
->class = POLICY_ITEM_RECV
;
364 if (policy_category
== POLICY_CATEGORY_DEFAULT
)
365 item_append(i
, &p
->default_items
);
366 else if (policy_category
== POLICY_CATEGORY_MANDATORY
)
367 item_append(i
, &p
->mandatory_items
);
368 else if (policy_category
== POLICY_CATEGORY_ON_CONSOLE
)
369 item_append(i
, &p
->on_console_items
);
370 else if (policy_category
== POLICY_CATEGORY_NO_CONSOLE
)
371 item_append(i
, &p
->no_console_items
);
372 else if (policy_category
== POLICY_CATEGORY_USER
) {
373 const char *u
= policy_user
;
375 assert_cc(sizeof(uid_t
) == sizeof(uint32_t));
377 r
= hashmap_ensure_allocated(&p
->user_items
, NULL
);
382 log_error("User policy without name");
386 r
= get_user_creds(&u
, &i
->uid
, NULL
, NULL
, NULL
);
388 log_error_errno(r
, "Failed to resolve user %s, ignoring policy: %m", u
);
393 first
= hashmap_get(p
->user_items
, UINT32_TO_PTR(i
->uid
));
394 item_append(i
, &first
);
397 r
= hashmap_replace(p
->user_items
, UINT32_TO_PTR(i
->uid
), first
);
399 LIST_REMOVE(items
, first
, i
);
404 } else if (policy_category
== POLICY_CATEGORY_GROUP
) {
405 const char *g
= policy_group
;
407 assert_cc(sizeof(gid_t
) == sizeof(uint32_t));
409 r
= hashmap_ensure_allocated(&p
->group_items
, NULL
);
414 log_error("Group policy without name");
418 r
= get_group_creds(&g
, &i
->gid
);
420 log_error_errno(r
, "Failed to resolve group %s, ignoring policy: %m", g
);
425 first
= hashmap_get(p
->group_items
, UINT32_TO_PTR(i
->gid
));
426 item_append(i
, &first
);
429 r
= hashmap_replace(p
->group_items
, UINT32_TO_PTR(i
->gid
), first
);
431 LIST_REMOVE(items
, first
, i
);
437 state
= STATE_POLICY
;
440 } else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
441 log_error("Unexpected token (8) at %s:%u.", path
, line
);
447 case STATE_ALLOW_DENY_INTERFACE
:
449 if (t
== XML_ATTRIBUTE_VALUE
) {
452 log_error("Duplicate interface at %s:%u.", path
, line
);
456 if (!streq(name
, "*")) {
460 state
= STATE_ALLOW_DENY
;
462 log_error("Unexpected token (9) at %s:%u.", path
, line
);
468 case STATE_ALLOW_DENY_MEMBER
:
470 if (t
== XML_ATTRIBUTE_VALUE
) {
473 log_error("Duplicate member in %s:%u.", path
, line
);
477 if (!streq(name
, "*")) {
481 state
= STATE_ALLOW_DENY
;
483 log_error("Unexpected token (10) in %s:%u.", path
, line
);
489 case STATE_ALLOW_DENY_ERROR
:
491 if (t
== XML_ATTRIBUTE_VALUE
) {
494 log_error("Duplicate error in %s:%u.", path
, line
);
498 if (!streq(name
, "*")) {
502 state
= STATE_ALLOW_DENY
;
504 log_error("Unexpected token (11) in %s:%u.", path
, line
);
510 case STATE_ALLOW_DENY_PATH
:
512 if (t
== XML_ATTRIBUTE_VALUE
) {
515 log_error("Duplicate path in %s:%u.", path
, line
);
519 if (!streq(name
, "*")) {
523 state
= STATE_ALLOW_DENY
;
525 log_error("Unexpected token (12) in %s:%u.", path
, line
);
531 case STATE_ALLOW_DENY_MESSAGE_TYPE
:
533 if (t
== XML_ATTRIBUTE_VALUE
) {
536 if (i
->message_type
!= 0) {
537 log_error("Duplicate message type in %s:%u.", path
, line
);
541 if (!streq(name
, "*")) {
542 r
= bus_message_type_from_string(name
, &i
->message_type
);
544 log_error("Invalid message type in %s:%u.", path
, line
);
549 state
= STATE_ALLOW_DENY
;
551 log_error("Unexpected token (13) in %s:%u.", path
, line
);
557 case STATE_ALLOW_DENY_NAME
:
559 if (t
== XML_ATTRIBUTE_VALUE
) {
562 log_error("Duplicate name in %s:%u.", path
, line
);
567 case POLICY_ITEM_USER
:
568 if (!streq(name
, "*")) {
569 const char *u
= name
;
571 r
= get_user_creds(&u
, &i
->uid
, NULL
, NULL
, NULL
);
573 log_error_errno(r
, "Failed to resolve user %s: %m", name
);
578 case POLICY_ITEM_GROUP
:
579 if (!streq(name
, "*")) {
580 const char *g
= name
;
582 r
= get_group_creds(&g
, &i
->gid
);
584 log_error_errno(r
, "Failed to resolve group %s: %m", name
);
590 case POLICY_ITEM_SEND
:
591 case POLICY_ITEM_RECV
:
593 if (streq(name
, "*"))
605 state
= STATE_ALLOW_DENY
;
607 log_error("Unexpected token (14) in %s:%u.", path
, line
);
613 case STATE_ALLOW_DENY_OTHER_ATTRIBUTE
:
615 if (t
== XML_ATTRIBUTE_VALUE
)
616 state
= STATE_ALLOW_DENY
;
618 log_error("Unexpected token (15) in %s:%u.", path
, line
);
626 if (t
== XML_TAG_OPEN
)
628 else if (t
== XML_TAG_CLOSE
|| t
== XML_TAG_CLOSE_EMPTY
) {
631 state
= STATE_BUSCONFIG
;
647 static const char *verdict_to_string(int v
) {
661 struct policy_check_filter
{
662 PolicyItemClass
class;
667 const char *interface
;
672 static int is_permissive(PolicyItem
*i
) {
676 return (i
->type
== POLICY_ITEM_ALLOW
) ? ALLOW
: DENY
;
679 static int check_policy_item(PolicyItem
*i
, const struct policy_check_filter
*filter
) {
685 case POLICY_ITEM_SEND
:
686 case POLICY_ITEM_RECV
:
688 if (i
->name
&& !streq_ptr(i
->name
, filter
->name
))
691 if ((i
->message_type
!= 0) && (i
->message_type
!= filter
->message_type
))
694 if (i
->path
&& !streq_ptr(i
->path
, filter
->path
))
697 if (i
->member
&& !streq_ptr(i
->member
, filter
->member
))
700 if (i
->interface
&& !streq_ptr(i
->interface
, filter
->interface
))
703 return is_permissive(i
);
705 case POLICY_ITEM_OWN
:
706 assert(filter
->name
);
708 if (streq(i
->name
, "*") || streq(i
->name
, filter
->name
))
709 return is_permissive(i
);
712 case POLICY_ITEM_OWN_PREFIX
:
713 assert(filter
->name
);
715 if (streq(i
->name
, "*") || service_name_startswith(filter
->name
, i
->name
))
716 return is_permissive(i
);
719 case POLICY_ITEM_USER
:
720 if (filter
->uid
!= UID_INVALID
)
721 if ((streq_ptr(i
->name
, "*") || (i
->uid_valid
&& i
->uid
== filter
->uid
)))
722 return is_permissive(i
);
725 case POLICY_ITEM_GROUP
:
726 if (filter
->gid
!= GID_INVALID
)
727 if ((streq_ptr(i
->name
, "*") || (i
->gid_valid
&& i
->gid
== filter
->gid
)))
728 return is_permissive(i
);
731 case POLICY_ITEM_IGNORE
:
739 static int check_policy_items(PolicyItem
*items
, const struct policy_check_filter
*filter
) {
746 /* Check all policies in a set - a broader one might be followed by a more specific one,
747 * and the order of rules in policy definitions matters */
748 LIST_FOREACH(items
, i
, items
) {
751 if (i
->class != filter
->class &&
752 !(i
->class == POLICY_ITEM_OWN_PREFIX
&& filter
->class == POLICY_ITEM_OWN
))
755 v
= check_policy_item(i
, filter
);
763 static int policy_check(Policy
*p
, const struct policy_check_filter
*filter
) {
771 assert(IN_SET(filter
->class, POLICY_ITEM_SEND
, POLICY_ITEM_RECV
, POLICY_ITEM_OWN
, POLICY_ITEM_USER
, POLICY_ITEM_GROUP
));
774 * The policy check is implemented by the following logic:
776 * 1. Check default items
777 * 2. Check group items
778 * 3. Check user items
779 * 4. Check on/no_console items
780 * 5. Check mandatory items
782 * Later rules override earlier rules.
785 verdict
= check_policy_items(p
->default_items
, filter
);
787 if (filter
->gid
!= GID_INVALID
) {
788 items
= hashmap_get(p
->group_items
, UINT32_TO_PTR(filter
->gid
));
790 v
= check_policy_items(items
, filter
);
796 if (filter
->uid
!= UID_INVALID
) {
797 items
= hashmap_get(p
->user_items
, UINT32_TO_PTR(filter
->uid
));
799 v
= check_policy_items(items
, filter
);
805 if (filter
->uid
!= UID_INVALID
&& sd_uid_get_seats(filter
->uid
, -1, NULL
) > 0)
806 v
= check_policy_items(p
->on_console_items
, filter
);
808 v
= check_policy_items(p
->no_console_items
, filter
);
812 v
= check_policy_items(p
->mandatory_items
, filter
);
819 bool policy_check_own(Policy
*p
, uid_t uid
, gid_t gid
, const char *name
) {
821 struct policy_check_filter filter
= {
822 .class = POLICY_ITEM_OWN
,
833 verdict
= policy_check(p
, &filter
);
835 log_full(LOG_AUTH
| (verdict
!= ALLOW
? LOG_WARNING
: LOG_DEBUG
),
836 "Ownership permission check for uid=" UID_FMT
" gid=" GID_FMT
" name=%s: %s",
837 uid
, gid
, strna(name
), strna(verdict_to_string(verdict
)));
839 return verdict
== ALLOW
;
842 bool policy_check_hello(Policy
*p
, uid_t uid
, gid_t gid
) {
844 struct policy_check_filter filter
= {
852 filter
.class = POLICY_ITEM_USER
;
853 verdict
= policy_check(p
, &filter
);
855 if (verdict
!= DENY
) {
858 filter
.class = POLICY_ITEM_GROUP
;
859 v
= policy_check(p
, &filter
);
864 log_full(LOG_AUTH
| (verdict
!= ALLOW
? LOG_WARNING
: LOG_DEBUG
),
865 "Hello permission check for uid=" UID_FMT
" gid=" GID_FMT
": %s",
866 uid
, gid
, strna(verdict_to_string(verdict
)));
868 return verdict
== ALLOW
;
871 bool policy_check_one_recv(Policy
*p
,
877 const char *interface
,
878 const char *member
) {
880 struct policy_check_filter filter
= {
881 .class = POLICY_ITEM_RECV
,
884 .message_type
= message_type
,
886 .interface
= interface
,
893 return policy_check(p
, &filter
) == ALLOW
;
896 bool policy_check_recv(Policy
*p
,
903 const char *interface
,
905 bool dbus_to_kernel
) {
907 char *n
, **nv
, *last
= NULL
;
913 if (set_isempty(names
) && strv_isempty(namesv
)) {
914 allow
= policy_check_one_recv(p
, uid
, gid
, message_type
, NULL
, path
, interface
, member
);
916 SET_FOREACH(n
, names
, i
) {
918 allow
= policy_check_one_recv(p
, uid
, gid
, message_type
, n
, path
, interface
, member
);
923 STRV_FOREACH(nv
, namesv
) {
925 allow
= policy_check_one_recv(p
, uid
, gid
, message_type
, *nv
, path
, interface
, member
);
932 log_full(LOG_AUTH
| (!allow
? LOG_WARNING
: LOG_DEBUG
),
933 "Receive permission check %s for uid=" UID_FMT
" gid=" GID_FMT
" message=%s name=%s path=%s interface=%s member=%s: %s",
934 dbus_to_kernel
? "dbus-1 to kernel" : "kernel to dbus-1", uid
, gid
, bus_message_type_to_string(message_type
), strna(last
),
935 strna(path
), strna(interface
), strna(member
), allow
? "ALLOW" : "DENY");
940 bool policy_check_one_send(Policy
*p
,
946 const char *interface
,
947 const char *member
) {
949 struct policy_check_filter filter
= {
950 .class = POLICY_ITEM_SEND
,
953 .message_type
= message_type
,
955 .interface
= interface
,
962 return policy_check(p
, &filter
) == ALLOW
;
965 bool policy_check_send(Policy
*p
,
972 const char *interface
,
975 char **out_used_name
) {
977 char *n
, **nv
, *last
= NULL
;
983 if (set_isempty(names
) && strv_isempty(namesv
)) {
984 allow
= policy_check_one_send(p
, uid
, gid
, message_type
, NULL
, path
, interface
, member
);
986 SET_FOREACH(n
, names
, i
) {
988 allow
= policy_check_one_send(p
, uid
, gid
, message_type
, n
, path
, interface
, member
);
993 STRV_FOREACH(nv
, namesv
) {
995 allow
= policy_check_one_send(p
, uid
, gid
, message_type
, *nv
, path
, interface
, member
);
1003 *out_used_name
= last
;
1005 log_full(LOG_AUTH
| (!allow
? LOG_WARNING
: LOG_DEBUG
),
1006 "Send permission check %s for uid=" UID_FMT
" gid=" GID_FMT
" message=%s name=%s path=%s interface=%s member=%s: %s",
1007 dbus_to_kernel
? "dbus-1 to kernel" : "kernel to dbus-1", uid
, gid
, bus_message_type_to_string(message_type
), strna(last
),
1008 strna(path
), strna(interface
), strna(member
), allow
? "ALLOW" : "DENY");
1013 int policy_load(Policy
*p
, char **files
) {
1019 STRV_FOREACH(i
, files
) {
1021 r
= file_load(p
, *i
);
1023 _cleanup_strv_free_
char **l
= NULL
;
1026 r
= conf_files_list(&l
, ".conf", NULL
, *i
, NULL
);
1028 return log_error_errno(r
, "Failed to get configuration file list: %m");
1034 /* We ignore all errors but EISDIR, and just proceed. */
1040 void policy_free(Policy
*p
) {
1041 PolicyItem
*i
, *first
;
1046 while ((i
= p
->default_items
)) {
1047 LIST_REMOVE(items
, p
->default_items
, i
);
1048 policy_item_free(i
);
1051 while ((i
= p
->mandatory_items
)) {
1052 LIST_REMOVE(items
, p
->mandatory_items
, i
);
1053 policy_item_free(i
);
1056 while ((i
= p
->on_console_items
)) {
1057 LIST_REMOVE(items
, p
->on_console_items
, i
);
1058 policy_item_free(i
);
1061 while ((i
= p
->no_console_items
)) {
1062 LIST_REMOVE(items
, p
->no_console_items
, i
);
1063 policy_item_free(i
);
1066 while ((first
= hashmap_steal_first(p
->user_items
))) {
1068 while ((i
= first
)) {
1069 LIST_REMOVE(items
, first
, i
);
1070 policy_item_free(i
);
1074 while ((first
= hashmap_steal_first(p
->group_items
))) {
1076 while ((i
= first
)) {
1077 LIST_REMOVE(items
, first
, i
);
1078 policy_item_free(i
);
1082 hashmap_free(p
->user_items
);
1083 hashmap_free(p
->group_items
);
1085 p
->user_items
= p
->group_items
= NULL
;
1088 static void dump_items(PolicyItem
*items
, const char *prefix
) {
1098 LIST_FOREACH(items
, i
, items
) {
1100 printf("%sType: %s\n"
1102 prefix
, policy_item_type_to_string(i
->type
),
1103 prefix
, policy_item_class_to_string(i
->class));
1106 printf("%sInterface: %s\n",
1107 prefix
, i
->interface
);
1110 printf("%sMember: %s\n",
1114 printf("%sError: %s\n",
1118 printf("%sPath: %s\n",
1122 printf("%sName: %s\n",
1125 if (i
->message_type
!= 0)
1126 printf("%sMessage Type: %s\n",
1127 prefix
, bus_message_type_to_string(i
->message_type
));
1130 _cleanup_free_
char *user
;
1132 user
= uid_to_name(i
->uid
);
1134 printf("%sUser: %s ("UID_FMT
")\n",
1135 prefix
, strna(user
), i
->uid
);
1139 _cleanup_free_
char *group
;
1141 group
= gid_to_name(i
->gid
);
1143 printf("%sGroup: %s ("GID_FMT
")\n",
1144 prefix
, strna(group
), i
->gid
);
1146 printf("%s-\n", prefix
);
1150 static void dump_hashmap_items(Hashmap
*h
) {
1155 HASHMAP_FOREACH_KEY(i
, k
, h
, j
) {
1156 printf("\t%s Item for %u:\n", draw_special_char(DRAW_ARROW
), PTR_TO_UINT(k
));
1157 dump_items(i
, "\t\t");
1161 void policy_dump(Policy
*p
) {
1163 printf("%s Default Items:\n", draw_special_char(DRAW_ARROW
));
1164 dump_items(p
->default_items
, "\t");
1166 printf("%s Group Items:\n", draw_special_char(DRAW_ARROW
));
1167 dump_hashmap_items(p
->group_items
);
1169 printf("%s User Items:\n", draw_special_char(DRAW_ARROW
));
1170 dump_hashmap_items(p
->user_items
);
1172 printf("%s On-Console Items:\n", draw_special_char(DRAW_ARROW
));
1173 dump_items(p
->on_console_items
, "\t");
1175 printf("%s No-Console Items:\n", draw_special_char(DRAW_ARROW
));
1176 dump_items(p
->no_console_items
, "\t");
1178 printf("%s Mandatory Items:\n", draw_special_char(DRAW_ARROW
));
1179 dump_items(p
->mandatory_items
, "\t");
1184 int shared_policy_new(SharedPolicy
**out
) {
1188 sp
= new0(SharedPolicy
, 1);
1192 r
= pthread_mutex_init(&sp
->lock
, NULL
);
1194 r
= log_error_errno(r
, "Cannot initialize shared policy mutex: %m");
1198 r
= pthread_rwlock_init(&sp
->rwlock
, NULL
);
1200 r
= log_error_errno(r
, "Cannot initialize shared policy rwlock: %m");
1208 /* pthread lock destruction is not fail-safe... meh! */
1210 pthread_mutex_destroy(&sp
->lock
);
1216 SharedPolicy
*shared_policy_free(SharedPolicy
*sp
) {
1220 policy_free(sp
->policy
);
1221 pthread_rwlock_destroy(&sp
->rwlock
);
1222 pthread_mutex_destroy(&sp
->lock
);
1223 strv_free(sp
->configuration
);
1229 static int shared_policy_reload_unlocked(SharedPolicy
*sp
, char **configuration
) {
1230 Policy old
, buffer
= {};
1236 r
= policy_load(&buffer
, configuration
);
1238 return log_error_errno(r
, "Failed to load policy: %m");
1240 log_debug("Reloading configuration");
1241 /* policy_dump(&buffer); */
1243 pthread_rwlock_wrlock(&sp
->rwlock
);
1244 memcpy(&old
, &sp
->buffer
, sizeof(old
));
1245 memcpy(&sp
->buffer
, &buffer
, sizeof(buffer
));
1246 free_old
= !!sp
->policy
;
1247 sp
->policy
= &sp
->buffer
;
1248 pthread_rwlock_unlock(&sp
->rwlock
);
1256 int shared_policy_reload(SharedPolicy
*sp
) {
1261 pthread_mutex_lock(&sp
->lock
);
1262 r
= shared_policy_reload_unlocked(sp
, sp
->configuration
);
1263 pthread_mutex_unlock(&sp
->lock
);
1268 int shared_policy_preload(SharedPolicy
*sp
, char **configuration
) {
1269 _cleanup_strv_free_
char **conf
= NULL
;
1274 conf
= strv_copy(configuration
);
1278 pthread_mutex_lock(&sp
->lock
);
1280 r
= shared_policy_reload_unlocked(sp
, conf
);
1282 sp
->configuration
= conf
;
1286 pthread_mutex_unlock(&sp
->lock
);
1291 Policy
*shared_policy_acquire(SharedPolicy
*sp
) {
1294 pthread_rwlock_rdlock(&sp
->rwlock
);
1297 pthread_rwlock_unlock(&sp
->rwlock
);
1302 void shared_policy_release(SharedPolicy
*sp
, Policy
*p
) {
1304 assert(!p
|| sp
->policy
== p
);
1307 pthread_rwlock_unlock(&sp
->rwlock
);
1310 static const char* const policy_item_type_table
[_POLICY_ITEM_TYPE_MAX
] = {
1311 [_POLICY_ITEM_TYPE_UNSET
] = "unset",
1312 [POLICY_ITEM_ALLOW
] = "allow",
1313 [POLICY_ITEM_DENY
] = "deny",
1315 DEFINE_STRING_TABLE_LOOKUP(policy_item_type
, PolicyItemType
);
1317 static const char* const policy_item_class_table
[_POLICY_ITEM_CLASS_MAX
] = {
1318 [_POLICY_ITEM_CLASS_UNSET
] = "unset",
1319 [POLICY_ITEM_SEND
] = "send",
1320 [POLICY_ITEM_RECV
] = "recv",
1321 [POLICY_ITEM_OWN
] = "own",
1322 [POLICY_ITEM_OWN_PREFIX
] = "own-prefix",
1323 [POLICY_ITEM_USER
] = "user",
1324 [POLICY_ITEM_GROUP
] = "group",
1325 [POLICY_ITEM_IGNORE
] = "ignore",
1327 DEFINE_STRING_TABLE_LOOKUP(policy_item_class
, PolicyItemClass
);