From 3c70e3bb022f0de3317f3600c9366a2f4597339e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 23 Dec 2014 18:36:04 +0100 Subject: core: rearrange code so that libsystemd/sd-bus/ does not include header files from core Stuff in src/shared or src/libsystemd should *never* include code from src/core or any of the tools, so don't do that here either. It's not OK! --- Makefile.am | 18 +- src/bus-proxyd/bus-policy.c | 1050 ---------------------------------- src/bus-proxyd/bus-policy.h | 104 ---- src/bus-proxyd/bus-proxyd.c | 3 +- src/bus-proxyd/bus-xml-policy.c | 1050 ++++++++++++++++++++++++++++++++++ src/bus-proxyd/bus-xml-policy.h | 104 ++++ src/bus-proxyd/test-bus-policy.c | 160 ------ src/bus-proxyd/test-bus-xml-policy.c | 158 +++++ src/core/bus-common.c | 35 -- src/core/bus-common.h | 35 -- src/core/bus-endpoint.c | 56 +- src/core/bus-endpoint.h | 4 +- src/core/busname.c | 3 +- src/core/busname.h | 17 - src/core/execute.c | 2 +- src/libsystemd/sd-bus/bus-internal.h | 1 + src/libsystemd/sd-bus/bus-kernel.c | 185 ------ src/libsystemd/sd-bus/bus-kernel.h | 5 - src/libsystemd/sd-bus/busctl.c | 1 + src/test/test-tables.c | 3 +- 20 files changed, 1383 insertions(+), 1611 deletions(-) delete mode 100644 src/bus-proxyd/bus-policy.c delete mode 100644 src/bus-proxyd/bus-policy.h create mode 100644 src/bus-proxyd/bus-xml-policy.c create mode 100644 src/bus-proxyd/bus-xml-policy.h delete mode 100644 src/bus-proxyd/test-bus-policy.c create mode 100644 src/bus-proxyd/test-bus-xml-policy.c delete mode 100644 src/core/bus-common.c delete mode 100644 src/core/bus-common.h diff --git a/Makefile.am b/Makefile.am index 904517ffa6..96c9fc44f2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1046,10 +1046,10 @@ libsystemd_core_la_SOURCES = \ src/core/socket.h \ src/core/busname.c \ src/core/busname.h \ - src/core/bus-common.c \ - src/core/bus-common.h \ src/core/bus-endpoint.c \ src/core/bus-endpoint.h \ + src/core/bus-policy.c \ + src/core/bus-policy.h \ src/core/target.c \ src/core/target.h \ src/core/snapshot.c \ @@ -1713,8 +1713,8 @@ test_unaligned_SOURCES = \ test_tables_SOURCES = \ src/test/test-tables.c \ src/shared/test-tables.h \ - src/bus-proxyd/bus-policy.c \ - src/bus-proxyd/bus-policy.h \ + src/bus-proxyd/bus-xml-policy.c \ + src/bus-proxyd/bus-xml-policy.h \ src/journal/journald-server.c \ src/journal/journald-server.h @@ -1948,9 +1948,9 @@ test_conf_files_LDADD = \ libsystemd-shared.la test_bus_policy_SOURCES = \ - src/bus-proxyd/test-bus-policy.c \ - src/bus-proxyd/bus-policy.c \ - src/bus-proxyd/bus-policy.h + src/bus-proxyd/test-bus-xml-policy.c \ + src/bus-proxyd/bus-xml-policy.c \ + src/bus-proxyd/bus-xml-policy.h test_bus_policy_LDADD = \ libsystemd-internal.la \ @@ -2598,8 +2598,8 @@ systemd_run_LDADD = \ # ------------------------------------------------------------------------------ systemd_bus_proxyd_SOURCES = \ src/bus-proxyd/bus-proxyd.c \ - src/bus-proxyd/bus-policy.c \ - src/bus-proxyd/bus-policy.h + src/bus-proxyd/bus-xml-policy.c \ + src/bus-proxyd/bus-xml-policy.h systemd_bus_proxyd_LDADD = \ libsystemd-internal.la \ diff --git a/src/bus-proxyd/bus-policy.c b/src/bus-proxyd/bus-policy.c deleted file mode 100644 index 59cc1d788b..0000000000 --- a/src/bus-proxyd/bus-policy.c +++ /dev/null @@ -1,1050 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include "xml.h" -#include "fileio.h" -#include "strv.h" -#include "conf-files.h" -#include "bus-internal.h" -#include "bus-message.h" -#include "bus-policy.h" - -static void policy_item_free(PolicyItem *i) { - assert(i); - - free(i->interface); - free(i->member); - free(i->error); - free(i->name); - free(i->path); - free(i); -} - -DEFINE_TRIVIAL_CLEANUP_FUNC(PolicyItem*, policy_item_free); - -static void item_append(PolicyItem *i, PolicyItem **list) { - - PolicyItem *tail; - - LIST_FIND_TAIL(items, *list, tail); - LIST_INSERT_AFTER(items, *list, tail, i); -} - -static int file_load(Policy *p, const char *path) { - - _cleanup_free_ char *c = NULL, *policy_user = NULL, *policy_group = NULL; - _cleanup_(policy_item_freep) PolicyItem *i = NULL; - void *xml_state = NULL; - unsigned n_other = 0; - const char *q; - int r; - - enum { - STATE_OUTSIDE, - STATE_BUSCONFIG, - STATE_POLICY, - STATE_POLICY_CONTEXT, - STATE_POLICY_USER, - STATE_POLICY_GROUP, - STATE_POLICY_OTHER_ATTRIBUTE, - STATE_ALLOW_DENY, - STATE_ALLOW_DENY_INTERFACE, - STATE_ALLOW_DENY_MEMBER, - STATE_ALLOW_DENY_ERROR, - STATE_ALLOW_DENY_PATH, - STATE_ALLOW_DENY_MESSAGE_TYPE, - STATE_ALLOW_DENY_NAME, - STATE_ALLOW_DENY_OTHER_ATTRIBUTE, - STATE_OTHER, - } state = STATE_OUTSIDE; - - enum { - POLICY_CATEGORY_NONE, - POLICY_CATEGORY_DEFAULT, - POLICY_CATEGORY_MANDATORY, - POLICY_CATEGORY_USER, - POLICY_CATEGORY_GROUP - } policy_category = POLICY_CATEGORY_NONE; - - unsigned line = 0; - - assert(p); - - r = read_full_file(path, &c, NULL); - if (r < 0) { - if (r == -ENOENT) - return 0; - if (r == -EISDIR) - return r; - - return log_error_errno(r, "Failed to load %s: %m", path); - } - - q = c; - for (;;) { - _cleanup_free_ char *name = NULL; - int t; - - t = xml_tokenize(&q, &name, &xml_state, &line); - if (t < 0) - return log_error_errno(t, "XML parse failure in %s: %m", path); - - switch (state) { - - case STATE_OUTSIDE: - - if (t == XML_TAG_OPEN) { - if (streq(name, "busconfig")) - state = STATE_BUSCONFIG; - else { - log_error("Unexpected tag %s at %s:%u.", name, path, line); - return -EINVAL; - } - - } else if (t == XML_END) - return 0; - else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { - log_error("Unexpected token (1) at %s:%u.", path, line); - return -EINVAL; - } - - break; - - case STATE_BUSCONFIG: - - if (t == XML_TAG_OPEN) { - if (streq(name, "policy")) { - state = STATE_POLICY; - policy_category = POLICY_CATEGORY_NONE; - free(policy_user); - free(policy_group); - policy_user = policy_group = NULL; - } else { - state = STATE_OTHER; - n_other = 0; - } - } else if (t == XML_TAG_CLOSE_EMPTY || - (t == XML_TAG_CLOSE && streq(name, "busconfig"))) - state = STATE_OUTSIDE; - else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { - log_error("Unexpected token (2) at %s:%u.", path, line); - return -EINVAL; - } - - break; - - case STATE_POLICY: - - if (t == XML_ATTRIBUTE_NAME) { - if (streq(name, "context")) - state = STATE_POLICY_CONTEXT; - else if (streq(name, "user")) - state = STATE_POLICY_USER; - else if (streq(name, "group")) - state = STATE_POLICY_GROUP; - else { - if (streq(name, "at_console")) - log_debug("Attribute %s of tag unsupported at %s:%u, ignoring.", name, path, line); - else - log_warning("Attribute %s of tag unknown at %s:%u, ignoring.", name, path, line); - state = STATE_POLICY_OTHER_ATTRIBUTE; - } - } else if (t == XML_TAG_CLOSE_EMPTY || - (t == XML_TAG_CLOSE && streq(name, "policy"))) - state = STATE_BUSCONFIG; - else if (t == XML_TAG_OPEN) { - PolicyItemType it; - - if (streq(name, "allow")) - it = POLICY_ITEM_ALLOW; - else if (streq(name, "deny")) - it = POLICY_ITEM_DENY; - else { - log_warning("Unknown tag %s in %s:%u.", name, path, line); - return -EINVAL; - } - - assert(!i); - i = new0(PolicyItem, 1); - if (!i) - return log_oom(); - - i->type = it; - state = STATE_ALLOW_DENY; - - } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { - log_error("Unexpected token (3) at %s:%u.", path, line); - return -EINVAL; - } - - break; - - case STATE_POLICY_CONTEXT: - - if (t == XML_ATTRIBUTE_VALUE) { - if (streq(name, "default")) { - policy_category = POLICY_CATEGORY_DEFAULT; - state = STATE_POLICY; - } else if (streq(name, "mandatory")) { - policy_category = POLICY_CATEGORY_MANDATORY; - state = STATE_POLICY; - } else { - log_error("context= parameter %s unknown for at %s:%u.", name, path, line); - return -EINVAL; - } - } else { - log_error("Unexpected token (4) at %s:%u.", path, line); - return -EINVAL; - } - - break; - - case STATE_POLICY_USER: - - if (t == XML_ATTRIBUTE_VALUE) { - free(policy_user); - policy_user = name; - name = NULL; - policy_category = POLICY_CATEGORY_USER; - state = STATE_POLICY; - } else { - log_error("Unexpected token (5) in %s:%u.", path, line); - return -EINVAL; - } - - break; - - case STATE_POLICY_GROUP: - - if (t == XML_ATTRIBUTE_VALUE) { - free(policy_group); - policy_group = name; - name = NULL; - policy_category = POLICY_CATEGORY_GROUP; - state = STATE_POLICY; - } else { - log_error("Unexpected token (6) at %s:%u.", path, line); - return -EINVAL; - } - - break; - - case STATE_POLICY_OTHER_ATTRIBUTE: - - if (t == XML_ATTRIBUTE_VALUE) - state = STATE_POLICY; - else { - log_error("Unexpected token (7) in %s:%u.", path, line); - return -EINVAL; - } - - break; - - case STATE_ALLOW_DENY: - - assert(i); - - if (t == XML_ATTRIBUTE_NAME) { - PolicyItemClass ic; - - if (startswith(name, "send_")) - ic = POLICY_ITEM_SEND; - else if (startswith(name, "receive_")) - ic = POLICY_ITEM_RECV; - else if (streq(name, "own")) - ic = POLICY_ITEM_OWN; - else if (streq(name, "own_prefix")) - ic = POLICY_ITEM_OWN_PREFIX; - else if (streq(name, "user")) - ic = POLICY_ITEM_USER; - else if (streq(name, "group")) - ic = POLICY_ITEM_GROUP; - else if (streq(name, "eavesdrop")) { - log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name, path, line); - i->class = POLICY_ITEM_IGNORE; - state = STATE_ALLOW_DENY_OTHER_ATTRIBUTE; - break; - } else { - log_error("Unknown attribute %s= at %s:%u, ignoring.", name, path, line); - state = STATE_ALLOW_DENY_OTHER_ATTRIBUTE; - break; - } - - if (i->class != _POLICY_ITEM_CLASS_UNSET && ic != i->class) { - log_error("send_ and receive_ fields mixed on same tag at %s:%u.", path, line); - return -EINVAL; - } - - i->class = ic; - - if (ic == POLICY_ITEM_SEND || ic == POLICY_ITEM_RECV) { - const char *u; - - u = strchr(name, '_'); - assert(u); - - u++; - - if (streq(u, "interface")) - state = STATE_ALLOW_DENY_INTERFACE; - else if (streq(u, "member")) - state = STATE_ALLOW_DENY_MEMBER; - else if (streq(u, "error")) - state = STATE_ALLOW_DENY_ERROR; - else if (streq(u, "path")) - state = STATE_ALLOW_DENY_PATH; - else if (streq(u, "type")) - state = STATE_ALLOW_DENY_MESSAGE_TYPE; - else if ((streq(u, "destination") && ic == POLICY_ITEM_SEND) || - (streq(u, "sender") && ic == POLICY_ITEM_RECV)) - state = STATE_ALLOW_DENY_NAME; - else { - if (streq(u, "requested_reply")) - log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name, path, line); - else - log_error("Unknown attribute %s= at %s:%u, ignoring.", name, path, line); - state = STATE_ALLOW_DENY_OTHER_ATTRIBUTE; - break; - } - } else - state = STATE_ALLOW_DENY_NAME; - - } else if (t == XML_TAG_CLOSE_EMPTY || - (t == XML_TAG_CLOSE && streq(name, i->type == POLICY_ITEM_ALLOW ? "allow" : "deny"))) { - - if (i->class == _POLICY_ITEM_CLASS_UNSET) { - log_error("Policy not set at %s:%u.", path, line); - return -EINVAL; - } - - if (policy_category == POLICY_CATEGORY_DEFAULT) - item_append(i, &p->default_items); - else if (policy_category == POLICY_CATEGORY_MANDATORY) - item_append(i, &p->mandatory_items); - else if (policy_category == POLICY_CATEGORY_USER) { - const char *u = policy_user; - - assert_cc(sizeof(uid_t) == sizeof(uint32_t)); - - r = hashmap_ensure_allocated(&p->user_items, NULL); - if (r < 0) - return log_oom(); - - if (!u) { - log_error("User policy without name"); - return -EINVAL; - } - - r = get_user_creds(&u, &i->uid, NULL, NULL, NULL); - if (r < 0) { - log_error_errno(r, "Failed to resolve user %s, ignoring policy: %m", u); - free(i); - } else { - PolicyItem *first; - - first = hashmap_get(p->user_items, UINT32_TO_PTR(i->uid)); - item_append(i, &first); - i->uid_valid = true; - - r = hashmap_replace(p->user_items, UINT32_TO_PTR(i->uid), first); - if (r < 0) { - LIST_REMOVE(items, first, i); - return log_oom(); - } - } - - } else if (policy_category == POLICY_CATEGORY_GROUP) { - const char *g = policy_group; - - assert_cc(sizeof(gid_t) == sizeof(uint32_t)); - - r = hashmap_ensure_allocated(&p->group_items, NULL); - if (r < 0) - return log_oom(); - - if (!g) { - log_error("Group policy without name"); - return -EINVAL; - } - - r = get_group_creds(&g, &i->gid); - if (r < 0) { - log_error_errno(r, "Failed to resolve group %s, ignoring policy: %m", g); - free(i); - } else { - PolicyItem *first; - - first = hashmap_get(p->group_items, UINT32_TO_PTR(i->gid)); - item_append(i, &first); - i->gid_valid = true; - - r = hashmap_replace(p->group_items, UINT32_TO_PTR(i->gid), first); - if (r < 0) { - LIST_REMOVE(items, first, i); - return log_oom(); - } - } - } - - state = STATE_POLICY; - i = NULL; - - } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { - log_error("Unexpected token (8) at %s:%u.", path, line); - return -EINVAL; - } - - break; - - case STATE_ALLOW_DENY_INTERFACE: - - if (t == XML_ATTRIBUTE_VALUE) { - assert(i); - if (i->interface) { - log_error("Duplicate interface at %s:%u.", path, line); - return -EINVAL; - } - - i->interface = name; - name = NULL; - state = STATE_ALLOW_DENY; - } else { - log_error("Unexpected token (9) at %s:%u.", path, line); - return -EINVAL; - } - - break; - - case STATE_ALLOW_DENY_MEMBER: - - if (t == XML_ATTRIBUTE_VALUE) { - assert(i); - if (i->member) { - log_error("Duplicate member in %s:%u.", path, line); - return -EINVAL; - } - - i->member = name; - name = NULL; - state = STATE_ALLOW_DENY; - } else { - log_error("Unexpected token (10) in %s:%u.", path, line); - return -EINVAL; - } - - break; - - case STATE_ALLOW_DENY_ERROR: - - if (t == XML_ATTRIBUTE_VALUE) { - assert(i); - if (i->error) { - log_error("Duplicate error in %s:%u.", path, line); - return -EINVAL; - } - - i->error = name; - name = NULL; - state = STATE_ALLOW_DENY; - } else { - log_error("Unexpected token (11) in %s:%u.", path, line); - return -EINVAL; - } - - break; - - case STATE_ALLOW_DENY_PATH: - - if (t == XML_ATTRIBUTE_VALUE) { - assert(i); - if (i->path) { - log_error("Duplicate path in %s:%u.", path, line); - return -EINVAL; - } - - i->path = name; - name = NULL; - state = STATE_ALLOW_DENY; - } else { - log_error("Unexpected token (12) in %s:%u.", path, line); - return -EINVAL; - } - - break; - - case STATE_ALLOW_DENY_MESSAGE_TYPE: - - if (t == XML_ATTRIBUTE_VALUE) { - assert(i); - - if (i->message_type != 0) { - log_error("Duplicate message type in %s:%u.", path, line); - return -EINVAL; - } - - r = bus_message_type_from_string(name, &i->message_type); - if (r < 0) { - log_error("Invalid message type in %s:%u.", path, line); - return -EINVAL; - } - - state = STATE_ALLOW_DENY; - } else { - log_error("Unexpected token (13) in %s:%u.", path, line); - return -EINVAL; - } - - break; - - case STATE_ALLOW_DENY_NAME: - - if (t == XML_ATTRIBUTE_VALUE) { - assert(i); - if (i->name) { - log_error("Duplicate name in %s:%u.", path, line); - return -EINVAL; - } - - switch (i->class) { - case POLICY_ITEM_USER: - if (!streq(name, "*")) { - const char *u = name; - - r = get_user_creds(&u, &i->uid, NULL, NULL, NULL); - if (r < 0) - log_error_errno(r, "Failed to resolve user %s: %m", name); - else - i->uid_valid = true; - } - break; - case POLICY_ITEM_GROUP: - if (!streq(name, "*")) { - const char *g = name; - - r = get_group_creds(&g, &i->gid); - if (r < 0) - log_error_errno(r, "Failed to resolve group %s: %m", name); - else - i->gid_valid = true; - } - break; - default: - break; - } - - i->name = name; - name = NULL; - - state = STATE_ALLOW_DENY; - } else { - log_error("Unexpected token (14) in %s:%u.", path, line); - return -EINVAL; - } - - break; - - case STATE_ALLOW_DENY_OTHER_ATTRIBUTE: - - if (t == XML_ATTRIBUTE_VALUE) - state = STATE_ALLOW_DENY; - else { - log_error("Unexpected token (15) in %s:%u.", path, line); - return -EINVAL; - } - - break; - - case STATE_OTHER: - - if (t == XML_TAG_OPEN) - n_other++; - else if (t == XML_TAG_CLOSE || t == XML_TAG_CLOSE_EMPTY) { - - if (n_other == 0) - state = STATE_BUSCONFIG; - else - n_other--; - } - - break; - } - } -} - -enum { - DENY, - ALLOW, - DUNNO, -}; - -static const char *verdict_to_string(int v) { - switch (v) { - - case DENY: - return "DENY"; - case ALLOW: - return "ALLOW"; - case DUNNO: - return "DUNNO"; - } - - return NULL; -} - -struct policy_check_filter { - PolicyItemClass class; - uid_t uid; - gid_t gid; - int message_type; - const char *name; - const char *interface; - const char *path; - const char *member; -}; - -static int is_permissive(PolicyItem *i) { - - assert(i); - - return (i->type == POLICY_ITEM_ALLOW) ? ALLOW : DENY; -} - -static int check_policy_item(PolicyItem *i, const struct policy_check_filter *filter) { - - assert(i); - assert(filter); - - switch (i->class) { - case POLICY_ITEM_SEND: - case POLICY_ITEM_RECV: - - if (i->name && !streq_ptr(i->name, filter->name)) - break; - - if ((i->message_type != 0) && (i->message_type != filter->message_type)) - break; - - if (i->path && !streq_ptr(i->path, filter->path)) - break; - - if (i->member && !streq_ptr(i->member, filter->member)) - break; - - if (i->interface && !streq_ptr(i->interface, filter->interface)) - break; - - return is_permissive(i); - - case POLICY_ITEM_OWN: - assert(filter->name); - - if (streq(i->name, "*") || streq(i->name, filter->name)) - return is_permissive(i); - break; - - case POLICY_ITEM_OWN_PREFIX: - assert(filter->name); - - if (streq(i->name, "*") || service_name_startswith(filter->name, i->name)) - return is_permissive(i); - break; - - case POLICY_ITEM_USER: - if (filter->uid != UID_INVALID) - if ((streq_ptr(i->name, "*") || (i->uid_valid && i->uid == filter->uid))) - return is_permissive(i); - break; - - case POLICY_ITEM_GROUP: - if (filter->gid != GID_INVALID) - if ((streq_ptr(i->name, "*") || (i->gid_valid && i->gid == filter->gid))) - return is_permissive(i); - break; - - case POLICY_ITEM_IGNORE: - default: - break; - } - - return DUNNO; -} - -static int check_policy_items(PolicyItem *items, const struct policy_check_filter *filter) { - - PolicyItem *i; - int verdict = DUNNO; - - assert(filter); - - /* Check all policies in a set - a broader one might be followed by a more specific one, - * and the order of rules in policy definitions matters */ - LIST_FOREACH(items, i, items) { - int v; - - if (i->class != filter->class && - !(i->class == POLICY_ITEM_OWN_PREFIX && filter->class == POLICY_ITEM_OWN)) - continue; - - v = check_policy_item(i, filter); - if (v != DUNNO) - verdict = v; - } - - return verdict; -} - -static int policy_check(Policy *p, const struct policy_check_filter *filter) { - - PolicyItem *items; - int verdict, v; - - assert(p); - assert(filter); - - assert(IN_SET(filter->class, POLICY_ITEM_SEND, POLICY_ITEM_RECV, POLICY_ITEM_OWN, POLICY_ITEM_USER, POLICY_ITEM_GROUP)); - - /* - * The policy check is implemented by the following logic: - * - * 1. Check default items - * 2. Check group items - * 3. Check user items - * 4. Check mandatory items - * - * Later rules override earlier rules. - */ - - verdict = check_policy_items(p->default_items, filter); - - if (filter->gid != GID_INVALID) { - items = hashmap_get(p->group_items, UINT32_TO_PTR(filter->gid)); - if (items) { - v = check_policy_items(items, filter); - if (v != DUNNO) - verdict = v; - } - } - - if (filter->uid != UID_INVALID) { - items = hashmap_get(p->user_items, UINT32_TO_PTR(filter->uid)); - if (items) { - v = check_policy_items(items, filter); - if (v != DUNNO) - verdict = v; - } - } - - v = check_policy_items(p->mandatory_items, filter); - if (v != DUNNO) - verdict = v; - - return verdict; -} - -bool policy_check_own(Policy *p, uid_t uid, gid_t gid, const char *name) { - - struct policy_check_filter filter = { - .class = POLICY_ITEM_OWN, - .uid = uid, - .gid = gid, - .name = name, - }; - - int verdict; - - assert(p); - assert(name); - - verdict = policy_check(p, &filter); - - log_full(LOG_AUTH | (verdict != ALLOW ? LOG_WARNING : LOG_DEBUG), - "Ownership permission check for uid=" UID_FMT " gid=" GID_FMT" name=%s: %s", - uid, gid, strna(name), strna(verdict_to_string(verdict))); - - return verdict == ALLOW; -} - -bool policy_check_hello(Policy *p, uid_t uid, gid_t gid) { - - struct policy_check_filter filter = { - .uid = uid, - .gid = gid, - }; - int verdict; - - assert(p); - - filter.class = POLICY_ITEM_USER; - verdict = policy_check(p, &filter); - - if (verdict != DENY) { - int v; - - filter.class = POLICY_ITEM_GROUP; - v = policy_check(p, &filter); - if (v != DUNNO) - verdict = v; - } - - log_full(LOG_AUTH | (verdict != ALLOW ? LOG_WARNING : LOG_DEBUG), - "Hello permission check for uid=" UID_FMT " gid=" GID_FMT": %s", - uid, gid, strna(verdict_to_string(verdict))); - - return verdict == ALLOW; -} - -bool policy_check_recv(Policy *p, - uid_t uid, - gid_t gid, - int message_type, - const char *name, - const char *path, - const char *interface, - const char *member) { - - struct policy_check_filter filter = { - .class = POLICY_ITEM_RECV, - .uid = uid, - .gid = gid, - .message_type = message_type, - .name = name, - .interface = interface, - .path = path, - .member = member, - }; - - int verdict; - - assert(p); - - verdict = policy_check(p, &filter); - - log_full(LOG_AUTH | (verdict != ALLOW ? LOG_WARNING : LOG_DEBUG), - "Recieve permission check for uid=" UID_FMT " gid=" GID_FMT" message=%s name=%s interface=%s path=%s member=%s: %s", - uid, gid, bus_message_type_to_string(message_type), strna(name), strna(path), strna(interface), strna(member), strna(verdict_to_string(verdict))); - - return verdict == ALLOW; -} - -bool policy_check_send(Policy *p, - uid_t uid, - gid_t gid, - int message_type, - const char *name, - const char *path, - const char *interface, - const char *member) { - - struct policy_check_filter filter = { - .class = POLICY_ITEM_SEND, - .uid = uid, - .gid = gid, - .message_type = message_type, - .name = name, - .interface = interface, - .path = path, - .member = member, - }; - - int verdict; - - assert(p); - - verdict = policy_check(p, &filter); - - log_full(LOG_AUTH | (verdict != ALLOW ? LOG_WARNING : LOG_DEBUG), - "Send permission check for uid=" UID_FMT " gid=" GID_FMT" message=%s name=%s interface=%s path=%s member=%s: %s", - uid, gid, bus_message_type_to_string(message_type), strna(name), strna(path), strna(interface), strna(member), strna(verdict_to_string(verdict))); - - return verdict == ALLOW; -} - -int policy_load(Policy *p, char **files) { - char **i; - int r; - - assert(p); - - STRV_FOREACH(i, files) { - - r = file_load(p, *i); - if (r == -EISDIR) { - _cleanup_strv_free_ char **l = NULL; - char **j; - - r = conf_files_list(&l, ".conf", NULL, *i, NULL); - if (r < 0) - return log_error_errno(r, "Failed to get configuration file list: %m"); - - STRV_FOREACH(j, l) - file_load(p, *j); - } - - /* We ignore all errors but EISDIR, and just proceed. */ - } - - return 0; -} - -void policy_free(Policy *p) { - PolicyItem *i, *first; - - if (!p) - return; - - while ((i = p->default_items)) { - LIST_REMOVE(items, p->default_items, i); - policy_item_free(i); - } - - while ((i = p->mandatory_items)) { - LIST_REMOVE(items, p->mandatory_items, i); - policy_item_free(i); - } - - while ((first = hashmap_steal_first(p->user_items))) { - - while ((i = first)) { - LIST_REMOVE(items, first, i); - policy_item_free(i); - } - } - - while ((first = hashmap_steal_first(p->group_items))) { - - while ((i = first)) { - LIST_REMOVE(items, first, i); - policy_item_free(i); - } - } - - hashmap_free(p->user_items); - hashmap_free(p->group_items); - - p->user_items = p->group_items = NULL; -} - -static void dump_items(PolicyItem *items, const char *prefix) { - - PolicyItem *i; - - if (!items) - return; - - if (!prefix) - prefix = ""; - - LIST_FOREACH(items, i, items) { - - printf("%sType: %s\n" - "%sClass: %s\n", - prefix, policy_item_type_to_string(i->type), - prefix, policy_item_class_to_string(i->class)); - - if (i->interface) - printf("%sInterface: %s\n", - prefix, i->interface); - - if (i->member) - printf("%sMember: %s\n", - prefix, i->member); - - if (i->error) - printf("%sError: %s\n", - prefix, i->error); - - if (i->path) - printf("%sPath: %s\n", - prefix, i->path); - - if (i->name) - printf("%sName: %s\n", - prefix, i->name); - - if (i->message_type != 0) - printf("%sMessage Type: %s\n", - prefix, bus_message_type_to_string(i->message_type)); - - if (i->uid_valid) { - _cleanup_free_ char *user; - - user = uid_to_name(i->uid); - - printf("%sUser: %s (%d)\n", - prefix, strna(user), i->uid); - } - - if (i->gid_valid) { - _cleanup_free_ char *group; - - group = gid_to_name(i->gid); - - printf("%sGroup: %s (%d)\n", - prefix, strna(group), i->gid); - } - printf("%s-\n", prefix); - } -} - -static void dump_hashmap_items(Hashmap *h) { - PolicyItem *i; - Iterator j; - void *k; - - HASHMAP_FOREACH_KEY(i, k, h, j) { - printf("\t%s Item for %u:\n", draw_special_char(DRAW_ARROW), PTR_TO_UINT(k)); - dump_items(i, "\t\t"); - } -} - -void policy_dump(Policy *p) { - - printf("%s Default Items:\n", draw_special_char(DRAW_ARROW)); - dump_items(p->default_items, "\t"); - - printf("%s Group Items:\n", draw_special_char(DRAW_ARROW)); - dump_hashmap_items(p->group_items); - - printf("%s User Items:\n", draw_special_char(DRAW_ARROW)); - dump_hashmap_items(p->user_items); - - printf("%s Mandatory Items:\n", draw_special_char(DRAW_ARROW)); - dump_items(p->mandatory_items, "\t"); -} - -static const char* const policy_item_type_table[_POLICY_ITEM_TYPE_MAX] = { - [_POLICY_ITEM_TYPE_UNSET] = "unset", - [POLICY_ITEM_ALLOW] = "allow", - [POLICY_ITEM_DENY] = "deny", -}; -DEFINE_STRING_TABLE_LOOKUP(policy_item_type, PolicyItemType); - -static const char* const policy_item_class_table[_POLICY_ITEM_CLASS_MAX] = { - [_POLICY_ITEM_CLASS_UNSET] = "unset", - [POLICY_ITEM_SEND] = "send", - [POLICY_ITEM_RECV] = "recv", - [POLICY_ITEM_OWN] = "own", - [POLICY_ITEM_OWN_PREFIX] = "own-prefix", - [POLICY_ITEM_USER] = "user", - [POLICY_ITEM_GROUP] = "group", - [POLICY_ITEM_IGNORE] = "ignore", -}; -DEFINE_STRING_TABLE_LOOKUP(policy_item_class, PolicyItemClass); diff --git a/src/bus-proxyd/bus-policy.h b/src/bus-proxyd/bus-policy.h deleted file mode 100644 index 933a53ceb5..0000000000 --- a/src/bus-proxyd/bus-policy.h +++ /dev/null @@ -1,104 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#pragma once - -/*** - This file is part of systemd. - - Copyright 2013 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include - -#include "list.h" -#include "hashmap.h" - -typedef enum PolicyItemType { - _POLICY_ITEM_TYPE_UNSET = 0, - POLICY_ITEM_ALLOW, - POLICY_ITEM_DENY, - _POLICY_ITEM_TYPE_MAX, - _POLICY_ITEM_TYPE_INVALID = -1, -} PolicyItemType; - -typedef enum PolicyItemClass { - _POLICY_ITEM_CLASS_UNSET = 0, - POLICY_ITEM_SEND, - POLICY_ITEM_RECV, - POLICY_ITEM_OWN, - POLICY_ITEM_OWN_PREFIX, - POLICY_ITEM_USER, - POLICY_ITEM_GROUP, - POLICY_ITEM_IGNORE, - _POLICY_ITEM_CLASS_MAX, - _POLICY_ITEM_CLASS_INVALID = -1, -} PolicyItemClass; - -typedef struct PolicyItem PolicyItem; - -struct PolicyItem { - PolicyItemType type; - PolicyItemClass class; - char *interface; - char *member; - char *error; - char *path; - char *name; - uint8_t message_type; - uid_t uid; - gid_t gid; - - bool uid_valid, gid_valid; - - LIST_FIELDS(PolicyItem, items); -}; - -typedef struct Policy { - LIST_HEAD(PolicyItem, default_items); - LIST_HEAD(PolicyItem, mandatory_items); - Hashmap *user_items; - Hashmap *group_items; -} Policy; - -int policy_load(Policy *p, char **files); -void policy_free(Policy *p); - -bool policy_check_own(Policy *p, uid_t uid, gid_t gid, const char *name); -bool policy_check_hello(Policy *p, uid_t uid, gid_t gid); -bool policy_check_recv(Policy *p, - uid_t uid, - gid_t gid, - int message_type, - const char *name, - const char *path, - const char *interface, - const char *member); -bool policy_check_send(Policy *p, - uid_t uid, - gid_t gid, - int message_type, - const char *name, - const char *path, - const char *interface, - const char *member); - -void policy_dump(Policy *p); - -const char* policy_item_type_to_string(PolicyItemType t) _const_; -PolicyItemType policy_item_type_from_string(const char *s) _pure_; - -const char* policy_item_class_to_string(PolicyItemClass t) _const_; -PolicyItemClass policy_item_class_from_string(const char *s) _pure_; diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c index 6da7fb9b55..64c11ffd16 100644 --- a/src/bus-proxyd/bus-proxyd.c +++ b/src/bus-proxyd/bus-proxyd.c @@ -44,9 +44,10 @@ #include "strv.h" #include "def.h" #include "capability.h" -#include "bus-policy.h" #include "bus-control.h" #include "smack-util.h" +#include "set.h" +#include "bus-xml-policy.h" static char *arg_address = NULL; static char *arg_command_line_buffer = NULL; diff --git a/src/bus-proxyd/bus-xml-policy.c b/src/bus-proxyd/bus-xml-policy.c new file mode 100644 index 0000000000..ac0e14b4f9 --- /dev/null +++ b/src/bus-proxyd/bus-xml-policy.c @@ -0,0 +1,1050 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2013 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "xml.h" +#include "fileio.h" +#include "strv.h" +#include "conf-files.h" +#include "bus-internal.h" +#include "bus-message.h" +#include "bus-xml-policy.h" + +static void policy_item_free(PolicyItem *i) { + assert(i); + + free(i->interface); + free(i->member); + free(i->error); + free(i->name); + free(i->path); + free(i); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(PolicyItem*, policy_item_free); + +static void item_append(PolicyItem *i, PolicyItem **list) { + + PolicyItem *tail; + + LIST_FIND_TAIL(items, *list, tail); + LIST_INSERT_AFTER(items, *list, tail, i); +} + +static int file_load(Policy *p, const char *path) { + + _cleanup_free_ char *c = NULL, *policy_user = NULL, *policy_group = NULL; + _cleanup_(policy_item_freep) PolicyItem *i = NULL; + void *xml_state = NULL; + unsigned n_other = 0; + const char *q; + int r; + + enum { + STATE_OUTSIDE, + STATE_BUSCONFIG, + STATE_POLICY, + STATE_POLICY_CONTEXT, + STATE_POLICY_USER, + STATE_POLICY_GROUP, + STATE_POLICY_OTHER_ATTRIBUTE, + STATE_ALLOW_DENY, + STATE_ALLOW_DENY_INTERFACE, + STATE_ALLOW_DENY_MEMBER, + STATE_ALLOW_DENY_ERROR, + STATE_ALLOW_DENY_PATH, + STATE_ALLOW_DENY_MESSAGE_TYPE, + STATE_ALLOW_DENY_NAME, + STATE_ALLOW_DENY_OTHER_ATTRIBUTE, + STATE_OTHER, + } state = STATE_OUTSIDE; + + enum { + POLICY_CATEGORY_NONE, + POLICY_CATEGORY_DEFAULT, + POLICY_CATEGORY_MANDATORY, + POLICY_CATEGORY_USER, + POLICY_CATEGORY_GROUP + } policy_category = POLICY_CATEGORY_NONE; + + unsigned line = 0; + + assert(p); + + r = read_full_file(path, &c, NULL); + if (r < 0) { + if (r == -ENOENT) + return 0; + if (r == -EISDIR) + return r; + + return log_error_errno(r, "Failed to load %s: %m", path); + } + + q = c; + for (;;) { + _cleanup_free_ char *name = NULL; + int t; + + t = xml_tokenize(&q, &name, &xml_state, &line); + if (t < 0) + return log_error_errno(t, "XML parse failure in %s: %m", path); + + switch (state) { + + case STATE_OUTSIDE: + + if (t == XML_TAG_OPEN) { + if (streq(name, "busconfig")) + state = STATE_BUSCONFIG; + else { + log_error("Unexpected tag %s at %s:%u.", name, path, line); + return -EINVAL; + } + + } else if (t == XML_END) + return 0; + else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { + log_error("Unexpected token (1) at %s:%u.", path, line); + return -EINVAL; + } + + break; + + case STATE_BUSCONFIG: + + if (t == XML_TAG_OPEN) { + if (streq(name, "policy")) { + state = STATE_POLICY; + policy_category = POLICY_CATEGORY_NONE; + free(policy_user); + free(policy_group); + policy_user = policy_group = NULL; + } else { + state = STATE_OTHER; + n_other = 0; + } + } else if (t == XML_TAG_CLOSE_EMPTY || + (t == XML_TAG_CLOSE && streq(name, "busconfig"))) + state = STATE_OUTSIDE; + else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { + log_error("Unexpected token (2) at %s:%u.", path, line); + return -EINVAL; + } + + break; + + case STATE_POLICY: + + if (t == XML_ATTRIBUTE_NAME) { + if (streq(name, "context")) + state = STATE_POLICY_CONTEXT; + else if (streq(name, "user")) + state = STATE_POLICY_USER; + else if (streq(name, "group")) + state = STATE_POLICY_GROUP; + else { + if (streq(name, "at_console")) + log_debug("Attribute %s of tag unsupported at %s:%u, ignoring.", name, path, line); + else + log_warning("Attribute %s of tag unknown at %s:%u, ignoring.", name, path, line); + state = STATE_POLICY_OTHER_ATTRIBUTE; + } + } else if (t == XML_TAG_CLOSE_EMPTY || + (t == XML_TAG_CLOSE && streq(name, "policy"))) + state = STATE_BUSCONFIG; + else if (t == XML_TAG_OPEN) { + PolicyItemType it; + + if (streq(name, "allow")) + it = POLICY_ITEM_ALLOW; + else if (streq(name, "deny")) + it = POLICY_ITEM_DENY; + else { + log_warning("Unknown tag %s in %s:%u.", name, path, line); + return -EINVAL; + } + + assert(!i); + i = new0(PolicyItem, 1); + if (!i) + return log_oom(); + + i->type = it; + state = STATE_ALLOW_DENY; + + } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { + log_error("Unexpected token (3) at %s:%u.", path, line); + return -EINVAL; + } + + break; + + case STATE_POLICY_CONTEXT: + + if (t == XML_ATTRIBUTE_VALUE) { + if (streq(name, "default")) { + policy_category = POLICY_CATEGORY_DEFAULT; + state = STATE_POLICY; + } else if (streq(name, "mandatory")) { + policy_category = POLICY_CATEGORY_MANDATORY; + state = STATE_POLICY; + } else { + log_error("context= parameter %s unknown for at %s:%u.", name, path, line); + return -EINVAL; + } + } else { + log_error("Unexpected token (4) at %s:%u.", path, line); + return -EINVAL; + } + + break; + + case STATE_POLICY_USER: + + if (t == XML_ATTRIBUTE_VALUE) { + free(policy_user); + policy_user = name; + name = NULL; + policy_category = POLICY_CATEGORY_USER; + state = STATE_POLICY; + } else { + log_error("Unexpected token (5) in %s:%u.", path, line); + return -EINVAL; + } + + break; + + case STATE_POLICY_GROUP: + + if (t == XML_ATTRIBUTE_VALUE) { + free(policy_group); + policy_group = name; + name = NULL; + policy_category = POLICY_CATEGORY_GROUP; + state = STATE_POLICY; + } else { + log_error("Unexpected token (6) at %s:%u.", path, line); + return -EINVAL; + } + + break; + + case STATE_POLICY_OTHER_ATTRIBUTE: + + if (t == XML_ATTRIBUTE_VALUE) + state = STATE_POLICY; + else { + log_error("Unexpected token (7) in %s:%u.", path, line); + return -EINVAL; + } + + break; + + case STATE_ALLOW_DENY: + + assert(i); + + if (t == XML_ATTRIBUTE_NAME) { + PolicyItemClass ic; + + if (startswith(name, "send_")) + ic = POLICY_ITEM_SEND; + else if (startswith(name, "receive_")) + ic = POLICY_ITEM_RECV; + else if (streq(name, "own")) + ic = POLICY_ITEM_OWN; + else if (streq(name, "own_prefix")) + ic = POLICY_ITEM_OWN_PREFIX; + else if (streq(name, "user")) + ic = POLICY_ITEM_USER; + else if (streq(name, "group")) + ic = POLICY_ITEM_GROUP; + else if (streq(name, "eavesdrop")) { + log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name, path, line); + i->class = POLICY_ITEM_IGNORE; + state = STATE_ALLOW_DENY_OTHER_ATTRIBUTE; + break; + } else { + log_error("Unknown attribute %s= at %s:%u, ignoring.", name, path, line); + state = STATE_ALLOW_DENY_OTHER_ATTRIBUTE; + break; + } + + if (i->class != _POLICY_ITEM_CLASS_UNSET && ic != i->class) { + log_error("send_ and receive_ fields mixed on same tag at %s:%u.", path, line); + return -EINVAL; + } + + i->class = ic; + + if (ic == POLICY_ITEM_SEND || ic == POLICY_ITEM_RECV) { + const char *u; + + u = strchr(name, '_'); + assert(u); + + u++; + + if (streq(u, "interface")) + state = STATE_ALLOW_DENY_INTERFACE; + else if (streq(u, "member")) + state = STATE_ALLOW_DENY_MEMBER; + else if (streq(u, "error")) + state = STATE_ALLOW_DENY_ERROR; + else if (streq(u, "path")) + state = STATE_ALLOW_DENY_PATH; + else if (streq(u, "type")) + state = STATE_ALLOW_DENY_MESSAGE_TYPE; + else if ((streq(u, "destination") && ic == POLICY_ITEM_SEND) || + (streq(u, "sender") && ic == POLICY_ITEM_RECV)) + state = STATE_ALLOW_DENY_NAME; + else { + if (streq(u, "requested_reply")) + log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name, path, line); + else + log_error("Unknown attribute %s= at %s:%u, ignoring.", name, path, line); + state = STATE_ALLOW_DENY_OTHER_ATTRIBUTE; + break; + } + } else + state = STATE_ALLOW_DENY_NAME; + + } else if (t == XML_TAG_CLOSE_EMPTY || + (t == XML_TAG_CLOSE && streq(name, i->type == POLICY_ITEM_ALLOW ? "allow" : "deny"))) { + + if (i->class == _POLICY_ITEM_CLASS_UNSET) { + log_error("Policy not set at %s:%u.", path, line); + return -EINVAL; + } + + if (policy_category == POLICY_CATEGORY_DEFAULT) + item_append(i, &p->default_items); + else if (policy_category == POLICY_CATEGORY_MANDATORY) + item_append(i, &p->mandatory_items); + else if (policy_category == POLICY_CATEGORY_USER) { + const char *u = policy_user; + + assert_cc(sizeof(uid_t) == sizeof(uint32_t)); + + r = hashmap_ensure_allocated(&p->user_items, NULL); + if (r < 0) + return log_oom(); + + if (!u) { + log_error("User policy without name"); + return -EINVAL; + } + + r = get_user_creds(&u, &i->uid, NULL, NULL, NULL); + if (r < 0) { + log_error_errno(r, "Failed to resolve user %s, ignoring policy: %m", u); + free(i); + } else { + PolicyItem *first; + + first = hashmap_get(p->user_items, UINT32_TO_PTR(i->uid)); + item_append(i, &first); + i->uid_valid = true; + + r = hashmap_replace(p->user_items, UINT32_TO_PTR(i->uid), first); + if (r < 0) { + LIST_REMOVE(items, first, i); + return log_oom(); + } + } + + } else if (policy_category == POLICY_CATEGORY_GROUP) { + const char *g = policy_group; + + assert_cc(sizeof(gid_t) == sizeof(uint32_t)); + + r = hashmap_ensure_allocated(&p->group_items, NULL); + if (r < 0) + return log_oom(); + + if (!g) { + log_error("Group policy without name"); + return -EINVAL; + } + + r = get_group_creds(&g, &i->gid); + if (r < 0) { + log_error_errno(r, "Failed to resolve group %s, ignoring policy: %m", g); + free(i); + } else { + PolicyItem *first; + + first = hashmap_get(p->group_items, UINT32_TO_PTR(i->gid)); + item_append(i, &first); + i->gid_valid = true; + + r = hashmap_replace(p->group_items, UINT32_TO_PTR(i->gid), first); + if (r < 0) { + LIST_REMOVE(items, first, i); + return log_oom(); + } + } + } + + state = STATE_POLICY; + i = NULL; + + } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) { + log_error("Unexpected token (8) at %s:%u.", path, line); + return -EINVAL; + } + + break; + + case STATE_ALLOW_DENY_INTERFACE: + + if (t == XML_ATTRIBUTE_VALUE) { + assert(i); + if (i->interface) { + log_error("Duplicate interface at %s:%u.", path, line); + return -EINVAL; + } + + i->interface = name; + name = NULL; + state = STATE_ALLOW_DENY; + } else { + log_error("Unexpected token (9) at %s:%u.", path, line); + return -EINVAL; + } + + break; + + case STATE_ALLOW_DENY_MEMBER: + + if (t == XML_ATTRIBUTE_VALUE) { + assert(i); + if (i->member) { + log_error("Duplicate member in %s:%u.", path, line); + return -EINVAL; + } + + i->member = name; + name = NULL; + state = STATE_ALLOW_DENY; + } else { + log_error("Unexpected token (10) in %s:%u.", path, line); + return -EINVAL; + } + + break; + + case STATE_ALLOW_DENY_ERROR: + + if (t == XML_ATTRIBUTE_VALUE) { + assert(i); + if (i->error) { + log_error("Duplicate error in %s:%u.", path, line); + return -EINVAL; + } + + i->error = name; + name = NULL; + state = STATE_ALLOW_DENY; + } else { + log_error("Unexpected token (11) in %s:%u.", path, line); + return -EINVAL; + } + + break; + + case STATE_ALLOW_DENY_PATH: + + if (t == XML_ATTRIBUTE_VALUE) { + assert(i); + if (i->path) { + log_error("Duplicate path in %s:%u.", path, line); + return -EINVAL; + } + + i->path = name; + name = NULL; + state = STATE_ALLOW_DENY; + } else { + log_error("Unexpected token (12) in %s:%u.", path, line); + return -EINVAL; + } + + break; + + case STATE_ALLOW_DENY_MESSAGE_TYPE: + + if (t == XML_ATTRIBUTE_VALUE) { + assert(i); + + if (i->message_type != 0) { + log_error("Duplicate message type in %s:%u.", path, line); + return -EINVAL; + } + + r = bus_message_type_from_string(name, &i->message_type); + if (r < 0) { + log_error("Invalid message type in %s:%u.", path, line); + return -EINVAL; + } + + state = STATE_ALLOW_DENY; + } else { + log_error("Unexpected token (13) in %s:%u.", path, line); + return -EINVAL; + } + + break; + + case STATE_ALLOW_DENY_NAME: + + if (t == XML_ATTRIBUTE_VALUE) { + assert(i); + if (i->name) { + log_error("Duplicate name in %s:%u.", path, line); + return -EINVAL; + } + + switch (i->class) { + case POLICY_ITEM_USER: + if (!streq(name, "*")) { + const char *u = name; + + r = get_user_creds(&u, &i->uid, NULL, NULL, NULL); + if (r < 0) + log_error_errno(r, "Failed to resolve user %s: %m", name); + else + i->uid_valid = true; + } + break; + case POLICY_ITEM_GROUP: + if (!streq(name, "*")) { + const char *g = name; + + r = get_group_creds(&g, &i->gid); + if (r < 0) + log_error_errno(r, "Failed to resolve group %s: %m", name); + else + i->gid_valid = true; + } + break; + default: + break; + } + + i->name = name; + name = NULL; + + state = STATE_ALLOW_DENY; + } else { + log_error("Unexpected token (14) in %s:%u.", path, line); + return -EINVAL; + } + + break; + + case STATE_ALLOW_DENY_OTHER_ATTRIBUTE: + + if (t == XML_ATTRIBUTE_VALUE) + state = STATE_ALLOW_DENY; + else { + log_error("Unexpected token (15) in %s:%u.", path, line); + return -EINVAL; + } + + break; + + case STATE_OTHER: + + if (t == XML_TAG_OPEN) + n_other++; + else if (t == XML_TAG_CLOSE || t == XML_TAG_CLOSE_EMPTY) { + + if (n_other == 0) + state = STATE_BUSCONFIG; + else + n_other--; + } + + break; + } + } +} + +enum { + DENY, + ALLOW, + DUNNO, +}; + +static const char *verdict_to_string(int v) { + switch (v) { + + case DENY: + return "DENY"; + case ALLOW: + return "ALLOW"; + case DUNNO: + return "DUNNO"; + } + + return NULL; +} + +struct policy_check_filter { + PolicyItemClass class; + uid_t uid; + gid_t gid; + int message_type; + const char *name; + const char *interface; + const char *path; + const char *member; +}; + +static int is_permissive(PolicyItem *i) { + + assert(i); + + return (i->type == POLICY_ITEM_ALLOW) ? ALLOW : DENY; +} + +static int check_policy_item(PolicyItem *i, const struct policy_check_filter *filter) { + + assert(i); + assert(filter); + + switch (i->class) { + case POLICY_ITEM_SEND: + case POLICY_ITEM_RECV: + + if (i->name && !streq_ptr(i->name, filter->name)) + break; + + if ((i->message_type != 0) && (i->message_type != filter->message_type)) + break; + + if (i->path && !streq_ptr(i->path, filter->path)) + break; + + if (i->member && !streq_ptr(i->member, filter->member)) + break; + + if (i->interface && !streq_ptr(i->interface, filter->interface)) + break; + + return is_permissive(i); + + case POLICY_ITEM_OWN: + assert(filter->name); + + if (streq(i->name, "*") || streq(i->name, filter->name)) + return is_permissive(i); + break; + + case POLICY_ITEM_OWN_PREFIX: + assert(filter->name); + + if (streq(i->name, "*") || service_name_startswith(filter->name, i->name)) + return is_permissive(i); + break; + + case POLICY_ITEM_USER: + if (filter->uid != UID_INVALID) + if ((streq_ptr(i->name, "*") || (i->uid_valid && i->uid == filter->uid))) + return is_permissive(i); + break; + + case POLICY_ITEM_GROUP: + if (filter->gid != GID_INVALID) + if ((streq_ptr(i->name, "*") || (i->gid_valid && i->gid == filter->gid))) + return is_permissive(i); + break; + + case POLICY_ITEM_IGNORE: + default: + break; + } + + return DUNNO; +} + +static int check_policy_items(PolicyItem *items, const struct policy_check_filter *filter) { + + PolicyItem *i; + int verdict = DUNNO; + + assert(filter); + + /* Check all policies in a set - a broader one might be followed by a more specific one, + * and the order of rules in policy definitions matters */ + LIST_FOREACH(items, i, items) { + int v; + + if (i->class != filter->class && + !(i->class == POLICY_ITEM_OWN_PREFIX && filter->class == POLICY_ITEM_OWN)) + continue; + + v = check_policy_item(i, filter); + if (v != DUNNO) + verdict = v; + } + + return verdict; +} + +static int policy_check(Policy *p, const struct policy_check_filter *filter) { + + PolicyItem *items; + int verdict, v; + + assert(p); + assert(filter); + + assert(IN_SET(filter->class, POLICY_ITEM_SEND, POLICY_ITEM_RECV, POLICY_ITEM_OWN, POLICY_ITEM_USER, POLICY_ITEM_GROUP)); + + /* + * The policy check is implemented by the following logic: + * + * 1. Check default items + * 2. Check group items + * 3. Check user items + * 4. Check mandatory items + * + * Later rules override earlier rules. + */ + + verdict = check_policy_items(p->default_items, filter); + + if (filter->gid != GID_INVALID) { + items = hashmap_get(p->group_items, UINT32_TO_PTR(filter->gid)); + if (items) { + v = check_policy_items(items, filter); + if (v != DUNNO) + verdict = v; + } + } + + if (filter->uid != UID_INVALID) { + items = hashmap_get(p->user_items, UINT32_TO_PTR(filter->uid)); + if (items) { + v = check_policy_items(items, filter); + if (v != DUNNO) + verdict = v; + } + } + + v = check_policy_items(p->mandatory_items, filter); + if (v != DUNNO) + verdict = v; + + return verdict; +} + +bool policy_check_own(Policy *p, uid_t uid, gid_t gid, const char *name) { + + struct policy_check_filter filter = { + .class = POLICY_ITEM_OWN, + .uid = uid, + .gid = gid, + .name = name, + }; + + int verdict; + + assert(p); + assert(name); + + verdict = policy_check(p, &filter); + + log_full(LOG_AUTH | (verdict != ALLOW ? LOG_WARNING : LOG_DEBUG), + "Ownership permission check for uid=" UID_FMT " gid=" GID_FMT" name=%s: %s", + uid, gid, strna(name), strna(verdict_to_string(verdict))); + + return verdict == ALLOW; +} + +bool policy_check_hello(Policy *p, uid_t uid, gid_t gid) { + + struct policy_check_filter filter = { + .uid = uid, + .gid = gid, + }; + int verdict; + + assert(p); + + filter.class = POLICY_ITEM_USER; + verdict = policy_check(p, &filter); + + if (verdict != DENY) { + int v; + + filter.class = POLICY_ITEM_GROUP; + v = policy_check(p, &filter); + if (v != DUNNO) + verdict = v; + } + + log_full(LOG_AUTH | (verdict != ALLOW ? LOG_WARNING : LOG_DEBUG), + "Hello permission check for uid=" UID_FMT " gid=" GID_FMT": %s", + uid, gid, strna(verdict_to_string(verdict))); + + return verdict == ALLOW; +} + +bool policy_check_recv(Policy *p, + uid_t uid, + gid_t gid, + int message_type, + const char *name, + const char *path, + const char *interface, + const char *member) { + + struct policy_check_filter filter = { + .class = POLICY_ITEM_RECV, + .uid = uid, + .gid = gid, + .message_type = message_type, + .name = name, + .interface = interface, + .path = path, + .member = member, + }; + + int verdict; + + assert(p); + + verdict = policy_check(p, &filter); + + log_full(LOG_AUTH | (verdict != ALLOW ? LOG_WARNING : LOG_DEBUG), + "Recieve permission check for uid=" UID_FMT " gid=" GID_FMT" message=%s name=%s interface=%s path=%s member=%s: %s", + uid, gid, bus_message_type_to_string(message_type), strna(name), strna(path), strna(interface), strna(member), strna(verdict_to_string(verdict))); + + return verdict == ALLOW; +} + +bool policy_check_send(Policy *p, + uid_t uid, + gid_t gid, + int message_type, + const char *name, + const char *path, + const char *interface, + const char *member) { + + struct policy_check_filter filter = { + .class = POLICY_ITEM_SEND, + .uid = uid, + .gid = gid, + .message_type = message_type, + .name = name, + .interface = interface, + .path = path, + .member = member, + }; + + int verdict; + + assert(p); + + verdict = policy_check(p, &filter); + + log_full(LOG_AUTH | (verdict != ALLOW ? LOG_WARNING : LOG_DEBUG), + "Send permission check for uid=" UID_FMT " gid=" GID_FMT" message=%s name=%s interface=%s path=%s member=%s: %s", + uid, gid, bus_message_type_to_string(message_type), strna(name), strna(path), strna(interface), strna(member), strna(verdict_to_string(verdict))); + + return verdict == ALLOW; +} + +int policy_load(Policy *p, char **files) { + char **i; + int r; + + assert(p); + + STRV_FOREACH(i, files) { + + r = file_load(p, *i); + if (r == -EISDIR) { + _cleanup_strv_free_ char **l = NULL; + char **j; + + r = conf_files_list(&l, ".conf", NULL, *i, NULL); + if (r < 0) + return log_error_errno(r, "Failed to get configuration file list: %m"); + + STRV_FOREACH(j, l) + file_load(p, *j); + } + + /* We ignore all errors but EISDIR, and just proceed. */ + } + + return 0; +} + +void policy_free(Policy *p) { + PolicyItem *i, *first; + + if (!p) + return; + + while ((i = p->default_items)) { + LIST_REMOVE(items, p->default_items, i); + policy_item_free(i); + } + + while ((i = p->mandatory_items)) { + LIST_REMOVE(items, p->mandatory_items, i); + policy_item_free(i); + } + + while ((first = hashmap_steal_first(p->user_items))) { + + while ((i = first)) { + LIST_REMOVE(items, first, i); + policy_item_free(i); + } + } + + while ((first = hashmap_steal_first(p->group_items))) { + + while ((i = first)) { + LIST_REMOVE(items, first, i); + policy_item_free(i); + } + } + + hashmap_free(p->user_items); + hashmap_free(p->group_items); + + p->user_items = p->group_items = NULL; +} + +static void dump_items(PolicyItem *items, const char *prefix) { + + PolicyItem *i; + + if (!items) + return; + + if (!prefix) + prefix = ""; + + LIST_FOREACH(items, i, items) { + + printf("%sType: %s\n" + "%sClass: %s\n", + prefix, policy_item_type_to_string(i->type), + prefix, policy_item_class_to_string(i->class)); + + if (i->interface) + printf("%sInterface: %s\n", + prefix, i->interface); + + if (i->member) + printf("%sMember: %s\n", + prefix, i->member); + + if (i->error) + printf("%sError: %s\n", + prefix, i->error); + + if (i->path) + printf("%sPath: %s\n", + prefix, i->path); + + if (i->name) + printf("%sName: %s\n", + prefix, i->name); + + if (i->message_type != 0) + printf("%sMessage Type: %s\n", + prefix, bus_message_type_to_string(i->message_type)); + + if (i->uid_valid) { + _cleanup_free_ char *user; + + user = uid_to_name(i->uid); + + printf("%sUser: %s (%d)\n", + prefix, strna(user), i->uid); + } + + if (i->gid_valid) { + _cleanup_free_ char *group; + + group = gid_to_name(i->gid); + + printf("%sGroup: %s (%d)\n", + prefix, strna(group), i->gid); + } + printf("%s-\n", prefix); + } +} + +static void dump_hashmap_items(Hashmap *h) { + PolicyItem *i; + Iterator j; + void *k; + + HASHMAP_FOREACH_KEY(i, k, h, j) { + printf("\t%s Item for %u:\n", draw_special_char(DRAW_ARROW), PTR_TO_UINT(k)); + dump_items(i, "\t\t"); + } +} + +void policy_dump(Policy *p) { + + printf("%s Default Items:\n", draw_special_char(DRAW_ARROW)); + dump_items(p->default_items, "\t"); + + printf("%s Group Items:\n", draw_special_char(DRAW_ARROW)); + dump_hashmap_items(p->group_items); + + printf("%s User Items:\n", draw_special_char(DRAW_ARROW)); + dump_hashmap_items(p->user_items); + + printf("%s Mandatory Items:\n", draw_special_char(DRAW_ARROW)); + dump_items(p->mandatory_items, "\t"); +} + +static const char* const policy_item_type_table[_POLICY_ITEM_TYPE_MAX] = { + [_POLICY_ITEM_TYPE_UNSET] = "unset", + [POLICY_ITEM_ALLOW] = "allow", + [POLICY_ITEM_DENY] = "deny", +}; +DEFINE_STRING_TABLE_LOOKUP(policy_item_type, PolicyItemType); + +static const char* const policy_item_class_table[_POLICY_ITEM_CLASS_MAX] = { + [_POLICY_ITEM_CLASS_UNSET] = "unset", + [POLICY_ITEM_SEND] = "send", + [POLICY_ITEM_RECV] = "recv", + [POLICY_ITEM_OWN] = "own", + [POLICY_ITEM_OWN_PREFIX] = "own-prefix", + [POLICY_ITEM_USER] = "user", + [POLICY_ITEM_GROUP] = "group", + [POLICY_ITEM_IGNORE] = "ignore", +}; +DEFINE_STRING_TABLE_LOOKUP(policy_item_class, PolicyItemClass); diff --git a/src/bus-proxyd/bus-xml-policy.h b/src/bus-proxyd/bus-xml-policy.h new file mode 100644 index 0000000000..933a53ceb5 --- /dev/null +++ b/src/bus-proxyd/bus-xml-policy.h @@ -0,0 +1,104 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2013 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include + +#include "list.h" +#include "hashmap.h" + +typedef enum PolicyItemType { + _POLICY_ITEM_TYPE_UNSET = 0, + POLICY_ITEM_ALLOW, + POLICY_ITEM_DENY, + _POLICY_ITEM_TYPE_MAX, + _POLICY_ITEM_TYPE_INVALID = -1, +} PolicyItemType; + +typedef enum PolicyItemClass { + _POLICY_ITEM_CLASS_UNSET = 0, + POLICY_ITEM_SEND, + POLICY_ITEM_RECV, + POLICY_ITEM_OWN, + POLICY_ITEM_OWN_PREFIX, + POLICY_ITEM_USER, + POLICY_ITEM_GROUP, + POLICY_ITEM_IGNORE, + _POLICY_ITEM_CLASS_MAX, + _POLICY_ITEM_CLASS_INVALID = -1, +} PolicyItemClass; + +typedef struct PolicyItem PolicyItem; + +struct PolicyItem { + PolicyItemType type; + PolicyItemClass class; + char *interface; + char *member; + char *error; + char *path; + char *name; + uint8_t message_type; + uid_t uid; + gid_t gid; + + bool uid_valid, gid_valid; + + LIST_FIELDS(PolicyItem, items); +}; + +typedef struct Policy { + LIST_HEAD(PolicyItem, default_items); + LIST_HEAD(PolicyItem, mandatory_items); + Hashmap *user_items; + Hashmap *group_items; +} Policy; + +int policy_load(Policy *p, char **files); +void policy_free(Policy *p); + +bool policy_check_own(Policy *p, uid_t uid, gid_t gid, const char *name); +bool policy_check_hello(Policy *p, uid_t uid, gid_t gid); +bool policy_check_recv(Policy *p, + uid_t uid, + gid_t gid, + int message_type, + const char *name, + const char *path, + const char *interface, + const char *member); +bool policy_check_send(Policy *p, + uid_t uid, + gid_t gid, + int message_type, + const char *name, + const char *path, + const char *interface, + const char *member); + +void policy_dump(Policy *p); + +const char* policy_item_type_to_string(PolicyItemType t) _const_; +PolicyItemType policy_item_type_from_string(const char *s) _pure_; + +const char* policy_item_class_to_string(PolicyItemClass t) _const_; +PolicyItemClass policy_item_class_from_string(const char *s) _pure_; diff --git a/src/bus-proxyd/test-bus-policy.c b/src/bus-proxyd/test-bus-policy.c deleted file mode 100644 index 91ab33da4a..0000000000 --- a/src/bus-proxyd/test-bus-policy.c +++ /dev/null @@ -1,160 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2014 Daniel Mack - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "log.h" -#include "util.h" -#include "sd-bus.h" -#include "bus-internal.h" -#include "bus-message.h" -#include "bus-util.h" -#include "build.h" -#include "strv.h" -#include "def.h" -#include "capability.h" - -#include - -static int test_policy_load(Policy *p, const char *name) -{ - _cleanup_free_ char *path = NULL; - int r = 0; - - path = strjoin(TEST_DIR, "/bus-policy/", name, NULL); - assert_se(path); - - if (access(path, R_OK) == 0) - policy_load(p, STRV_MAKE(path)); - else - r = -ENOENT; - - return r; -} - -int main(int argc, char *argv[]) { - - Policy p = {}; - - /* Ownership tests */ - assert_se(test_policy_load(&p, "ownerships.conf") == 0); - - assert_se(policy_check_own(&p, 0, 0, "org.test.test1") == true); - assert_se(policy_check_own(&p, 1, 0, "org.test.test1") == true); - - assert_se(policy_check_own(&p, 0, 0, "org.test.test2") == true); - assert_se(policy_check_own(&p, 1, 0, "org.test.test2") == false); - - assert_se(policy_check_own(&p, 0, 0, "org.test.test3") == false); - assert_se(policy_check_own(&p, 1, 0, "org.test.test3") == false); - - assert_se(policy_check_own(&p, 0, 0, "org.test.test4") == false); - assert_se(policy_check_own(&p, 1, 0, "org.test.test4") == true); - - policy_free(&p); - - /* Signaltest */ - assert_se(test_policy_load(&p, "signals.conf") == 0); - - assert_se(policy_check_send(&p, 0, 0, SD_BUS_MESSAGE_SIGNAL, "bli.bla.blubb", NULL, "/an/object/path", NULL) == true); - assert_se(policy_check_send(&p, 1, 0, SD_BUS_MESSAGE_SIGNAL, "bli.bla.blubb", NULL, "/an/object/path", NULL) == false); - - policy_free(&p); - - /* Method calls */ - assert_se(test_policy_load(&p, "methods.conf") == 0); - policy_dump(&p); - - assert_se(policy_check_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "bli.bla.blubb", "Member") == false); - assert_se(policy_check_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "bli.bla.blubb", "Member") == false); - assert_se(policy_check_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int1", "Member") == true); - assert_se(policy_check_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == true); - - assert_se(policy_check_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test3", "/an/object/path", "org.test.int3", "Member111") == true); - - policy_free(&p); - - /* User and groups */ - assert_se(test_policy_load(&p, "hello.conf") == 0); - policy_dump(&p); - - assert_se(policy_check_hello(&p, 0, 0) == true); - assert_se(policy_check_hello(&p, 1, 0) == false); - assert_se(policy_check_hello(&p, 0, 1) == false); - - policy_free(&p); - - /* dbus1 test file: ownership */ - - assert_se(test_policy_load(&p, "check-own-rules.conf") >= 0); - policy_dump(&p); - - assert_se(policy_check_own(&p, 0, 0, "org.freedesktop") == false); - assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystem") == false); - assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems") == true); - assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems.foo") == true); - assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems.foo.bar") == true); - assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems2") == false); - assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems2.foo") == false); - assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems2.foo.bar") == false); - - policy_free(&p); - - /* dbus1 test file: many rules */ - - assert_se(test_policy_load(&p, "many-rules.conf") >= 0); - policy_dump(&p); - policy_free(&p); - - /* dbus1 test file: generic test */ - - assert_se(test_policy_load(&p, "test.conf") >= 0); - policy_dump(&p); - - assert_se(policy_check_own(&p, 0, 0, "org.foo.FooService") == true); - assert_se(policy_check_own(&p, 0, 0, "org.foo.FooService2") == false); - assert_se(policy_check_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == false); - assert_se(policy_check_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true); - assert_se(policy_check_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true); - assert_se(policy_check_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface2", "Member") == false); - assert_se(policy_check_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService2", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == false); - - assert_se(policy_check_own(&p, 100, 0, "org.foo.FooService") == false); - assert_se(policy_check_own(&p, 100, 0, "org.foo.FooService2") == false); - assert_se(policy_check_send(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == false); - assert_se(policy_check_send(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == false); - assert_se(policy_check_recv(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true); - assert_se(policy_check_recv(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface2", "Member") == false); - assert_se(policy_check_recv(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService2", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == false); - - policy_free(&p); - - return EXIT_SUCCESS; -} diff --git a/src/bus-proxyd/test-bus-xml-policy.c b/src/bus-proxyd/test-bus-xml-policy.c new file mode 100644 index 0000000000..b0f4ed7d3d --- /dev/null +++ b/src/bus-proxyd/test-bus-xml-policy.c @@ -0,0 +1,158 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2014 Daniel Mack + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "util.h" +#include "sd-bus.h" +#include "bus-internal.h" +#include "bus-message.h" +#include "bus-util.h" +#include "build.h" +#include "strv.h" +#include "def.h" +#include "capability.h" +#include "bus-xml-policy.h" + +static int test_policy_load(Policy *p, const char *name) { + _cleanup_free_ char *path = NULL; + int r = 0; + + path = strjoin(TEST_DIR, "/bus-policy/", name, NULL); + assert_se(path); + + if (access(path, R_OK) == 0) + policy_load(p, STRV_MAKE(path)); + else + r = -ENOENT; + + return r; +} + +int main(int argc, char *argv[]) { + + Policy p = {}; + + /* Ownership tests */ + assert_se(test_policy_load(&p, "ownerships.conf") == 0); + + assert_se(policy_check_own(&p, 0, 0, "org.test.test1") == true); + assert_se(policy_check_own(&p, 1, 0, "org.test.test1") == true); + + assert_se(policy_check_own(&p, 0, 0, "org.test.test2") == true); + assert_se(policy_check_own(&p, 1, 0, "org.test.test2") == false); + + assert_se(policy_check_own(&p, 0, 0, "org.test.test3") == false); + assert_se(policy_check_own(&p, 1, 0, "org.test.test3") == false); + + assert_se(policy_check_own(&p, 0, 0, "org.test.test4") == false); + assert_se(policy_check_own(&p, 1, 0, "org.test.test4") == true); + + policy_free(&p); + + /* Signaltest */ + assert_se(test_policy_load(&p, "signals.conf") == 0); + + assert_se(policy_check_send(&p, 0, 0, SD_BUS_MESSAGE_SIGNAL, "bli.bla.blubb", NULL, "/an/object/path", NULL) == true); + assert_se(policy_check_send(&p, 1, 0, SD_BUS_MESSAGE_SIGNAL, "bli.bla.blubb", NULL, "/an/object/path", NULL) == false); + + policy_free(&p); + + /* Method calls */ + assert_se(test_policy_load(&p, "methods.conf") == 0); + policy_dump(&p); + + assert_se(policy_check_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "bli.bla.blubb", "Member") == false); + assert_se(policy_check_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "bli.bla.blubb", "Member") == false); + assert_se(policy_check_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int1", "Member") == true); + assert_se(policy_check_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == true); + + assert_se(policy_check_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test3", "/an/object/path", "org.test.int3", "Member111") == true); + + policy_free(&p); + + /* User and groups */ + assert_se(test_policy_load(&p, "hello.conf") == 0); + policy_dump(&p); + + assert_se(policy_check_hello(&p, 0, 0) == true); + assert_se(policy_check_hello(&p, 1, 0) == false); + assert_se(policy_check_hello(&p, 0, 1) == false); + + policy_free(&p); + + /* dbus1 test file: ownership */ + + assert_se(test_policy_load(&p, "check-own-rules.conf") >= 0); + policy_dump(&p); + + assert_se(policy_check_own(&p, 0, 0, "org.freedesktop") == false); + assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystem") == false); + assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems") == true); + assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems.foo") == true); + assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems.foo.bar") == true); + assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems2") == false); + assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems2.foo") == false); + assert_se(policy_check_own(&p, 0, 0, "org.freedesktop.ManySystems2.foo.bar") == false); + + policy_free(&p); + + /* dbus1 test file: many rules */ + + assert_se(test_policy_load(&p, "many-rules.conf") >= 0); + policy_dump(&p); + policy_free(&p); + + /* dbus1 test file: generic test */ + + assert_se(test_policy_load(&p, "test.conf") >= 0); + policy_dump(&p); + + assert_se(policy_check_own(&p, 0, 0, "org.foo.FooService") == true); + assert_se(policy_check_own(&p, 0, 0, "org.foo.FooService2") == false); + assert_se(policy_check_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == false); + assert_se(policy_check_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true); + assert_se(policy_check_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true); + assert_se(policy_check_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface2", "Member") == false); + assert_se(policy_check_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService2", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == false); + + assert_se(policy_check_own(&p, 100, 0, "org.foo.FooService") == false); + assert_se(policy_check_own(&p, 100, 0, "org.foo.FooService2") == false); + assert_se(policy_check_send(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == false); + assert_se(policy_check_send(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == false); + assert_se(policy_check_recv(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true); + assert_se(policy_check_recv(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface2", "Member") == false); + assert_se(policy_check_recv(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService2", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == false); + + policy_free(&p); + + return EXIT_SUCCESS; +} diff --git a/src/core/bus-common.c b/src/core/bus-common.c deleted file mode 100644 index 4a61cb9a3a..0000000000 --- a/src/core/bus-common.c +++ /dev/null @@ -1,35 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2014 Daniel Mack - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include "special.h" -#include "bus-kernel.h" -#include "bus-internal.h" -#include "bus-util.h" -#include "service.h" -#include "bus-common.h" - -static const char* const bus_policy_access_table[_BUS_POLICY_ACCESS_MAX] = { - [BUS_POLICY_ACCESS_SEE] = "see", - [BUS_POLICY_ACCESS_TALK] = "talk", - [BUS_POLICY_ACCESS_OWN] = "own", -}; - -DEFINE_STRING_TABLE_LOOKUP(bus_policy_access, BusPolicyAccess); diff --git a/src/core/bus-common.h b/src/core/bus-common.h deleted file mode 100644 index 209f870c72..0000000000 --- a/src/core/bus-common.h +++ /dev/null @@ -1,35 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#pragma once - -#include "macro.h" - -/*** - This file is part of systemd. - - Copyright 2014 Daniel Mack - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -typedef enum BusPolicyAccess { - BUS_POLICY_ACCESS_SEE, - BUS_POLICY_ACCESS_TALK, - BUS_POLICY_ACCESS_OWN, - _BUS_POLICY_ACCESS_MAX, - _BUS_POLICY_ACCESS_INVALID = -1 -} BusPolicyAccess; - -const char* bus_policy_access_to_string(BusPolicyAccess i) _const_; -BusPolicyAccess bus_policy_access_from_string(const char *s) _pure_; diff --git a/src/core/bus-endpoint.c b/src/core/bus-endpoint.c index aac540ddee..27dd192a2f 100644 --- a/src/core/bus-endpoint.c +++ b/src/core/bus-endpoint.c @@ -19,10 +19,56 @@ #include +#include "kdbus.h" +#include "bus-kernel.h" +#include "bus-policy.h" #include "bus-endpoint.h" -int bus_endpoint_new(BusEndpoint **ep) -{ +int bus_kernel_set_endpoint_policy(int fd, uid_t uid, BusEndpoint *ep) { + + struct kdbus_cmd_update *update; + struct kdbus_item *n; + BusEndpointPolicy *po; + Iterator i; + size_t size; + int r; + + size = ALIGN8(offsetof(struct kdbus_cmd_update, items)); + + HASHMAP_FOREACH(po, ep->policy_hash, i) { + size += ALIGN8(offsetof(struct kdbus_item, str) + strlen(po->name) + 1); + size += ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access)); + } + + update = alloca0_align(size, 8); + update->size = size; + + n = update->items; + + HASHMAP_FOREACH(po, ep->policy_hash, i) { + n->type = KDBUS_ITEM_NAME; + n->size = offsetof(struct kdbus_item, str) + strlen(po->name) + 1; + strcpy(n->str, po->name); + n = KDBUS_ITEM_NEXT(n); + + n->type = KDBUS_ITEM_POLICY_ACCESS; + n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access); + + n->policy_access.type = KDBUS_POLICY_ACCESS_USER; + n->policy_access.access = bus_kernel_translate_access(po->access); + n->policy_access.id = uid; + + n = KDBUS_ITEM_NEXT(n); + } + + r = ioctl(fd, KDBUS_CMD_ENDPOINT_UPDATE, update); + if (r < 0) + return -errno; + + return 0; +} + +int bus_endpoint_new(BusEndpoint **ep) { assert(ep); *ep = new0(BusEndpoint, 1); @@ -32,8 +78,7 @@ int bus_endpoint_new(BusEndpoint **ep) return 0; } -int bus_endpoint_add_policy(BusEndpoint *ep, const char *name, BusPolicyAccess access) -{ +int bus_endpoint_add_policy(BusEndpoint *ep, const char *name, BusPolicyAccess access) { _cleanup_free_ BusEndpointPolicy *po = NULL; _cleanup_free_ char *key = NULL; int r; @@ -80,8 +125,7 @@ int bus_endpoint_add_policy(BusEndpoint *ep, const char *name, BusPolicyAccess a return 0; } -void bus_endpoint_free(BusEndpoint *endpoint) -{ +void bus_endpoint_free(BusEndpoint *endpoint) { if (!endpoint) return; diff --git a/src/core/bus-endpoint.h b/src/core/bus-endpoint.h index 2c5415f34e..4a31f4c4be 100644 --- a/src/core/bus-endpoint.h +++ b/src/core/bus-endpoint.h @@ -24,8 +24,8 @@ typedef struct BusEndpoint BusEndpoint; typedef struct BusEndpointPolicy BusEndpointPolicy; -#include "bus-common.h" #include "hashmap.h" +#include "bus-policy.h" struct BusEndpointPolicy { char *name; @@ -40,3 +40,5 @@ int bus_endpoint_new(BusEndpoint **ep); void bus_endpoint_free(BusEndpoint *endpoint); int bus_endpoint_add_policy(BusEndpoint *ep, const char *name, BusPolicyAccess access); + +int bus_kernel_set_endpoint_policy(int fd, uid_t uid, BusEndpoint *ep); diff --git a/src/core/busname.c b/src/core/busname.c index acd665282d..9ab95569eb 100644 --- a/src/core/busname.c +++ b/src/core/busname.c @@ -26,9 +26,10 @@ #include "bus-internal.h" #include "bus-util.h" #include "service.h" +#include "kdbus.h" +#include "bus-policy.h" #include "dbus-busname.h" #include "busname.h" -#include "kdbus.h" static const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = { [BUSNAME_DEAD] = UNIT_INACTIVE, diff --git a/src/core/busname.h b/src/core/busname.h index c9b653d82e..775822d8de 100644 --- a/src/core/busname.h +++ b/src/core/busname.h @@ -25,7 +25,6 @@ typedef struct BusName BusName; typedef struct BusNamePolicy BusNamePolicy; #include "unit.h" -#include "bus-common.h" typedef enum BusNameState { BUSNAME_DEAD, @@ -52,22 +51,6 @@ typedef enum BusNameResult { _BUSNAME_RESULT_INVALID = -1 } BusNameResult; -typedef enum BusNamePolicyType { - BUSNAME_POLICY_TYPE_USER, - BUSNAME_POLICY_TYPE_GROUP, - _BUSNAME_POLICY_TYPE_MAX, - _BUSNAME_POLICY_TYPE_INVALID = -1 -} BusNamePolicyType; - -struct BusNamePolicy { - BusNamePolicyType type; - BusPolicyAccess access; - - char *name; - - LIST_FIELDS(BusNamePolicy, policy); -}; - struct BusName { Unit meta; diff --git a/src/core/execute.c b/src/core/execute.c index 4735ab2417..c472dadfed 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -84,7 +84,7 @@ #include "mkdir.h" #include "apparmor-util.h" #include "smack-util.h" -#include "bus-kernel.h" +#include "bus-endpoint.h" #include "label.h" #include "cap-list.h" diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 977b3407ba..cb529d5a9e 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -31,6 +31,7 @@ #include "list.h" #include "util.h" #include "refcnt.h" +#include "socket-util.h" #include "sd-bus.h" #include "bus-error.h" diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index a69628945d..a7811eea0a 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -1576,69 +1576,6 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) { return fd; } -static int bus_kernel_translate_access(BusPolicyAccess access) { - assert(access >= 0); - assert(access < _BUS_POLICY_ACCESS_MAX); - - switch (access) { - - case BUS_POLICY_ACCESS_SEE: - return KDBUS_POLICY_SEE; - - case BUS_POLICY_ACCESS_TALK: - return KDBUS_POLICY_TALK; - - case BUS_POLICY_ACCESS_OWN: - return KDBUS_POLICY_OWN; - - default: - assert_not_reached("Unknown policy access"); - } -} - -static int bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbus_item *item) { - int r; - - assert(policy); - assert(item); - - switch (policy->type) { - - case BUSNAME_POLICY_TYPE_USER: { - const char *user = policy->name; - uid_t uid; - - r = get_user_creds(&user, &uid, NULL, NULL, NULL); - if (r < 0) - return r; - - item->policy_access.type = KDBUS_POLICY_ACCESS_USER; - item->policy_access.id = uid; - break; - } - - case BUSNAME_POLICY_TYPE_GROUP: { - const char *group = policy->name; - gid_t gid; - - r = get_group_creds(&group, &gid); - if (r < 0) - return r; - - item->policy_access.type = KDBUS_POLICY_ACCESS_GROUP; - item->policy_access.id = gid; - break; - } - - default: - assert_not_reached("Unknown policy type"); - } - - item->policy_access.access = bus_kernel_translate_access(policy->access); - - return 0; -} - int bus_kernel_open_bus_fd(const char *bus, char **path) { char *p; int fd; @@ -1715,128 +1652,6 @@ int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char * return fd; } -int bus_kernel_set_endpoint_policy(int fd, uid_t uid, BusEndpoint *ep) { - - struct kdbus_cmd_update *update; - struct kdbus_item *n; - BusEndpointPolicy *po; - Iterator i; - size_t size; - int r; - - size = ALIGN8(offsetof(struct kdbus_cmd_update, items)); - - HASHMAP_FOREACH(po, ep->policy_hash, i) { - size += ALIGN8(offsetof(struct kdbus_item, str) + strlen(po->name) + 1); - size += ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access)); - } - - update = alloca0_align(size, 8); - update->size = size; - - n = update->items; - - HASHMAP_FOREACH(po, ep->policy_hash, i) { - n->type = KDBUS_ITEM_NAME; - n->size = offsetof(struct kdbus_item, str) + strlen(po->name) + 1; - strcpy(n->str, po->name); - n = KDBUS_ITEM_NEXT(n); - - n->type = KDBUS_ITEM_POLICY_ACCESS; - n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access); - - n->policy_access.type = KDBUS_POLICY_ACCESS_USER; - n->policy_access.access = bus_kernel_translate_access(po->access); - n->policy_access.id = uid; - - n = KDBUS_ITEM_NEXT(n); - } - - r = ioctl(fd, KDBUS_CMD_ENDPOINT_UPDATE, update); - if (r < 0) - return -errno; - - return 0; -} - -int bus_kernel_make_starter( - int fd, - const char *name, - bool activating, - bool accept_fd, - BusNamePolicy *policy, - BusPolicyAccess world_policy) { - - struct kdbus_cmd_free cmd_free = { .size = sizeof(cmd_free) }; - struct kdbus_cmd_hello *hello; - struct kdbus_item *n; - size_t policy_cnt = 0; - BusNamePolicy *po; - size_t size; - int r; - - assert(fd >= 0); - assert(name); - - LIST_FOREACH(policy, po, policy) - policy_cnt++; - - if (world_policy >= 0) - policy_cnt++; - - size = offsetof(struct kdbus_cmd_hello, items) + - ALIGN8(offsetof(struct kdbus_item, str) + strlen(name) + 1) + - policy_cnt * ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access)); - - hello = alloca0_align(size, 8); - - n = hello->items; - strcpy(n->str, name); - n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1; - n->type = KDBUS_ITEM_NAME; - n = KDBUS_ITEM_NEXT(n); - - LIST_FOREACH(policy, po, policy) { - n->type = KDBUS_ITEM_POLICY_ACCESS; - n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access); - - r = bus_kernel_translate_policy(po, n); - if (r < 0) - return r; - - n = KDBUS_ITEM_NEXT(n); - } - - if (world_policy >= 0) { - n->type = KDBUS_ITEM_POLICY_ACCESS; - n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access); - n->policy_access.type = KDBUS_POLICY_ACCESS_WORLD; - n->policy_access.access = bus_kernel_translate_access(world_policy); - } - - hello->size = size; - hello->flags = - (activating ? KDBUS_HELLO_ACTIVATOR : KDBUS_HELLO_POLICY_HOLDER) | - (accept_fd ? KDBUS_HELLO_ACCEPT_FD : 0); - hello->pool_size = KDBUS_POOL_SIZE; - hello->attach_flags_send = _KDBUS_ATTACH_ANY; - hello->attach_flags_recv = _KDBUS_ATTACH_ANY; - - if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) - return -errno; - - /* not interested in any output values */ - cmd_free.offset = hello->offset; - (void) ioctl(fd, KDBUS_CMD_FREE, &cmd_free); - - /* The higher 32bit of the bus_flags fields are considered - * 'incompatible flags'. Refuse them all for now. */ - if (hello->bus_flags > 0xFFFFFFFFULL) - return -ENOTSUP; - - return fd; -} - int bus_kernel_try_close(sd_bus *bus) { assert(bus); assert(bus->is_kernel); diff --git a/src/libsystemd/sd-bus/bus-kernel.h b/src/libsystemd/sd-bus/bus-kernel.h index 2152f62d12..7b1e9ef981 100644 --- a/src/libsystemd/sd-bus/bus-kernel.h +++ b/src/libsystemd/sd-bus/bus-kernel.h @@ -23,8 +23,6 @@ #include -#include "busname.h" -#include "bus-endpoint.h" #include "sd-bus.h" #define KDBUS_ITEM_NEXT(item) \ @@ -67,13 +65,10 @@ int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority); int bus_kernel_open_bus_fd(const char *bus, char **path); -int bus_kernel_make_starter(int fd, const char *name, bool activating, bool accept_fd, BusNamePolicy *policy, BusPolicyAccess world_policy); int bus_kernel_create_bus(const char *name, bool world, char **s); int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char **path); -int bus_kernel_set_endpoint_policy(int fd, uid_t uid, BusEndpoint *ep); - int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated); void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated); diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c index dd6ae865b6..3233c1b29b 100644 --- a/src/libsystemd/sd-bus/busctl.c +++ b/src/libsystemd/sd-bus/busctl.c @@ -28,6 +28,7 @@ #include "pager.h" #include "xml.h" #include "path-util.h" +#include "set.h" #include "sd-bus.h" #include "bus-message.h" diff --git a/src/test/test-tables.c b/src/test/test-tables.c index 97d5609adf..bda224bec6 100644 --- a/src/test/test-tables.c +++ b/src/test/test-tables.c @@ -46,7 +46,8 @@ #include "util.h" #include "architecture.h" #include "link-config.h" -#include "bus-policy.h" +#include "bus-xml-policy.h" +#include "busname.h" #include "journald-server.h" #include "locale-util.h" -- cgit v1.2.3-54-g00ecf