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/>.
26 #include "conf-files.h"
27 #include "bus-internal.h"
28 #include "bus-xml-policy.h"
30 #include "formats-util.h"
32 static void policy_item_free(PolicyItem
*i
) {
43 DEFINE_TRIVIAL_CLEANUP_FUNC(PolicyItem
*, policy_item_free
);
45 static void item_append(PolicyItem
*i
, PolicyItem
**list
) {
49 LIST_FIND_TAIL(items
, *list
, tail
);
50 LIST_INSERT_AFTER(items
, *list
, tail
, i
);
53 static int file_load(Policy
*p
, const char *path
) {
55 _cleanup_free_
char *c
= NULL
, *policy_user
= NULL
, *policy_group
= NULL
;
56 _cleanup_(policy_item_freep
) PolicyItem
*i
= NULL
;
57 void *xml_state
= NULL
;
70 STATE_POLICY_OTHER_ATTRIBUTE
,
72 STATE_ALLOW_DENY_INTERFACE
,
73 STATE_ALLOW_DENY_MEMBER
,
74 STATE_ALLOW_DENY_ERROR
,
75 STATE_ALLOW_DENY_PATH
,
76 STATE_ALLOW_DENY_MESSAGE_TYPE
,
77 STATE_ALLOW_DENY_NAME
,
78 STATE_ALLOW_DENY_OTHER_ATTRIBUTE
,
80 } state
= STATE_OUTSIDE
;
84 POLICY_CATEGORY_DEFAULT
,
85 POLICY_CATEGORY_MANDATORY
,
86 POLICY_CATEGORY_ON_CONSOLE
,
87 POLICY_CATEGORY_NO_CONSOLE
,
90 } policy_category
= POLICY_CATEGORY_NONE
;
96 r
= read_full_file(path
, &c
, NULL
);
103 return log_error_errno(r
, "Failed to load %s: %m", path
);
108 _cleanup_free_
char *name
= NULL
;
111 t
= xml_tokenize(&q
, &name
, &xml_state
, &line
);
113 return log_error_errno(t
, "XML parse failure in %s: %m", path
);
119 if (t
== XML_TAG_OPEN
) {
120 if (streq(name
, "busconfig"))
121 state
= STATE_BUSCONFIG
;
123 log_error("Unexpected tag %s at %s:%u.", name
, path
, line
);
127 } else if (t
== XML_END
)
129 else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
130 log_error("Unexpected token (1) at %s:%u.", path
, line
);
136 case STATE_BUSCONFIG
:
138 if (t
== XML_TAG_OPEN
) {
139 if (streq(name
, "policy")) {
140 state
= STATE_POLICY
;
141 policy_category
= POLICY_CATEGORY_NONE
;
144 policy_user
= policy_group
= NULL
;
149 } else if (t
== XML_TAG_CLOSE_EMPTY
||
150 (t
== XML_TAG_CLOSE
&& streq(name
, "busconfig")))
151 state
= STATE_OUTSIDE
;
152 else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
153 log_error("Unexpected token (2) at %s:%u.", path
, line
);
161 if (t
== XML_ATTRIBUTE_NAME
) {
162 if (streq(name
, "context"))
163 state
= STATE_POLICY_CONTEXT
;
164 else if (streq(name
, "at_console"))
165 state
= STATE_POLICY_CONSOLE
;
166 else if (streq(name
, "user"))
167 state
= STATE_POLICY_USER
;
168 else if (streq(name
, "group"))
169 state
= STATE_POLICY_GROUP
;
171 log_warning("Attribute %s of <policy> tag unknown at %s:%u, ignoring.", name
, path
, line
);
172 state
= STATE_POLICY_OTHER_ATTRIBUTE
;
174 } else if (t
== XML_TAG_CLOSE_EMPTY
||
175 (t
== XML_TAG_CLOSE
&& streq(name
, "policy")))
176 state
= STATE_BUSCONFIG
;
177 else if (t
== XML_TAG_OPEN
) {
180 if (streq(name
, "allow"))
181 it
= POLICY_ITEM_ALLOW
;
182 else if (streq(name
, "deny"))
183 it
= POLICY_ITEM_DENY
;
185 log_warning("Unknown tag %s in <policy> %s:%u.", name
, path
, line
);
190 i
= new0(PolicyItem
, 1);
195 state
= STATE_ALLOW_DENY
;
197 } else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
198 log_error("Unexpected token (3) at %s:%u.", path
, line
);
204 case STATE_POLICY_CONTEXT
:
206 if (t
== XML_ATTRIBUTE_VALUE
) {
207 if (streq(name
, "default")) {
208 policy_category
= POLICY_CATEGORY_DEFAULT
;
209 state
= STATE_POLICY
;
210 } else if (streq(name
, "mandatory")) {
211 policy_category
= POLICY_CATEGORY_MANDATORY
;
212 state
= STATE_POLICY
;
214 log_error("context= parameter %s unknown for <policy> at %s:%u.", name
, path
, line
);
218 log_error("Unexpected token (4) at %s:%u.", path
, line
);
224 case STATE_POLICY_CONSOLE
:
226 if (t
== XML_ATTRIBUTE_VALUE
) {
227 if (streq(name
, "true")) {
228 policy_category
= POLICY_CATEGORY_ON_CONSOLE
;
229 state
= STATE_POLICY
;
230 } else if (streq(name
, "false")) {
231 policy_category
= POLICY_CATEGORY_NO_CONSOLE
;
232 state
= STATE_POLICY
;
234 log_error("at_console= parameter %s unknown for <policy> at %s:%u.", name
, path
, line
);
238 log_error("Unexpected token (4.1) at %s:%u.", path
, line
);
244 case STATE_POLICY_USER
:
246 if (t
== XML_ATTRIBUTE_VALUE
) {
250 policy_category
= POLICY_CATEGORY_USER
;
251 state
= STATE_POLICY
;
253 log_error("Unexpected token (5) in %s:%u.", path
, line
);
259 case STATE_POLICY_GROUP
:
261 if (t
== XML_ATTRIBUTE_VALUE
) {
265 policy_category
= POLICY_CATEGORY_GROUP
;
266 state
= STATE_POLICY
;
268 log_error("Unexpected token (6) at %s:%u.", path
, line
);
274 case STATE_POLICY_OTHER_ATTRIBUTE
:
276 if (t
== XML_ATTRIBUTE_VALUE
)
277 state
= STATE_POLICY
;
279 log_error("Unexpected token (7) in %s:%u.", path
, line
);
285 case STATE_ALLOW_DENY
:
289 if (t
== XML_ATTRIBUTE_NAME
) {
292 if (startswith(name
, "send_"))
293 ic
= POLICY_ITEM_SEND
;
294 else if (startswith(name
, "receive_"))
295 ic
= POLICY_ITEM_RECV
;
296 else if (streq(name
, "own"))
297 ic
= POLICY_ITEM_OWN
;
298 else if (streq(name
, "own_prefix"))
299 ic
= POLICY_ITEM_OWN_PREFIX
;
300 else if (streq(name
, "user"))
301 ic
= POLICY_ITEM_USER
;
302 else if (streq(name
, "group"))
303 ic
= POLICY_ITEM_GROUP
;
304 else if (streq(name
, "eavesdrop")) {
305 log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name
, path
, line
);
306 state
= STATE_ALLOW_DENY_OTHER_ATTRIBUTE
;
309 log_error("Unknown attribute %s= at %s:%u, ignoring.", name
, path
, line
);
310 state
= STATE_ALLOW_DENY_OTHER_ATTRIBUTE
;
314 if (i
->class != _POLICY_ITEM_CLASS_UNSET
&& ic
!= i
->class) {
315 log_error("send_, receive_/eavesdrop fields mixed on same tag at %s:%u.", path
, line
);
321 if (ic
== POLICY_ITEM_SEND
|| ic
== POLICY_ITEM_RECV
) {
324 u
= strchr(name
, '_');
329 if (streq(u
, "interface"))
330 state
= STATE_ALLOW_DENY_INTERFACE
;
331 else if (streq(u
, "member"))
332 state
= STATE_ALLOW_DENY_MEMBER
;
333 else if (streq(u
, "error"))
334 state
= STATE_ALLOW_DENY_ERROR
;
335 else if (streq(u
, "path"))
336 state
= STATE_ALLOW_DENY_PATH
;
337 else if (streq(u
, "type"))
338 state
= STATE_ALLOW_DENY_MESSAGE_TYPE
;
339 else if ((streq(u
, "destination") && ic
== POLICY_ITEM_SEND
) ||
340 (streq(u
, "sender") && ic
== POLICY_ITEM_RECV
))
341 state
= STATE_ALLOW_DENY_NAME
;
343 if (streq(u
, "requested_reply"))
344 log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name
, path
, line
);
346 log_error("Unknown attribute %s= at %s:%u, ignoring.", name
, path
, line
);
347 state
= STATE_ALLOW_DENY_OTHER_ATTRIBUTE
;
351 state
= STATE_ALLOW_DENY_NAME
;
353 } else if (t
== XML_TAG_CLOSE_EMPTY
||
354 (t
== XML_TAG_CLOSE
&& streq(name
, i
->type
== POLICY_ITEM_ALLOW
? "allow" : "deny"))) {
356 /* If the tag is fully empty so far, we consider it a recv */
357 if (i
->class == _POLICY_ITEM_CLASS_UNSET
)
358 i
->class = POLICY_ITEM_RECV
;
360 if (policy_category
== POLICY_CATEGORY_DEFAULT
)
361 item_append(i
, &p
->default_items
);
362 else if (policy_category
== POLICY_CATEGORY_MANDATORY
)
363 item_append(i
, &p
->mandatory_items
);
364 else if (policy_category
== POLICY_CATEGORY_ON_CONSOLE
)
365 item_append(i
, &p
->on_console_items
);
366 else if (policy_category
== POLICY_CATEGORY_NO_CONSOLE
)
367 item_append(i
, &p
->no_console_items
);
368 else if (policy_category
== POLICY_CATEGORY_USER
) {
369 const char *u
= policy_user
;
371 assert_cc(sizeof(uid_t
) == sizeof(uint32_t));
373 r
= hashmap_ensure_allocated(&p
->user_items
, NULL
);
378 log_error("User policy without name");
382 r
= get_user_creds(&u
, &i
->uid
, NULL
, NULL
, NULL
);
384 log_error_errno(r
, "Failed to resolve user %s, ignoring policy: %m", u
);
389 first
= hashmap_get(p
->user_items
, UINT32_TO_PTR(i
->uid
));
390 item_append(i
, &first
);
393 r
= hashmap_replace(p
->user_items
, UINT32_TO_PTR(i
->uid
), first
);
395 LIST_REMOVE(items
, first
, i
);
400 } else if (policy_category
== POLICY_CATEGORY_GROUP
) {
401 const char *g
= policy_group
;
403 assert_cc(sizeof(gid_t
) == sizeof(uint32_t));
405 r
= hashmap_ensure_allocated(&p
->group_items
, NULL
);
410 log_error("Group policy without name");
414 r
= get_group_creds(&g
, &i
->gid
);
416 log_error_errno(r
, "Failed to resolve group %s, ignoring policy: %m", g
);
421 first
= hashmap_get(p
->group_items
, UINT32_TO_PTR(i
->gid
));
422 item_append(i
, &first
);
425 r
= hashmap_replace(p
->group_items
, UINT32_TO_PTR(i
->gid
), first
);
427 LIST_REMOVE(items
, first
, i
);
433 state
= STATE_POLICY
;
436 } else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
437 log_error("Unexpected token (8) at %s:%u.", path
, line
);
443 case STATE_ALLOW_DENY_INTERFACE
:
445 if (t
== XML_ATTRIBUTE_VALUE
) {
448 log_error("Duplicate interface at %s:%u.", path
, line
);
452 if (!streq(name
, "*")) {
456 state
= STATE_ALLOW_DENY
;
458 log_error("Unexpected token (9) at %s:%u.", path
, line
);
464 case STATE_ALLOW_DENY_MEMBER
:
466 if (t
== XML_ATTRIBUTE_VALUE
) {
469 log_error("Duplicate member in %s:%u.", path
, line
);
473 if (!streq(name
, "*")) {
477 state
= STATE_ALLOW_DENY
;
479 log_error("Unexpected token (10) in %s:%u.", path
, line
);
485 case STATE_ALLOW_DENY_ERROR
:
487 if (t
== XML_ATTRIBUTE_VALUE
) {
490 log_error("Duplicate error in %s:%u.", path
, line
);
494 if (!streq(name
, "*")) {
498 state
= STATE_ALLOW_DENY
;
500 log_error("Unexpected token (11) in %s:%u.", path
, line
);
506 case STATE_ALLOW_DENY_PATH
:
508 if (t
== XML_ATTRIBUTE_VALUE
) {
511 log_error("Duplicate path in %s:%u.", path
, line
);
515 if (!streq(name
, "*")) {
519 state
= STATE_ALLOW_DENY
;
521 log_error("Unexpected token (12) in %s:%u.", path
, line
);
527 case STATE_ALLOW_DENY_MESSAGE_TYPE
:
529 if (t
== XML_ATTRIBUTE_VALUE
) {
532 if (i
->message_type
!= 0) {
533 log_error("Duplicate message type in %s:%u.", path
, line
);
537 if (!streq(name
, "*")) {
538 r
= bus_message_type_from_string(name
, &i
->message_type
);
540 log_error("Invalid message type in %s:%u.", path
, line
);
545 state
= STATE_ALLOW_DENY
;
547 log_error("Unexpected token (13) in %s:%u.", path
, line
);
553 case STATE_ALLOW_DENY_NAME
:
555 if (t
== XML_ATTRIBUTE_VALUE
) {
558 log_error("Duplicate name in %s:%u.", path
, line
);
563 case POLICY_ITEM_USER
:
564 if (!streq(name
, "*")) {
565 const char *u
= name
;
567 r
= get_user_creds(&u
, &i
->uid
, NULL
, NULL
, NULL
);
569 log_error_errno(r
, "Failed to resolve user %s: %m", name
);
574 case POLICY_ITEM_GROUP
:
575 if (!streq(name
, "*")) {
576 const char *g
= name
;
578 r
= get_group_creds(&g
, &i
->gid
);
580 log_error_errno(r
, "Failed to resolve group %s: %m", name
);
586 case POLICY_ITEM_SEND
:
587 case POLICY_ITEM_RECV
:
589 if (streq(name
, "*")) {
603 state
= STATE_ALLOW_DENY
;
605 log_error("Unexpected token (14) in %s:%u.", path
, line
);
611 case STATE_ALLOW_DENY_OTHER_ATTRIBUTE
:
613 if (t
== XML_ATTRIBUTE_VALUE
)
614 state
= STATE_ALLOW_DENY
;
616 log_error("Unexpected token (15) in %s:%u.", path
, line
);
624 if (t
== XML_TAG_OPEN
)
626 else if (t
== XML_TAG_CLOSE
|| t
== XML_TAG_CLOSE_EMPTY
) {
629 state
= STATE_BUSCONFIG
;
645 static const char *verdict_to_string(int v
) {
659 struct policy_check_filter
{
660 PolicyItemClass
class;
665 const char *interface
;
670 static int is_permissive(PolicyItem
*i
) {
674 return (i
->type
== POLICY_ITEM_ALLOW
) ? ALLOW
: DENY
;
677 static int check_policy_item(PolicyItem
*i
, const struct policy_check_filter
*filter
) {
683 case POLICY_ITEM_SEND
:
684 case POLICY_ITEM_RECV
:
686 if (i
->name
&& !streq_ptr(i
->name
, filter
->name
))
689 if ((i
->message_type
!= 0) && (i
->message_type
!= filter
->message_type
))
692 if (i
->path
&& !streq_ptr(i
->path
, filter
->path
))
695 if (i
->member
&& !streq_ptr(i
->member
, filter
->member
))
698 if (i
->interface
&& !streq_ptr(i
->interface
, filter
->interface
))
701 return is_permissive(i
);
703 case POLICY_ITEM_OWN
:
704 assert(filter
->name
);
706 if (streq(i
->name
, "*") || streq(i
->name
, filter
->name
))
707 return is_permissive(i
);
710 case POLICY_ITEM_OWN_PREFIX
:
711 assert(filter
->name
);
713 if (streq(i
->name
, "*") || service_name_startswith(filter
->name
, i
->name
))
714 return is_permissive(i
);
717 case POLICY_ITEM_USER
:
718 if (filter
->uid
!= UID_INVALID
)
719 if ((streq_ptr(i
->name
, "*") || (i
->uid_valid
&& i
->uid
== filter
->uid
)))
720 return is_permissive(i
);
723 case POLICY_ITEM_GROUP
:
724 if (filter
->gid
!= GID_INVALID
)
725 if ((streq_ptr(i
->name
, "*") || (i
->gid_valid
&& i
->gid
== filter
->gid
)))
726 return is_permissive(i
);
729 case POLICY_ITEM_IGNORE
:
737 static int check_policy_items(PolicyItem
*items
, const struct policy_check_filter
*filter
) {
744 /* Check all policies in a set - a broader one might be followed by a more specific one,
745 * and the order of rules in policy definitions matters */
746 LIST_FOREACH(items
, i
, items
) {
749 if (i
->class != filter
->class &&
750 !(i
->class == POLICY_ITEM_OWN_PREFIX
&& filter
->class == POLICY_ITEM_OWN
))
753 v
= check_policy_item(i
, filter
);
761 static int policy_check(Policy
*p
, const struct policy_check_filter
*filter
) {
769 assert(IN_SET(filter
->class, POLICY_ITEM_SEND
, POLICY_ITEM_RECV
, POLICY_ITEM_OWN
, POLICY_ITEM_USER
, POLICY_ITEM_GROUP
));
772 * The policy check is implemented by the following logic:
774 * 1. Check default items
775 * 2. Check group items
776 * 3. Check user items
777 * 4. Check on/no_console items
778 * 5. Check mandatory items
780 * Later rules override earlier rules.
783 verdict
= check_policy_items(p
->default_items
, filter
);
785 if (filter
->gid
!= GID_INVALID
) {
786 items
= hashmap_get(p
->group_items
, UINT32_TO_PTR(filter
->gid
));
788 v
= check_policy_items(items
, filter
);
794 if (filter
->uid
!= UID_INVALID
) {
795 items
= hashmap_get(p
->user_items
, UINT32_TO_PTR(filter
->uid
));
797 v
= check_policy_items(items
, filter
);
803 if (filter
->uid
!= UID_INVALID
&& sd_uid_get_seats(filter
->uid
, -1, NULL
) > 0)
804 v
= check_policy_items(p
->on_console_items
, filter
);
806 v
= check_policy_items(p
->no_console_items
, filter
);
810 v
= check_policy_items(p
->mandatory_items
, filter
);
817 bool policy_check_own(Policy
*p
, uid_t uid
, gid_t gid
, const char *name
) {
819 struct policy_check_filter filter
= {
820 .class = POLICY_ITEM_OWN
,
831 verdict
= policy_check(p
, &filter
);
833 log_full(LOG_AUTH
| (verdict
!= ALLOW
? LOG_WARNING
: LOG_DEBUG
),
834 "Ownership permission check for uid=" UID_FMT
" gid=" GID_FMT
" name=%s: %s",
835 uid
, gid
, strna(name
), strna(verdict_to_string(verdict
)));
837 return verdict
== ALLOW
;
840 bool policy_check_hello(Policy
*p
, uid_t uid
, gid_t gid
) {
842 struct policy_check_filter filter
= {
850 filter
.class = POLICY_ITEM_USER
;
851 verdict
= policy_check(p
, &filter
);
853 if (verdict
!= DENY
) {
856 filter
.class = POLICY_ITEM_GROUP
;
857 v
= policy_check(p
, &filter
);
862 log_full(LOG_AUTH
| (verdict
!= ALLOW
? LOG_WARNING
: LOG_DEBUG
),
863 "Hello permission check for uid=" UID_FMT
" gid=" GID_FMT
": %s",
864 uid
, gid
, strna(verdict_to_string(verdict
)));
866 return verdict
== ALLOW
;
869 bool policy_check_one_recv(Policy
*p
,
875 const char *interface
,
876 const char *member
) {
878 struct policy_check_filter filter
= {
879 .class = POLICY_ITEM_RECV
,
882 .message_type
= message_type
,
884 .interface
= interface
,
891 return policy_check(p
, &filter
) == ALLOW
;
894 bool policy_check_recv(Policy
*p
,
901 const char *interface
,
903 bool dbus_to_kernel
) {
905 char *n
, **nv
, *last
= NULL
;
911 if (set_isempty(names
) && strv_isempty(namesv
)) {
912 allow
= policy_check_one_recv(p
, uid
, gid
, message_type
, NULL
, path
, interface
, member
);
914 SET_FOREACH(n
, names
, i
) {
916 allow
= policy_check_one_recv(p
, uid
, gid
, message_type
, n
, path
, interface
, member
);
921 STRV_FOREACH(nv
, namesv
) {
923 allow
= policy_check_one_recv(p
, uid
, gid
, message_type
, *nv
, path
, interface
, member
);
930 log_full(LOG_AUTH
| (!allow
? LOG_WARNING
: LOG_DEBUG
),
931 "Receive permission check %s for uid=" UID_FMT
" gid=" GID_FMT
" message=%s name=%s path=%s interface=%s member=%s: %s",
932 dbus_to_kernel
? "dbus-1 to kernel" : "kernel to dbus-1", uid
, gid
, bus_message_type_to_string(message_type
), strna(last
),
933 strna(path
), strna(interface
), strna(member
), allow
? "ALLOW" : "DENY");
938 bool policy_check_one_send(Policy
*p
,
944 const char *interface
,
945 const char *member
) {
947 struct policy_check_filter filter
= {
948 .class = POLICY_ITEM_SEND
,
951 .message_type
= message_type
,
953 .interface
= interface
,
960 return policy_check(p
, &filter
) == ALLOW
;
963 bool policy_check_send(Policy
*p
,
970 const char *interface
,
973 char **out_used_name
) {
975 char *n
, **nv
, *last
= NULL
;
981 if (set_isempty(names
) && strv_isempty(namesv
)) {
982 allow
= policy_check_one_send(p
, uid
, gid
, message_type
, NULL
, path
, interface
, member
);
984 SET_FOREACH(n
, names
, i
) {
986 allow
= policy_check_one_send(p
, uid
, gid
, message_type
, n
, path
, interface
, member
);
991 STRV_FOREACH(nv
, namesv
) {
993 allow
= policy_check_one_send(p
, uid
, gid
, message_type
, *nv
, path
, interface
, member
);
1001 *out_used_name
= last
;
1003 log_full(LOG_AUTH
| (!allow
? LOG_WARNING
: LOG_DEBUG
),
1004 "Send permission check %s for uid=" UID_FMT
" gid=" GID_FMT
" message=%s name=%s path=%s interface=%s member=%s: %s",
1005 dbus_to_kernel
? "dbus-1 to kernel" : "kernel to dbus-1", uid
, gid
, bus_message_type_to_string(message_type
), strna(last
),
1006 strna(path
), strna(interface
), strna(member
), allow
? "ALLOW" : "DENY");
1011 int policy_load(Policy
*p
, char **files
) {
1017 STRV_FOREACH(i
, files
) {
1019 r
= file_load(p
, *i
);
1021 _cleanup_strv_free_
char **l
= NULL
;
1024 r
= conf_files_list(&l
, ".conf", NULL
, *i
, NULL
);
1026 return log_error_errno(r
, "Failed to get configuration file list: %m");
1032 /* We ignore all errors but EISDIR, and just proceed. */
1038 void policy_free(Policy
*p
) {
1039 PolicyItem
*i
, *first
;
1044 while ((i
= p
->default_items
)) {
1045 LIST_REMOVE(items
, p
->default_items
, i
);
1046 policy_item_free(i
);
1049 while ((i
= p
->mandatory_items
)) {
1050 LIST_REMOVE(items
, p
->mandatory_items
, i
);
1051 policy_item_free(i
);
1054 while ((i
= p
->on_console_items
)) {
1055 LIST_REMOVE(items
, p
->on_console_items
, i
);
1056 policy_item_free(i
);
1059 while ((i
= p
->no_console_items
)) {
1060 LIST_REMOVE(items
, p
->no_console_items
, i
);
1061 policy_item_free(i
);
1064 while ((first
= hashmap_steal_first(p
->user_items
))) {
1066 while ((i
= first
)) {
1067 LIST_REMOVE(items
, first
, i
);
1068 policy_item_free(i
);
1072 while ((first
= hashmap_steal_first(p
->group_items
))) {
1074 while ((i
= first
)) {
1075 LIST_REMOVE(items
, first
, i
);
1076 policy_item_free(i
);
1080 hashmap_free(p
->user_items
);
1081 hashmap_free(p
->group_items
);
1083 p
->user_items
= p
->group_items
= NULL
;
1086 static void dump_items(PolicyItem
*items
, const char *prefix
) {
1096 LIST_FOREACH(items
, i
, items
) {
1098 printf("%sType: %s\n"
1100 prefix
, policy_item_type_to_string(i
->type
),
1101 prefix
, policy_item_class_to_string(i
->class));
1104 printf("%sInterface: %s\n",
1105 prefix
, i
->interface
);
1108 printf("%sMember: %s\n",
1112 printf("%sError: %s\n",
1116 printf("%sPath: %s\n",
1120 printf("%sName: %s\n",
1123 if (i
->message_type
!= 0)
1124 printf("%sMessage Type: %s\n",
1125 prefix
, bus_message_type_to_string(i
->message_type
));
1128 _cleanup_free_
char *user
;
1130 user
= uid_to_name(i
->uid
);
1132 printf("%sUser: %s ("UID_FMT
")\n",
1133 prefix
, strna(user
), i
->uid
);
1137 _cleanup_free_
char *group
;
1139 group
= gid_to_name(i
->gid
);
1141 printf("%sGroup: %s ("GID_FMT
")\n",
1142 prefix
, strna(group
), i
->gid
);
1144 printf("%s-\n", prefix
);
1148 static void dump_hashmap_items(Hashmap
*h
) {
1153 HASHMAP_FOREACH_KEY(i
, k
, h
, j
) {
1154 printf("\t%s Item for %u:\n", draw_special_char(DRAW_ARROW
), PTR_TO_UINT(k
));
1155 dump_items(i
, "\t\t");
1159 void policy_dump(Policy
*p
) {
1161 printf("%s Default Items:\n", draw_special_char(DRAW_ARROW
));
1162 dump_items(p
->default_items
, "\t");
1164 printf("%s Group Items:\n", draw_special_char(DRAW_ARROW
));
1165 dump_hashmap_items(p
->group_items
);
1167 printf("%s User Items:\n", draw_special_char(DRAW_ARROW
));
1168 dump_hashmap_items(p
->user_items
);
1170 printf("%s On-Console Items:\n", draw_special_char(DRAW_ARROW
));
1171 dump_items(p
->on_console_items
, "\t");
1173 printf("%s No-Console Items:\n", draw_special_char(DRAW_ARROW
));
1174 dump_items(p
->no_console_items
, "\t");
1176 printf("%s Mandatory Items:\n", draw_special_char(DRAW_ARROW
));
1177 dump_items(p
->mandatory_items
, "\t");
1182 int shared_policy_new(SharedPolicy
**out
) {
1186 sp
= new0(SharedPolicy
, 1);
1190 r
= pthread_mutex_init(&sp
->lock
, NULL
);
1192 log_error_errno(r
, "Cannot initialize shared policy mutex: %m");
1196 r
= pthread_rwlock_init(&sp
->rwlock
, NULL
);
1198 log_error_errno(r
, "Cannot initialize shared policy rwlock: %m");
1206 /* pthread lock destruction is not fail-safe... meh! */
1208 pthread_mutex_destroy(&sp
->lock
);
1214 SharedPolicy
*shared_policy_free(SharedPolicy
*sp
) {
1218 policy_free(sp
->policy
);
1219 pthread_rwlock_destroy(&sp
->rwlock
);
1220 pthread_mutex_destroy(&sp
->lock
);
1221 strv_free(sp
->configuration
);
1227 static int shared_policy_reload_unlocked(SharedPolicy
*sp
, char **configuration
) {
1228 Policy old
, buffer
= {};
1234 r
= policy_load(&buffer
, configuration
);
1236 return log_error_errno(r
, "Failed to load policy: %m");
1238 log_debug("Reloading configuration");
1239 /* policy_dump(&buffer); */
1241 pthread_rwlock_wrlock(&sp
->rwlock
);
1242 memcpy(&old
, &sp
->buffer
, sizeof(old
));
1243 memcpy(&sp
->buffer
, &buffer
, sizeof(buffer
));
1244 free_old
= !!sp
->policy
;
1245 sp
->policy
= &sp
->buffer
;
1246 pthread_rwlock_unlock(&sp
->rwlock
);
1254 int shared_policy_reload(SharedPolicy
*sp
) {
1259 pthread_mutex_lock(&sp
->lock
);
1260 r
= shared_policy_reload_unlocked(sp
, sp
->configuration
);
1261 pthread_mutex_unlock(&sp
->lock
);
1266 int shared_policy_preload(SharedPolicy
*sp
, char **configuration
) {
1267 _cleanup_strv_free_
char **conf
= NULL
;
1272 conf
= strv_copy(configuration
);
1276 pthread_mutex_lock(&sp
->lock
);
1278 r
= shared_policy_reload_unlocked(sp
, conf
);
1280 sp
->configuration
= conf
;
1284 pthread_mutex_unlock(&sp
->lock
);
1289 Policy
*shared_policy_acquire(SharedPolicy
*sp
) {
1292 pthread_rwlock_rdlock(&sp
->rwlock
);
1295 pthread_rwlock_unlock(&sp
->rwlock
);
1300 void shared_policy_release(SharedPolicy
*sp
, Policy
*p
) {
1302 assert(!p
|| sp
->policy
== p
);
1305 pthread_rwlock_unlock(&sp
->rwlock
);
1308 static const char* const policy_item_type_table
[_POLICY_ITEM_TYPE_MAX
] = {
1309 [_POLICY_ITEM_TYPE_UNSET
] = "unset",
1310 [POLICY_ITEM_ALLOW
] = "allow",
1311 [POLICY_ITEM_DENY
] = "deny",
1313 DEFINE_STRING_TABLE_LOOKUP(policy_item_type
, PolicyItemType
);
1315 static const char* const policy_item_class_table
[_POLICY_ITEM_CLASS_MAX
] = {
1316 [_POLICY_ITEM_CLASS_UNSET
] = "unset",
1317 [POLICY_ITEM_SEND
] = "send",
1318 [POLICY_ITEM_RECV
] = "recv",
1319 [POLICY_ITEM_OWN
] = "own",
1320 [POLICY_ITEM_OWN_PREFIX
] = "own-prefix",
1321 [POLICY_ITEM_USER
] = "user",
1322 [POLICY_ITEM_GROUP
] = "group",
1323 [POLICY_ITEM_IGNORE
] = "ignore",
1325 DEFINE_STRING_TABLE_LOOKUP(policy_item_class
, PolicyItemClass
);