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 "alloc-util.h"
25 #include "bus-internal.h"
26 #include "bus-xml-policy.h"
27 #include "conf-files.h"
29 #include "formats-util.h"
30 #include "locale-util.h"
32 #include "string-table.h"
33 #include "string-util.h"
35 #include "user-util.h"
38 static void policy_item_free(PolicyItem
*i
) {
49 DEFINE_TRIVIAL_CLEANUP_FUNC(PolicyItem
*, policy_item_free
);
51 static void item_append(PolicyItem
*i
, PolicyItem
**list
) {
55 LIST_FIND_TAIL(items
, *list
, tail
);
56 LIST_INSERT_AFTER(items
, *list
, tail
, i
);
59 static int file_load(Policy
*p
, const char *path
) {
61 _cleanup_free_
char *c
= NULL
, *policy_user
= NULL
, *policy_group
= NULL
;
62 _cleanup_(policy_item_freep
) PolicyItem
*i
= NULL
;
63 void *xml_state
= NULL
;
76 STATE_POLICY_OTHER_ATTRIBUTE
,
78 STATE_ALLOW_DENY_INTERFACE
,
79 STATE_ALLOW_DENY_MEMBER
,
80 STATE_ALLOW_DENY_ERROR
,
81 STATE_ALLOW_DENY_PATH
,
82 STATE_ALLOW_DENY_MESSAGE_TYPE
,
83 STATE_ALLOW_DENY_NAME
,
84 STATE_ALLOW_DENY_OTHER_ATTRIBUTE
,
86 } state
= STATE_OUTSIDE
;
90 POLICY_CATEGORY_DEFAULT
,
91 POLICY_CATEGORY_MANDATORY
,
92 POLICY_CATEGORY_ON_CONSOLE
,
93 POLICY_CATEGORY_NO_CONSOLE
,
96 } policy_category
= POLICY_CATEGORY_NONE
;
102 r
= read_full_file(path
, &c
, NULL
);
109 return log_error_errno(r
, "Failed to load %s: %m", path
);
114 _cleanup_free_
char *name
= NULL
;
117 t
= xml_tokenize(&q
, &name
, &xml_state
, &line
);
119 return log_error_errno(t
, "XML parse failure in %s: %m", path
);
125 if (t
== XML_TAG_OPEN
) {
126 if (streq(name
, "busconfig"))
127 state
= STATE_BUSCONFIG
;
129 log_error("Unexpected tag %s at %s:%u.", name
, path
, line
);
133 } else if (t
== XML_END
)
135 else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
136 log_error("Unexpected token (1) at %s:%u.", path
, line
);
142 case STATE_BUSCONFIG
:
144 if (t
== XML_TAG_OPEN
) {
145 if (streq(name
, "policy")) {
146 state
= STATE_POLICY
;
147 policy_category
= POLICY_CATEGORY_NONE
;
150 policy_user
= policy_group
= NULL
;
155 } else if (t
== XML_TAG_CLOSE_EMPTY
||
156 (t
== XML_TAG_CLOSE
&& streq(name
, "busconfig")))
157 state
= STATE_OUTSIDE
;
158 else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
159 log_error("Unexpected token (2) at %s:%u.", path
, line
);
167 if (t
== XML_ATTRIBUTE_NAME
) {
168 if (streq(name
, "context"))
169 state
= STATE_POLICY_CONTEXT
;
170 else if (streq(name
, "at_console"))
171 state
= STATE_POLICY_CONSOLE
;
172 else if (streq(name
, "user"))
173 state
= STATE_POLICY_USER
;
174 else if (streq(name
, "group"))
175 state
= STATE_POLICY_GROUP
;
177 log_warning("Attribute %s of <policy> tag unknown at %s:%u, ignoring.", name
, path
, line
);
178 state
= STATE_POLICY_OTHER_ATTRIBUTE
;
180 } else if (t
== XML_TAG_CLOSE_EMPTY
||
181 (t
== XML_TAG_CLOSE
&& streq(name
, "policy")))
182 state
= STATE_BUSCONFIG
;
183 else if (t
== XML_TAG_OPEN
) {
186 if (streq(name
, "allow"))
187 it
= POLICY_ITEM_ALLOW
;
188 else if (streq(name
, "deny"))
189 it
= POLICY_ITEM_DENY
;
191 log_warning("Unknown tag %s in <policy> %s:%u.", name
, path
, line
);
196 i
= new0(PolicyItem
, 1);
201 state
= STATE_ALLOW_DENY
;
203 } else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
204 log_error("Unexpected token (3) at %s:%u.", path
, line
);
210 case STATE_POLICY_CONTEXT
:
212 if (t
== XML_ATTRIBUTE_VALUE
) {
213 if (streq(name
, "default")) {
214 policy_category
= POLICY_CATEGORY_DEFAULT
;
215 state
= STATE_POLICY
;
216 } else if (streq(name
, "mandatory")) {
217 policy_category
= POLICY_CATEGORY_MANDATORY
;
218 state
= STATE_POLICY
;
220 log_error("context= parameter %s unknown for <policy> at %s:%u.", name
, path
, line
);
224 log_error("Unexpected token (4) at %s:%u.", path
, line
);
230 case STATE_POLICY_CONSOLE
:
232 if (t
== XML_ATTRIBUTE_VALUE
) {
233 if (streq(name
, "true")) {
234 policy_category
= POLICY_CATEGORY_ON_CONSOLE
;
235 state
= STATE_POLICY
;
236 } else if (streq(name
, "false")) {
237 policy_category
= POLICY_CATEGORY_NO_CONSOLE
;
238 state
= STATE_POLICY
;
240 log_error("at_console= parameter %s unknown for <policy> at %s:%u.", name
, path
, line
);
244 log_error("Unexpected token (4.1) at %s:%u.", path
, line
);
250 case STATE_POLICY_USER
:
252 if (t
== XML_ATTRIBUTE_VALUE
) {
256 policy_category
= POLICY_CATEGORY_USER
;
257 state
= STATE_POLICY
;
259 log_error("Unexpected token (5) in %s:%u.", path
, line
);
265 case STATE_POLICY_GROUP
:
267 if (t
== XML_ATTRIBUTE_VALUE
) {
271 policy_category
= POLICY_CATEGORY_GROUP
;
272 state
= STATE_POLICY
;
274 log_error("Unexpected token (6) at %s:%u.", path
, line
);
280 case STATE_POLICY_OTHER_ATTRIBUTE
:
282 if (t
== XML_ATTRIBUTE_VALUE
)
283 state
= STATE_POLICY
;
285 log_error("Unexpected token (7) in %s:%u.", path
, line
);
291 case STATE_ALLOW_DENY
:
295 if (t
== XML_ATTRIBUTE_NAME
) {
298 if (startswith(name
, "send_"))
299 ic
= POLICY_ITEM_SEND
;
300 else if (startswith(name
, "receive_"))
301 ic
= POLICY_ITEM_RECV
;
302 else if (streq(name
, "own"))
303 ic
= POLICY_ITEM_OWN
;
304 else if (streq(name
, "own_prefix"))
305 ic
= POLICY_ITEM_OWN_PREFIX
;
306 else if (streq(name
, "user"))
307 ic
= POLICY_ITEM_USER
;
308 else if (streq(name
, "group"))
309 ic
= POLICY_ITEM_GROUP
;
310 else if (STR_IN_SET(name
, "eavesdrop", "log")) {
311 log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name
, path
, line
);
312 state
= STATE_ALLOW_DENY_OTHER_ATTRIBUTE
;
315 log_error("Unknown attribute %s= at %s:%u, ignoring.", name
, path
, line
);
316 state
= STATE_ALLOW_DENY_OTHER_ATTRIBUTE
;
320 if (i
->class != _POLICY_ITEM_CLASS_UNSET
&& ic
!= i
->class) {
321 log_error("send_, receive_/eavesdrop fields mixed on same tag at %s:%u.", path
, line
);
327 if (ic
== POLICY_ITEM_SEND
|| ic
== POLICY_ITEM_RECV
) {
330 u
= strchr(name
, '_');
335 if (streq(u
, "interface"))
336 state
= STATE_ALLOW_DENY_INTERFACE
;
337 else if (streq(u
, "member"))
338 state
= STATE_ALLOW_DENY_MEMBER
;
339 else if (streq(u
, "error"))
340 state
= STATE_ALLOW_DENY_ERROR
;
341 else if (streq(u
, "path"))
342 state
= STATE_ALLOW_DENY_PATH
;
343 else if (streq(u
, "type"))
344 state
= STATE_ALLOW_DENY_MESSAGE_TYPE
;
345 else if ((streq(u
, "destination") && ic
== POLICY_ITEM_SEND
) ||
346 (streq(u
, "sender") && ic
== POLICY_ITEM_RECV
))
347 state
= STATE_ALLOW_DENY_NAME
;
349 if (streq(u
, "requested_reply"))
350 log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name
, path
, line
);
352 log_error("Unknown attribute %s= at %s:%u, ignoring.", name
, path
, line
);
353 state
= STATE_ALLOW_DENY_OTHER_ATTRIBUTE
;
357 state
= STATE_ALLOW_DENY_NAME
;
359 } else if (t
== XML_TAG_CLOSE_EMPTY
||
360 (t
== XML_TAG_CLOSE
&& streq(name
, i
->type
== POLICY_ITEM_ALLOW
? "allow" : "deny"))) {
362 /* If the tag is fully empty so far, we consider it a recv */
363 if (i
->class == _POLICY_ITEM_CLASS_UNSET
)
364 i
->class = POLICY_ITEM_RECV
;
366 if (policy_category
== POLICY_CATEGORY_DEFAULT
)
367 item_append(i
, &p
->default_items
);
368 else if (policy_category
== POLICY_CATEGORY_MANDATORY
)
369 item_append(i
, &p
->mandatory_items
);
370 else if (policy_category
== POLICY_CATEGORY_ON_CONSOLE
)
371 item_append(i
, &p
->on_console_items
);
372 else if (policy_category
== POLICY_CATEGORY_NO_CONSOLE
)
373 item_append(i
, &p
->no_console_items
);
374 else if (policy_category
== POLICY_CATEGORY_USER
) {
375 const char *u
= policy_user
;
377 assert_cc(sizeof(uid_t
) == sizeof(uint32_t));
379 r
= hashmap_ensure_allocated(&p
->user_items
, NULL
);
384 log_error("User policy without name");
388 r
= get_user_creds(&u
, &i
->uid
, NULL
, NULL
, NULL
);
390 log_error_errno(r
, "Failed to resolve user %s, ignoring policy: %m", u
);
395 first
= hashmap_get(p
->user_items
, UINT32_TO_PTR(i
->uid
));
396 item_append(i
, &first
);
399 r
= hashmap_replace(p
->user_items
, UINT32_TO_PTR(i
->uid
), first
);
401 LIST_REMOVE(items
, first
, i
);
406 } else if (policy_category
== POLICY_CATEGORY_GROUP
) {
407 const char *g
= policy_group
;
409 assert_cc(sizeof(gid_t
) == sizeof(uint32_t));
411 r
= hashmap_ensure_allocated(&p
->group_items
, NULL
);
416 log_error("Group policy without name");
420 r
= get_group_creds(&g
, &i
->gid
);
422 log_error_errno(r
, "Failed to resolve group %s, ignoring policy: %m", g
);
427 first
= hashmap_get(p
->group_items
, UINT32_TO_PTR(i
->gid
));
428 item_append(i
, &first
);
431 r
= hashmap_replace(p
->group_items
, UINT32_TO_PTR(i
->gid
), first
);
433 LIST_REMOVE(items
, first
, i
);
439 state
= STATE_POLICY
;
442 } else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
443 log_error("Unexpected token (8) at %s:%u.", path
, line
);
449 case STATE_ALLOW_DENY_INTERFACE
:
451 if (t
== XML_ATTRIBUTE_VALUE
) {
454 log_error("Duplicate interface at %s:%u.", path
, line
);
458 if (!streq(name
, "*")) {
462 state
= STATE_ALLOW_DENY
;
464 log_error("Unexpected token (9) at %s:%u.", path
, line
);
470 case STATE_ALLOW_DENY_MEMBER
:
472 if (t
== XML_ATTRIBUTE_VALUE
) {
475 log_error("Duplicate member in %s:%u.", path
, line
);
479 if (!streq(name
, "*")) {
483 state
= STATE_ALLOW_DENY
;
485 log_error("Unexpected token (10) in %s:%u.", path
, line
);
491 case STATE_ALLOW_DENY_ERROR
:
493 if (t
== XML_ATTRIBUTE_VALUE
) {
496 log_error("Duplicate error in %s:%u.", path
, line
);
500 if (!streq(name
, "*")) {
504 state
= STATE_ALLOW_DENY
;
506 log_error("Unexpected token (11) in %s:%u.", path
, line
);
512 case STATE_ALLOW_DENY_PATH
:
514 if (t
== XML_ATTRIBUTE_VALUE
) {
517 log_error("Duplicate path in %s:%u.", path
, line
);
521 if (!streq(name
, "*")) {
525 state
= STATE_ALLOW_DENY
;
527 log_error("Unexpected token (12) in %s:%u.", path
, line
);
533 case STATE_ALLOW_DENY_MESSAGE_TYPE
:
535 if (t
== XML_ATTRIBUTE_VALUE
) {
538 if (i
->message_type
!= 0) {
539 log_error("Duplicate message type in %s:%u.", path
, line
);
543 if (!streq(name
, "*")) {
544 r
= bus_message_type_from_string(name
, &i
->message_type
);
546 log_error("Invalid message type in %s:%u.", path
, line
);
551 state
= STATE_ALLOW_DENY
;
553 log_error("Unexpected token (13) in %s:%u.", path
, line
);
559 case STATE_ALLOW_DENY_NAME
:
561 if (t
== XML_ATTRIBUTE_VALUE
) {
564 log_error("Duplicate name in %s:%u.", path
, line
);
569 case POLICY_ITEM_USER
:
570 if (!streq(name
, "*")) {
571 const char *u
= name
;
573 r
= get_user_creds(&u
, &i
->uid
, NULL
, NULL
, NULL
);
575 log_error_errno(r
, "Failed to resolve user %s: %m", name
);
580 case POLICY_ITEM_GROUP
:
581 if (!streq(name
, "*")) {
582 const char *g
= name
;
584 r
= get_group_creds(&g
, &i
->gid
);
586 log_error_errno(r
, "Failed to resolve group %s: %m", name
);
592 case POLICY_ITEM_SEND
:
593 case POLICY_ITEM_RECV
:
595 if (streq(name
, "*"))
607 state
= STATE_ALLOW_DENY
;
609 log_error("Unexpected token (14) in %s:%u.", path
, line
);
615 case STATE_ALLOW_DENY_OTHER_ATTRIBUTE
:
617 if (t
== XML_ATTRIBUTE_VALUE
)
618 state
= STATE_ALLOW_DENY
;
620 log_error("Unexpected token (15) in %s:%u.", path
, line
);
628 if (t
== XML_TAG_OPEN
)
630 else if (t
== XML_TAG_CLOSE
|| t
== XML_TAG_CLOSE_EMPTY
) {
633 state
= STATE_BUSCONFIG
;
649 static const char *verdict_to_string(int v
) {
663 struct policy_check_filter
{
664 PolicyItemClass
class;
669 const char *interface
;
674 static int is_permissive(PolicyItem
*i
) {
678 return (i
->type
== POLICY_ITEM_ALLOW
) ? ALLOW
: DENY
;
681 static int check_policy_item(PolicyItem
*i
, const struct policy_check_filter
*filter
) {
687 case POLICY_ITEM_SEND
:
688 case POLICY_ITEM_RECV
:
690 if (i
->name
&& !streq_ptr(i
->name
, filter
->name
))
693 if ((i
->message_type
!= 0) && (i
->message_type
!= filter
->message_type
))
696 if (i
->path
&& !streq_ptr(i
->path
, filter
->path
))
699 if (i
->member
&& !streq_ptr(i
->member
, filter
->member
))
702 if (i
->interface
&& !streq_ptr(i
->interface
, filter
->interface
))
705 return is_permissive(i
);
707 case POLICY_ITEM_OWN
:
708 assert(filter
->name
);
710 if (streq(i
->name
, "*") || streq(i
->name
, filter
->name
))
711 return is_permissive(i
);
714 case POLICY_ITEM_OWN_PREFIX
:
715 assert(filter
->name
);
717 if (streq(i
->name
, "*") || service_name_startswith(filter
->name
, i
->name
))
718 return is_permissive(i
);
721 case POLICY_ITEM_USER
:
722 if (filter
->uid
!= UID_INVALID
)
723 if ((streq_ptr(i
->name
, "*") || (i
->uid_valid
&& i
->uid
== filter
->uid
)))
724 return is_permissive(i
);
727 case POLICY_ITEM_GROUP
:
728 if (filter
->gid
!= GID_INVALID
)
729 if ((streq_ptr(i
->name
, "*") || (i
->gid_valid
&& i
->gid
== filter
->gid
)))
730 return is_permissive(i
);
733 case POLICY_ITEM_IGNORE
:
741 static int check_policy_items(PolicyItem
*items
, const struct policy_check_filter
*filter
) {
748 /* Check all policies in a set - a broader one might be followed by a more specific one,
749 * and the order of rules in policy definitions matters */
750 LIST_FOREACH(items
, i
, items
) {
753 if (i
->class != filter
->class &&
754 !(i
->class == POLICY_ITEM_OWN_PREFIX
&& filter
->class == POLICY_ITEM_OWN
))
757 v
= check_policy_item(i
, filter
);
765 static int policy_check(Policy
*p
, const struct policy_check_filter
*filter
) {
773 assert(IN_SET(filter
->class, POLICY_ITEM_SEND
, POLICY_ITEM_RECV
, POLICY_ITEM_OWN
, POLICY_ITEM_USER
, POLICY_ITEM_GROUP
));
776 * The policy check is implemented by the following logic:
778 * 1. Check default items
779 * 2. Check group items
780 * 3. Check user items
781 * 4. Check on/no_console items
782 * 5. Check mandatory items
784 * Later rules override earlier rules.
787 verdict
= check_policy_items(p
->default_items
, filter
);
789 if (filter
->gid
!= GID_INVALID
) {
790 items
= hashmap_get(p
->group_items
, UINT32_TO_PTR(filter
->gid
));
792 v
= check_policy_items(items
, filter
);
798 if (filter
->uid
!= UID_INVALID
) {
799 items
= hashmap_get(p
->user_items
, UINT32_TO_PTR(filter
->uid
));
801 v
= check_policy_items(items
, filter
);
807 if (filter
->uid
!= UID_INVALID
&& sd_uid_get_seats(filter
->uid
, -1, NULL
) > 0)
808 v
= check_policy_items(p
->on_console_items
, filter
);
810 v
= check_policy_items(p
->no_console_items
, filter
);
814 v
= check_policy_items(p
->mandatory_items
, filter
);
821 bool policy_check_own(Policy
*p
, uid_t uid
, gid_t gid
, const char *name
) {
823 struct policy_check_filter filter
= {
824 .class = POLICY_ITEM_OWN
,
835 verdict
= policy_check(p
, &filter
);
837 log_full(LOG_AUTH
| (verdict
!= ALLOW
? LOG_WARNING
: LOG_DEBUG
),
838 "Ownership permission check for uid=" UID_FMT
" gid=" GID_FMT
" name=%s: %s",
839 uid
, gid
, strna(name
), strna(verdict_to_string(verdict
)));
841 return verdict
== ALLOW
;
844 bool policy_check_hello(Policy
*p
, uid_t uid
, gid_t gid
) {
846 struct policy_check_filter filter
= {
854 filter
.class = POLICY_ITEM_USER
;
855 verdict
= policy_check(p
, &filter
);
857 if (verdict
!= DENY
) {
860 filter
.class = POLICY_ITEM_GROUP
;
861 v
= policy_check(p
, &filter
);
866 log_full(LOG_AUTH
| (verdict
!= ALLOW
? LOG_WARNING
: LOG_DEBUG
),
867 "Hello permission check for uid=" UID_FMT
" gid=" GID_FMT
": %s",
868 uid
, gid
, strna(verdict_to_string(verdict
)));
870 return verdict
== ALLOW
;
873 bool policy_check_one_recv(Policy
*p
,
879 const char *interface
,
880 const char *member
) {
882 struct policy_check_filter filter
= {
883 .class = POLICY_ITEM_RECV
,
886 .message_type
= message_type
,
888 .interface
= interface
,
895 return policy_check(p
, &filter
) == ALLOW
;
898 bool policy_check_recv(Policy
*p
,
905 const char *interface
,
907 bool dbus_to_kernel
) {
909 char *n
, **nv
, *last
= NULL
;
915 if (set_isempty(names
) && strv_isempty(namesv
)) {
916 allow
= policy_check_one_recv(p
, uid
, gid
, message_type
, NULL
, path
, interface
, member
);
918 SET_FOREACH(n
, names
, i
) {
920 allow
= policy_check_one_recv(p
, uid
, gid
, message_type
, n
, path
, interface
, member
);
925 STRV_FOREACH(nv
, namesv
) {
927 allow
= policy_check_one_recv(p
, uid
, gid
, message_type
, *nv
, path
, interface
, member
);
934 log_full(LOG_AUTH
| (!allow
? LOG_WARNING
: LOG_DEBUG
),
935 "Receive permission check %s for uid=" UID_FMT
" gid=" GID_FMT
" message=%s name=%s path=%s interface=%s member=%s: %s",
936 dbus_to_kernel
? "dbus-1 to kernel" : "kernel to dbus-1", uid
, gid
, bus_message_type_to_string(message_type
), strna(last
),
937 strna(path
), strna(interface
), strna(member
), allow
? "ALLOW" : "DENY");
942 bool policy_check_one_send(Policy
*p
,
948 const char *interface
,
949 const char *member
) {
951 struct policy_check_filter filter
= {
952 .class = POLICY_ITEM_SEND
,
955 .message_type
= message_type
,
957 .interface
= interface
,
964 return policy_check(p
, &filter
) == ALLOW
;
967 bool policy_check_send(Policy
*p
,
974 const char *interface
,
977 char **out_used_name
) {
979 char *n
, **nv
, *last
= NULL
;
985 if (set_isempty(names
) && strv_isempty(namesv
)) {
986 allow
= policy_check_one_send(p
, uid
, gid
, message_type
, NULL
, path
, interface
, member
);
988 SET_FOREACH(n
, names
, i
) {
990 allow
= policy_check_one_send(p
, uid
, gid
, message_type
, n
, path
, interface
, member
);
995 STRV_FOREACH(nv
, namesv
) {
997 allow
= policy_check_one_send(p
, uid
, gid
, message_type
, *nv
, path
, interface
, member
);
1005 *out_used_name
= last
;
1007 log_full(LOG_AUTH
| (!allow
? LOG_WARNING
: LOG_DEBUG
),
1008 "Send permission check %s for uid=" UID_FMT
" gid=" GID_FMT
" message=%s name=%s path=%s interface=%s member=%s: %s",
1009 dbus_to_kernel
? "dbus-1 to kernel" : "kernel to dbus-1", uid
, gid
, bus_message_type_to_string(message_type
), strna(last
),
1010 strna(path
), strna(interface
), strna(member
), allow
? "ALLOW" : "DENY");
1015 int policy_load(Policy
*p
, char **files
) {
1021 STRV_FOREACH(i
, files
) {
1023 r
= file_load(p
, *i
);
1025 _cleanup_strv_free_
char **l
= NULL
;
1028 r
= conf_files_list(&l
, ".conf", NULL
, *i
, NULL
);
1030 return log_error_errno(r
, "Failed to get configuration file list: %m");
1036 /* We ignore all errors but EISDIR, and just proceed. */
1042 void policy_free(Policy
*p
) {
1043 PolicyItem
*i
, *first
;
1048 while ((i
= p
->default_items
)) {
1049 LIST_REMOVE(items
, p
->default_items
, i
);
1050 policy_item_free(i
);
1053 while ((i
= p
->mandatory_items
)) {
1054 LIST_REMOVE(items
, p
->mandatory_items
, i
);
1055 policy_item_free(i
);
1058 while ((i
= p
->on_console_items
)) {
1059 LIST_REMOVE(items
, p
->on_console_items
, i
);
1060 policy_item_free(i
);
1063 while ((i
= p
->no_console_items
)) {
1064 LIST_REMOVE(items
, p
->no_console_items
, i
);
1065 policy_item_free(i
);
1068 while ((first
= hashmap_steal_first(p
->user_items
))) {
1070 while ((i
= first
)) {
1071 LIST_REMOVE(items
, first
, i
);
1072 policy_item_free(i
);
1076 while ((first
= hashmap_steal_first(p
->group_items
))) {
1078 while ((i
= first
)) {
1079 LIST_REMOVE(items
, first
, i
);
1080 policy_item_free(i
);
1084 hashmap_free(p
->user_items
);
1085 hashmap_free(p
->group_items
);
1087 p
->user_items
= p
->group_items
= NULL
;
1090 static void dump_items(PolicyItem
*items
, const char *prefix
) {
1100 LIST_FOREACH(items
, i
, items
) {
1102 printf("%sType: %s\n"
1104 prefix
, policy_item_type_to_string(i
->type
),
1105 prefix
, policy_item_class_to_string(i
->class));
1108 printf("%sInterface: %s\n",
1109 prefix
, i
->interface
);
1112 printf("%sMember: %s\n",
1116 printf("%sError: %s\n",
1120 printf("%sPath: %s\n",
1124 printf("%sName: %s\n",
1127 if (i
->message_type
!= 0)
1128 printf("%sMessage Type: %s\n",
1129 prefix
, bus_message_type_to_string(i
->message_type
));
1132 _cleanup_free_
char *user
;
1134 user
= uid_to_name(i
->uid
);
1136 printf("%sUser: %s ("UID_FMT
")\n",
1137 prefix
, strna(user
), i
->uid
);
1141 _cleanup_free_
char *group
;
1143 group
= gid_to_name(i
->gid
);
1145 printf("%sGroup: %s ("GID_FMT
")\n",
1146 prefix
, strna(group
), i
->gid
);
1148 printf("%s-\n", prefix
);
1152 static void dump_hashmap_items(Hashmap
*h
) {
1157 HASHMAP_FOREACH_KEY(i
, k
, h
, j
) {
1158 printf("\t%s Item for %u:\n", draw_special_char(DRAW_ARROW
), PTR_TO_UINT(k
));
1159 dump_items(i
, "\t\t");
1163 void policy_dump(Policy
*p
) {
1165 printf("%s Default Items:\n", draw_special_char(DRAW_ARROW
));
1166 dump_items(p
->default_items
, "\t");
1168 printf("%s Group Items:\n", draw_special_char(DRAW_ARROW
));
1169 dump_hashmap_items(p
->group_items
);
1171 printf("%s User Items:\n", draw_special_char(DRAW_ARROW
));
1172 dump_hashmap_items(p
->user_items
);
1174 printf("%s On-Console Items:\n", draw_special_char(DRAW_ARROW
));
1175 dump_items(p
->on_console_items
, "\t");
1177 printf("%s No-Console Items:\n", draw_special_char(DRAW_ARROW
));
1178 dump_items(p
->no_console_items
, "\t");
1180 printf("%s Mandatory Items:\n", draw_special_char(DRAW_ARROW
));
1181 dump_items(p
->mandatory_items
, "\t");
1186 int shared_policy_new(SharedPolicy
**out
) {
1190 sp
= new0(SharedPolicy
, 1);
1194 r
= pthread_mutex_init(&sp
->lock
, NULL
);
1196 r
= log_error_errno(r
, "Cannot initialize shared policy mutex: %m");
1200 r
= pthread_rwlock_init(&sp
->rwlock
, NULL
);
1202 r
= log_error_errno(r
, "Cannot initialize shared policy rwlock: %m");
1210 /* pthread lock destruction is not fail-safe... meh! */
1212 pthread_mutex_destroy(&sp
->lock
);
1218 SharedPolicy
*shared_policy_free(SharedPolicy
*sp
) {
1222 policy_free(sp
->policy
);
1223 pthread_rwlock_destroy(&sp
->rwlock
);
1224 pthread_mutex_destroy(&sp
->lock
);
1225 strv_free(sp
->configuration
);
1231 static int shared_policy_reload_unlocked(SharedPolicy
*sp
, char **configuration
) {
1232 Policy old
, buffer
= {};
1238 r
= policy_load(&buffer
, configuration
);
1240 return log_error_errno(r
, "Failed to load policy: %m");
1242 log_debug("Reloading configuration");
1243 /* policy_dump(&buffer); */
1245 pthread_rwlock_wrlock(&sp
->rwlock
);
1246 memcpy(&old
, &sp
->buffer
, sizeof(old
));
1247 memcpy(&sp
->buffer
, &buffer
, sizeof(buffer
));
1248 free_old
= !!sp
->policy
;
1249 sp
->policy
= &sp
->buffer
;
1250 pthread_rwlock_unlock(&sp
->rwlock
);
1258 int shared_policy_reload(SharedPolicy
*sp
) {
1263 pthread_mutex_lock(&sp
->lock
);
1264 r
= shared_policy_reload_unlocked(sp
, sp
->configuration
);
1265 pthread_mutex_unlock(&sp
->lock
);
1270 int shared_policy_preload(SharedPolicy
*sp
, char **configuration
) {
1271 _cleanup_strv_free_
char **conf
= NULL
;
1276 conf
= strv_copy(configuration
);
1280 pthread_mutex_lock(&sp
->lock
);
1282 r
= shared_policy_reload_unlocked(sp
, conf
);
1284 sp
->configuration
= conf
;
1288 pthread_mutex_unlock(&sp
->lock
);
1293 Policy
*shared_policy_acquire(SharedPolicy
*sp
) {
1296 pthread_rwlock_rdlock(&sp
->rwlock
);
1299 pthread_rwlock_unlock(&sp
->rwlock
);
1304 void shared_policy_release(SharedPolicy
*sp
, Policy
*p
) {
1306 assert(!p
|| sp
->policy
== p
);
1309 pthread_rwlock_unlock(&sp
->rwlock
);
1312 static const char* const policy_item_type_table
[_POLICY_ITEM_TYPE_MAX
] = {
1313 [_POLICY_ITEM_TYPE_UNSET
] = "unset",
1314 [POLICY_ITEM_ALLOW
] = "allow",
1315 [POLICY_ITEM_DENY
] = "deny",
1317 DEFINE_STRING_TABLE_LOOKUP(policy_item_type
, PolicyItemType
);
1319 static const char* const policy_item_class_table
[_POLICY_ITEM_CLASS_MAX
] = {
1320 [_POLICY_ITEM_CLASS_UNSET
] = "unset",
1321 [POLICY_ITEM_SEND
] = "send",
1322 [POLICY_ITEM_RECV
] = "recv",
1323 [POLICY_ITEM_OWN
] = "own",
1324 [POLICY_ITEM_OWN_PREFIX
] = "own-prefix",
1325 [POLICY_ITEM_USER
] = "user",
1326 [POLICY_ITEM_GROUP
] = "group",
1327 [POLICY_ITEM_IGNORE
] = "ignore",
1329 DEFINE_STRING_TABLE_LOOKUP(policy_item_class
, PolicyItemClass
);