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 "conf-files.h"
27 #include "formats-util.h"
29 #include "string-util.h"
32 #include "bus-xml-policy.h"
34 static void policy_item_free(PolicyItem
*i
) {
45 DEFINE_TRIVIAL_CLEANUP_FUNC(PolicyItem
*, policy_item_free
);
47 static void item_append(PolicyItem
*i
, PolicyItem
**list
) {
51 LIST_FIND_TAIL(items
, *list
, tail
);
52 LIST_INSERT_AFTER(items
, *list
, tail
, i
);
55 static int file_load(Policy
*p
, const char *path
) {
57 _cleanup_free_
char *c
= NULL
, *policy_user
= NULL
, *policy_group
= NULL
;
58 _cleanup_(policy_item_freep
) PolicyItem
*i
= NULL
;
59 void *xml_state
= NULL
;
72 STATE_POLICY_OTHER_ATTRIBUTE
,
74 STATE_ALLOW_DENY_INTERFACE
,
75 STATE_ALLOW_DENY_MEMBER
,
76 STATE_ALLOW_DENY_ERROR
,
77 STATE_ALLOW_DENY_PATH
,
78 STATE_ALLOW_DENY_MESSAGE_TYPE
,
79 STATE_ALLOW_DENY_NAME
,
80 STATE_ALLOW_DENY_OTHER_ATTRIBUTE
,
82 } state
= STATE_OUTSIDE
;
86 POLICY_CATEGORY_DEFAULT
,
87 POLICY_CATEGORY_MANDATORY
,
88 POLICY_CATEGORY_ON_CONSOLE
,
89 POLICY_CATEGORY_NO_CONSOLE
,
92 } policy_category
= POLICY_CATEGORY_NONE
;
98 r
= read_full_file(path
, &c
, NULL
);
105 return log_error_errno(r
, "Failed to load %s: %m", path
);
110 _cleanup_free_
char *name
= NULL
;
113 t
= xml_tokenize(&q
, &name
, &xml_state
, &line
);
115 return log_error_errno(t
, "XML parse failure in %s: %m", path
);
121 if (t
== XML_TAG_OPEN
) {
122 if (streq(name
, "busconfig"))
123 state
= STATE_BUSCONFIG
;
125 log_error("Unexpected tag %s at %s:%u.", name
, path
, line
);
129 } else if (t
== XML_END
)
131 else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
132 log_error("Unexpected token (1) at %s:%u.", path
, line
);
138 case STATE_BUSCONFIG
:
140 if (t
== XML_TAG_OPEN
) {
141 if (streq(name
, "policy")) {
142 state
= STATE_POLICY
;
143 policy_category
= POLICY_CATEGORY_NONE
;
146 policy_user
= policy_group
= NULL
;
151 } else if (t
== XML_TAG_CLOSE_EMPTY
||
152 (t
== XML_TAG_CLOSE
&& streq(name
, "busconfig")))
153 state
= STATE_OUTSIDE
;
154 else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
155 log_error("Unexpected token (2) at %s:%u.", path
, line
);
163 if (t
== XML_ATTRIBUTE_NAME
) {
164 if (streq(name
, "context"))
165 state
= STATE_POLICY_CONTEXT
;
166 else if (streq(name
, "at_console"))
167 state
= STATE_POLICY_CONSOLE
;
168 else if (streq(name
, "user"))
169 state
= STATE_POLICY_USER
;
170 else if (streq(name
, "group"))
171 state
= STATE_POLICY_GROUP
;
173 log_warning("Attribute %s of <policy> tag unknown at %s:%u, ignoring.", name
, path
, line
);
174 state
= STATE_POLICY_OTHER_ATTRIBUTE
;
176 } else if (t
== XML_TAG_CLOSE_EMPTY
||
177 (t
== XML_TAG_CLOSE
&& streq(name
, "policy")))
178 state
= STATE_BUSCONFIG
;
179 else if (t
== XML_TAG_OPEN
) {
182 if (streq(name
, "allow"))
183 it
= POLICY_ITEM_ALLOW
;
184 else if (streq(name
, "deny"))
185 it
= POLICY_ITEM_DENY
;
187 log_warning("Unknown tag %s in <policy> %s:%u.", name
, path
, line
);
192 i
= new0(PolicyItem
, 1);
197 state
= STATE_ALLOW_DENY
;
199 } else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
200 log_error("Unexpected token (3) at %s:%u.", path
, line
);
206 case STATE_POLICY_CONTEXT
:
208 if (t
== XML_ATTRIBUTE_VALUE
) {
209 if (streq(name
, "default")) {
210 policy_category
= POLICY_CATEGORY_DEFAULT
;
211 state
= STATE_POLICY
;
212 } else if (streq(name
, "mandatory")) {
213 policy_category
= POLICY_CATEGORY_MANDATORY
;
214 state
= STATE_POLICY
;
216 log_error("context= parameter %s unknown for <policy> at %s:%u.", name
, path
, line
);
220 log_error("Unexpected token (4) at %s:%u.", path
, line
);
226 case STATE_POLICY_CONSOLE
:
228 if (t
== XML_ATTRIBUTE_VALUE
) {
229 if (streq(name
, "true")) {
230 policy_category
= POLICY_CATEGORY_ON_CONSOLE
;
231 state
= STATE_POLICY
;
232 } else if (streq(name
, "false")) {
233 policy_category
= POLICY_CATEGORY_NO_CONSOLE
;
234 state
= STATE_POLICY
;
236 log_error("at_console= parameter %s unknown for <policy> at %s:%u.", name
, path
, line
);
240 log_error("Unexpected token (4.1) at %s:%u.", path
, line
);
246 case STATE_POLICY_USER
:
248 if (t
== XML_ATTRIBUTE_VALUE
) {
252 policy_category
= POLICY_CATEGORY_USER
;
253 state
= STATE_POLICY
;
255 log_error("Unexpected token (5) in %s:%u.", path
, line
);
261 case STATE_POLICY_GROUP
:
263 if (t
== XML_ATTRIBUTE_VALUE
) {
267 policy_category
= POLICY_CATEGORY_GROUP
;
268 state
= STATE_POLICY
;
270 log_error("Unexpected token (6) at %s:%u.", path
, line
);
276 case STATE_POLICY_OTHER_ATTRIBUTE
:
278 if (t
== XML_ATTRIBUTE_VALUE
)
279 state
= STATE_POLICY
;
281 log_error("Unexpected token (7) in %s:%u.", path
, line
);
287 case STATE_ALLOW_DENY
:
291 if (t
== XML_ATTRIBUTE_NAME
) {
294 if (startswith(name
, "send_"))
295 ic
= POLICY_ITEM_SEND
;
296 else if (startswith(name
, "receive_"))
297 ic
= POLICY_ITEM_RECV
;
298 else if (streq(name
, "own"))
299 ic
= POLICY_ITEM_OWN
;
300 else if (streq(name
, "own_prefix"))
301 ic
= POLICY_ITEM_OWN_PREFIX
;
302 else if (streq(name
, "user"))
303 ic
= POLICY_ITEM_USER
;
304 else if (streq(name
, "group"))
305 ic
= POLICY_ITEM_GROUP
;
306 else if (STR_IN_SET(name
, "eavesdrop", "log")) {
307 log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name
, path
, line
);
308 state
= STATE_ALLOW_DENY_OTHER_ATTRIBUTE
;
311 log_error("Unknown attribute %s= at %s:%u, ignoring.", name
, path
, line
);
312 state
= STATE_ALLOW_DENY_OTHER_ATTRIBUTE
;
316 if (i
->class != _POLICY_ITEM_CLASS_UNSET
&& ic
!= i
->class) {
317 log_error("send_, receive_/eavesdrop fields mixed on same tag at %s:%u.", path
, line
);
323 if (ic
== POLICY_ITEM_SEND
|| ic
== POLICY_ITEM_RECV
) {
326 u
= strchr(name
, '_');
331 if (streq(u
, "interface"))
332 state
= STATE_ALLOW_DENY_INTERFACE
;
333 else if (streq(u
, "member"))
334 state
= STATE_ALLOW_DENY_MEMBER
;
335 else if (streq(u
, "error"))
336 state
= STATE_ALLOW_DENY_ERROR
;
337 else if (streq(u
, "path"))
338 state
= STATE_ALLOW_DENY_PATH
;
339 else if (streq(u
, "type"))
340 state
= STATE_ALLOW_DENY_MESSAGE_TYPE
;
341 else if ((streq(u
, "destination") && ic
== POLICY_ITEM_SEND
) ||
342 (streq(u
, "sender") && ic
== POLICY_ITEM_RECV
))
343 state
= STATE_ALLOW_DENY_NAME
;
345 if (streq(u
, "requested_reply"))
346 log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name
, path
, line
);
348 log_error("Unknown attribute %s= at %s:%u, ignoring.", name
, path
, line
);
349 state
= STATE_ALLOW_DENY_OTHER_ATTRIBUTE
;
353 state
= STATE_ALLOW_DENY_NAME
;
355 } else if (t
== XML_TAG_CLOSE_EMPTY
||
356 (t
== XML_TAG_CLOSE
&& streq(name
, i
->type
== POLICY_ITEM_ALLOW
? "allow" : "deny"))) {
358 /* If the tag is fully empty so far, we consider it a recv */
359 if (i
->class == _POLICY_ITEM_CLASS_UNSET
)
360 i
->class = POLICY_ITEM_RECV
;
362 if (policy_category
== POLICY_CATEGORY_DEFAULT
)
363 item_append(i
, &p
->default_items
);
364 else if (policy_category
== POLICY_CATEGORY_MANDATORY
)
365 item_append(i
, &p
->mandatory_items
);
366 else if (policy_category
== POLICY_CATEGORY_ON_CONSOLE
)
367 item_append(i
, &p
->on_console_items
);
368 else if (policy_category
== POLICY_CATEGORY_NO_CONSOLE
)
369 item_append(i
, &p
->no_console_items
);
370 else if (policy_category
== POLICY_CATEGORY_USER
) {
371 const char *u
= policy_user
;
373 assert_cc(sizeof(uid_t
) == sizeof(uint32_t));
375 r
= hashmap_ensure_allocated(&p
->user_items
, NULL
);
380 log_error("User policy without name");
384 r
= get_user_creds(&u
, &i
->uid
, NULL
, NULL
, NULL
);
386 log_error_errno(r
, "Failed to resolve user %s, ignoring policy: %m", u
);
391 first
= hashmap_get(p
->user_items
, UINT32_TO_PTR(i
->uid
));
392 item_append(i
, &first
);
395 r
= hashmap_replace(p
->user_items
, UINT32_TO_PTR(i
->uid
), first
);
397 LIST_REMOVE(items
, first
, i
);
402 } else if (policy_category
== POLICY_CATEGORY_GROUP
) {
403 const char *g
= policy_group
;
405 assert_cc(sizeof(gid_t
) == sizeof(uint32_t));
407 r
= hashmap_ensure_allocated(&p
->group_items
, NULL
);
412 log_error("Group policy without name");
416 r
= get_group_creds(&g
, &i
->gid
);
418 log_error_errno(r
, "Failed to resolve group %s, ignoring policy: %m", g
);
423 first
= hashmap_get(p
->group_items
, UINT32_TO_PTR(i
->gid
));
424 item_append(i
, &first
);
427 r
= hashmap_replace(p
->group_items
, UINT32_TO_PTR(i
->gid
), first
);
429 LIST_REMOVE(items
, first
, i
);
435 state
= STATE_POLICY
;
438 } else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
439 log_error("Unexpected token (8) at %s:%u.", path
, line
);
445 case STATE_ALLOW_DENY_INTERFACE
:
447 if (t
== XML_ATTRIBUTE_VALUE
) {
450 log_error("Duplicate interface at %s:%u.", path
, line
);
454 if (!streq(name
, "*")) {
458 state
= STATE_ALLOW_DENY
;
460 log_error("Unexpected token (9) at %s:%u.", path
, line
);
466 case STATE_ALLOW_DENY_MEMBER
:
468 if (t
== XML_ATTRIBUTE_VALUE
) {
471 log_error("Duplicate member in %s:%u.", path
, line
);
475 if (!streq(name
, "*")) {
479 state
= STATE_ALLOW_DENY
;
481 log_error("Unexpected token (10) in %s:%u.", path
, line
);
487 case STATE_ALLOW_DENY_ERROR
:
489 if (t
== XML_ATTRIBUTE_VALUE
) {
492 log_error("Duplicate error in %s:%u.", path
, line
);
496 if (!streq(name
, "*")) {
500 state
= STATE_ALLOW_DENY
;
502 log_error("Unexpected token (11) in %s:%u.", path
, line
);
508 case STATE_ALLOW_DENY_PATH
:
510 if (t
== XML_ATTRIBUTE_VALUE
) {
513 log_error("Duplicate path in %s:%u.", path
, line
);
517 if (!streq(name
, "*")) {
521 state
= STATE_ALLOW_DENY
;
523 log_error("Unexpected token (12) in %s:%u.", path
, line
);
529 case STATE_ALLOW_DENY_MESSAGE_TYPE
:
531 if (t
== XML_ATTRIBUTE_VALUE
) {
534 if (i
->message_type
!= 0) {
535 log_error("Duplicate message type in %s:%u.", path
, line
);
539 if (!streq(name
, "*")) {
540 r
= bus_message_type_from_string(name
, &i
->message_type
);
542 log_error("Invalid message type in %s:%u.", path
, line
);
547 state
= STATE_ALLOW_DENY
;
549 log_error("Unexpected token (13) in %s:%u.", path
, line
);
555 case STATE_ALLOW_DENY_NAME
:
557 if (t
== XML_ATTRIBUTE_VALUE
) {
560 log_error("Duplicate name in %s:%u.", path
, line
);
565 case POLICY_ITEM_USER
:
566 if (!streq(name
, "*")) {
567 const char *u
= name
;
569 r
= get_user_creds(&u
, &i
->uid
, NULL
, NULL
, NULL
);
571 log_error_errno(r
, "Failed to resolve user %s: %m", name
);
576 case POLICY_ITEM_GROUP
:
577 if (!streq(name
, "*")) {
578 const char *g
= name
;
580 r
= get_group_creds(&g
, &i
->gid
);
582 log_error_errno(r
, "Failed to resolve group %s: %m", name
);
588 case POLICY_ITEM_SEND
:
589 case POLICY_ITEM_RECV
:
591 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 r
= log_error_errno(r
, "Cannot initialize shared policy mutex: %m");
1196 r
= pthread_rwlock_init(&sp
->rwlock
, NULL
);
1198 r
= 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
);