summaryrefslogtreecommitdiff
path: root/src/bus-proxyd
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-02-15 14:54:09 +0100
committerLennart Poettering <lennart@poettering.net>2016-02-15 14:54:09 +0100
commit8eff97a103581750d90c7e0c2f984dc261226ccc (patch)
treea3cb36a7db39448767d62866504e465a8ee1c56e /src/bus-proxyd
parent4d5d9d001105507ee40ff56f0456053c2c7ed6d3 (diff)
parent798c486fbcdce3346cd862c52e1a200bb8a2cb23 (diff)
Merge pull request #2618 from zonque/busproxy-removal
remove bus-proxyd
Diffstat (limited to 'src/bus-proxyd')
l---------src/bus-proxyd/Makefile1
-rw-r--r--src/bus-proxyd/bus-proxyd.c328
-rw-r--r--src/bus-proxyd/bus-xml-policy.c1327
-rw-r--r--src/bus-proxyd/bus-xml-policy.h147
-rw-r--r--src/bus-proxyd/driver.c745
-rw-r--r--src/bus-proxyd/driver.h27
-rw-r--r--src/bus-proxyd/proxy.c953
-rw-r--r--src/bus-proxyd/proxy.h66
-rw-r--r--src/bus-proxyd/stdio-bridge.c244
-rw-r--r--src/bus-proxyd/synthesize.c225
-rw-r--r--src/bus-proxyd/synthesize.h36
-rw-r--r--src/bus-proxyd/test-bus-xml-policy.c170
12 files changed, 0 insertions, 4269 deletions
diff --git a/src/bus-proxyd/Makefile b/src/bus-proxyd/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/bus-proxyd/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c
deleted file mode 100644
index b6bd6eb390..0000000000
--- a/src/bus-proxyd/bus-proxyd.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Daniel Mack
- Copyright 2014 Kay Sievers
- Copyright 2015 David Herrmann
-
- 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <getopt.h>
-#include <pthread.h>
-#include <stddef.h>
-#include <string.h>
-#include <sys/prctl.h>
-#include <sys/socket.h>
-#include <unistd.h>
-
-#include "sd-daemon.h"
-
-#include "alloc-util.h"
-#include "bus-internal.h"
-#include "bus-xml-policy.h"
-#include "capability-util.h"
-#include "def.h"
-#include "fd-util.h"
-#include "formats-util.h"
-#include "log.h"
-#include "proxy.h"
-#include "string-util.h"
-#include "strv.h"
-#include "user-util.h"
-#include "util.h"
-
-static char *arg_address = NULL;
-static char **arg_configuration = NULL;
-
-typedef struct {
- int fd;
- SharedPolicy *policy;
- uid_t bus_uid;
-} ClientContext;
-
-static ClientContext *client_context_free(ClientContext *c) {
- if (!c)
- return NULL;
-
- safe_close(c->fd);
- free(c);
-
- return NULL;
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(ClientContext*, client_context_free);
-
-static int client_context_new(ClientContext **out) {
- _cleanup_(client_context_freep) ClientContext *c = NULL;
-
- c = new0(ClientContext, 1);
- if (!c)
- return -ENOMEM;
-
- c->fd = -1;
-
- *out = c;
- c = NULL;
- return 0;
-}
-
-static void *run_client(void *userdata) {
- _cleanup_(client_context_freep) ClientContext *c = userdata;
- _cleanup_(proxy_freep) Proxy *p = NULL;
- char comm[16];
- int r;
-
- r = proxy_new(&p, c->fd, c->fd, arg_address);
- c->fd = -1;
-
- if (r < 0)
- goto exit;
-
- /* set comm to "p$PIDu$UID" and suffix with '*' if truncated */
- r = snprintf(comm, sizeof(comm), "p" PID_FMT "u" UID_FMT, p->local_creds.pid, p->local_creds.uid);
- if (r >= (ssize_t)sizeof(comm))
- comm[sizeof(comm) - 2] = '*';
- (void) prctl(PR_SET_NAME, comm);
-
- r = proxy_set_policy(p, c->policy, arg_configuration);
- if (r < 0)
- goto exit;
-
- r = proxy_hello_policy(p, c->bus_uid);
- if (r < 0)
- goto exit;
-
- r = proxy_run(p);
-
-exit:
- return NULL;
-}
-
-static int loop_clients(int accept_fd, uid_t bus_uid) {
- _cleanup_(shared_policy_freep) SharedPolicy *sp = NULL;
- pthread_attr_t attr;
- int r;
-
- r = pthread_attr_init(&attr);
- if (r != 0)
- return log_error_errno(r, "Cannot initialize pthread attributes: %m");
-
- r = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if (r != 0) {
- r = log_error_errno(r, "Cannot mark pthread attributes as detached: %m");
- goto finish;
- }
-
- r = shared_policy_new(&sp);
- if (r < 0)
- goto finish;
-
- for (;;) {
- ClientContext *c;
- pthread_t tid;
- int fd;
-
- fd = accept4(accept_fd, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
- if (fd < 0) {
- if (errno == EAGAIN || errno == EINTR)
- continue;
-
- r = log_error_errno(errno, "accept4() failed: %m");
- goto finish;
- }
-
- r = client_context_new(&c);
- if (r < 0) {
- log_oom();
- close(fd);
- continue;
- }
-
- c->fd = fd;
- c->policy = sp;
- c->bus_uid = bus_uid;
-
- r = pthread_create(&tid, &attr, run_client, c);
- if (r != 0) {
- log_warning_errno(r, "Cannot spawn thread, ignoring: %m");
- client_context_free(c);
- continue;
- }
- }
-
-finish:
- pthread_attr_destroy(&attr);
- return r;
-}
-
-static int help(void) {
-
- printf("%s [OPTIONS...]\n\n"
- "DBus proxy server.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --configuration=PATH Configuration file or directory\n"
- " --machine=MACHINE Connect to specified machine\n"
- " --address=ADDRESS Connect to the bus specified by ADDRESS\n"
- " (default: " DEFAULT_SYSTEM_BUS_ADDRESS ")\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_ADDRESS,
- ARG_CONFIGURATION,
- ARG_MACHINE,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "address", required_argument, NULL, ARG_ADDRESS },
- { "configuration", required_argument, NULL, ARG_CONFIGURATION },
- { "machine", required_argument, NULL, ARG_MACHINE },
- {},
- };
-
- int c, r;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- return version();
-
- case ARG_ADDRESS:
- r = free_and_strdup(&arg_address, optarg);
- if (r < 0)
- return log_oom();
- break;
-
- case ARG_CONFIGURATION:
- r = strv_extend(&arg_configuration, optarg);
- if (r < 0)
- return log_oom();
- break;
-
- case ARG_MACHINE: {
- _cleanup_free_ char *e = NULL;
- char *a;
-
- e = bus_address_escape(optarg);
- if (!e)
- return log_oom();
-
- a = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL);
- if (!a)
- return log_oom();
-
- free(arg_address);
- arg_address = a;
-
- break;
- }
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached("Unhandled option");
- }
-
- if (argc > optind) {
- log_error("Too many arguments");
- return -EINVAL;
- }
-
- if (!arg_address) {
- arg_address = strdup(DEFAULT_SYSTEM_BUS_ADDRESS);
- if (!arg_address)
- return log_oom();
- }
-
- return 1;
-}
-
-int main(int argc, char *argv[]) {
- int r, accept_fd;
- uid_t uid, bus_uid;
- gid_t gid;
-
- log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
- log_parse_environment();
- log_open();
-
- bus_uid = getuid();
-
- if (geteuid() == 0) {
- const char *user = "systemd-bus-proxy";
-
- r = get_user_creds(&user, &uid, &gid, NULL, NULL);
- if (r < 0) {
- log_error_errno(r, "Cannot resolve user name %s: %m", user);
- goto finish;
- }
-
- r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
- if (r < 0) {
- log_error_errno(r, "Cannot drop privileges: %m");
- goto finish;
- }
- }
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
-
- r = sd_listen_fds(0);
- if (r != 1) {
- log_error("Illegal number of file descriptors passed");
- goto finish;
- }
-
- accept_fd = SD_LISTEN_FDS_START;
-
- r = fd_nonblock(accept_fd, false);
- if (r < 0) {
- log_error_errno(r, "Cannot mark accept-fd non-blocking: %m");
- goto finish;
- }
-
- r = loop_clients(accept_fd, bus_uid);
-
-finish:
- sd_notify(false,
- "STOPPING=1\n"
- "STATUS=Shutting down.");
-
- strv_free(arg_configuration);
- free(arg_address);
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/bus-proxyd/bus-xml-policy.c b/src/bus-proxyd/bus-xml-policy.c
deleted file mode 100644
index 8943e0dc12..0000000000
--- a/src/bus-proxyd/bus-xml-policy.c
+++ /dev/null
@@ -1,1327 +0,0 @@
-/***
- 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-login.h"
-
-#include "alloc-util.h"
-#include "bus-internal.h"
-#include "bus-xml-policy.h"
-#include "conf-files.h"
-#include "fileio.h"
-#include "formats-util.h"
-#include "locale-util.h"
-#include "set.h"
-#include "string-table.h"
-#include "string-util.h"
-#include "strv.h"
-#include "user-util.h"
-#include "xml.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_CONSOLE,
- 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_ON_CONSOLE,
- POLICY_CATEGORY_NO_CONSOLE,
- 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, "at_console"))
- state = STATE_POLICY_CONSOLE;
- else if (streq(name, "user"))
- state = STATE_POLICY_USER;
- else if (streq(name, "group"))
- state = STATE_POLICY_GROUP;
- else {
- log_warning("Attribute %s of <policy> 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 <policy> %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 <policy> 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_CONSOLE:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- if (streq(name, "true")) {
- policy_category = POLICY_CATEGORY_ON_CONSOLE;
- state = STATE_POLICY;
- } else if (streq(name, "false")) {
- policy_category = POLICY_CATEGORY_NO_CONSOLE;
- state = STATE_POLICY;
- } else {
- log_error("at_console= parameter %s unknown for <policy> at %s:%u.", name, path, line);
- return -EINVAL;
- }
- } else {
- log_error("Unexpected token (4.1) 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 (STR_IN_SET(name, "eavesdrop", "log")) {
- log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name, path, line);
- 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_, receive_/eavesdrop 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 the tag is fully empty so far, we consider it a recv */
- if (i->class == _POLICY_ITEM_CLASS_UNSET)
- i->class = POLICY_ITEM_RECV;
-
- 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_ON_CONSOLE)
- item_append(i, &p->on_console_items);
- else if (policy_category == POLICY_CATEGORY_NO_CONSOLE)
- item_append(i, &p->no_console_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, UID_TO_PTR(i->uid));
- item_append(i, &first);
- i->uid_valid = true;
-
- r = hashmap_replace(p->user_items, UID_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, GID_TO_PTR(i->gid));
- item_append(i, &first);
- i->gid_valid = true;
-
- r = hashmap_replace(p->group_items, GID_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;
- }
-
- if (!streq(name, "*")) {
- 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;
- }
-
- if (!streq(name, "*")) {
- 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;
- }
-
- if (!streq(name, "*")) {
- 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;
- }
-
- if (!streq(name, "*")) {
- 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;
- }
-
- if (!streq(name, "*")) {
- 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;
-
- case POLICY_ITEM_SEND:
- case POLICY_ITEM_RECV:
-
- if (streq(name, "*"))
- name = mfree(name);
- 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 on/no_console items
- * 5. 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, GID_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, UID_TO_PTR(filter->uid));
- if (items) {
- v = check_policy_items(items, filter);
- if (v != DUNNO)
- verdict = v;
- }
- }
-
- if (filter->uid != UID_INVALID && sd_uid_get_seats(filter->uid, -1, NULL) > 0)
- v = check_policy_items(p->on_console_items, filter);
- else
- v = check_policy_items(p->no_console_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_one_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,
- };
-
- assert(p);
-
- return policy_check(p, &filter) == ALLOW;
-}
-
-bool policy_check_recv(Policy *p,
- uid_t uid,
- gid_t gid,
- int message_type,
- Set *names,
- char **namesv,
- const char *path,
- const char *interface,
- const char *member,
- bool dbus_to_kernel) {
-
- char *n, **nv, *last = NULL;
- bool allow = false;
- Iterator i;
-
- assert(p);
-
- if (set_isempty(names) && strv_isempty(namesv)) {
- allow = policy_check_one_recv(p, uid, gid, message_type, NULL, path, interface, member);
- } else {
- SET_FOREACH(n, names, i) {
- last = n;
- allow = policy_check_one_recv(p, uid, gid, message_type, n, path, interface, member);
- if (allow)
- break;
- }
- if (!allow) {
- STRV_FOREACH(nv, namesv) {
- last = *nv;
- allow = policy_check_one_recv(p, uid, gid, message_type, *nv, path, interface, member);
- if (allow)
- break;
- }
- }
- }
-
- log_full(LOG_AUTH | (!allow ? LOG_WARNING : LOG_DEBUG),
- "Receive permission check %s for uid=" UID_FMT " gid=" GID_FMT" message=%s name=%s path=%s interface=%s member=%s: %s",
- dbus_to_kernel ? "dbus-1 to kernel" : "kernel to dbus-1", uid, gid, bus_message_type_to_string(message_type), strna(last),
- strna(path), strna(interface), strna(member), allow ? "ALLOW" : "DENY");
-
- return allow;
-}
-
-bool policy_check_one_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,
- };
-
- assert(p);
-
- return policy_check(p, &filter) == ALLOW;
-}
-
-bool policy_check_send(Policy *p,
- uid_t uid,
- gid_t gid,
- int message_type,
- Set *names,
- char **namesv,
- const char *path,
- const char *interface,
- const char *member,
- bool dbus_to_kernel,
- char **out_used_name) {
-
- char *n, **nv, *last = NULL;
- bool allow = false;
- Iterator i;
-
- assert(p);
-
- if (set_isempty(names) && strv_isempty(namesv)) {
- allow = policy_check_one_send(p, uid, gid, message_type, NULL, path, interface, member);
- } else {
- SET_FOREACH(n, names, i) {
- last = n;
- allow = policy_check_one_send(p, uid, gid, message_type, n, path, interface, member);
- if (allow)
- break;
- }
- if (!allow) {
- STRV_FOREACH(nv, namesv) {
- last = *nv;
- allow = policy_check_one_send(p, uid, gid, message_type, *nv, path, interface, member);
- if (allow)
- break;
- }
- }
- }
-
- if (out_used_name)
- *out_used_name = last;
-
- log_full(LOG_AUTH | (!allow ? LOG_WARNING : LOG_DEBUG),
- "Send permission check %s for uid=" UID_FMT " gid=" GID_FMT" message=%s name=%s path=%s interface=%s member=%s: %s",
- dbus_to_kernel ? "dbus-1 to kernel" : "kernel to dbus-1", uid, gid, bus_message_type_to_string(message_type), strna(last),
- strna(path), strna(interface), strna(member), allow ? "ALLOW" : "DENY");
-
- return 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 ((i = p->on_console_items)) {
- LIST_REMOVE(items, p->on_console_items, i);
- policy_item_free(i);
- }
-
- while ((i = p->no_console_items)) {
- LIST_REMOVE(items, p->no_console_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 ("UID_FMT")\n",
- prefix, strna(user), i->uid);
- }
-
- if (i->gid_valid) {
- _cleanup_free_ char *group;
-
- group = gid_to_name(i->gid);
-
- printf("%sGroup: %s ("GID_FMT")\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 " UID_FMT ":\n", draw_special_char(DRAW_ARROW), PTR_TO_UID(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 On-Console Items:\n", draw_special_char(DRAW_ARROW));
- dump_items(p->on_console_items, "\t");
-
- printf("%s No-Console Items:\n", draw_special_char(DRAW_ARROW));
- dump_items(p->no_console_items, "\t");
-
- printf("%s Mandatory Items:\n", draw_special_char(DRAW_ARROW));
- dump_items(p->mandatory_items, "\t");
-
- fflush(stdout);
-}
-
-int shared_policy_new(SharedPolicy **out) {
- SharedPolicy *sp;
- int r;
-
- sp = new0(SharedPolicy, 1);
- if (!sp)
- return log_oom();
-
- r = pthread_mutex_init(&sp->lock, NULL);
- if (r != 0) {
- r = log_error_errno(r, "Cannot initialize shared policy mutex: %m");
- goto exit_free;
- }
-
- r = pthread_rwlock_init(&sp->rwlock, NULL);
- if (r != 0) {
- r = log_error_errno(r, "Cannot initialize shared policy rwlock: %m");
- goto exit_mutex;
- }
-
- *out = sp;
- sp = NULL;
- return 0;
-
- /* pthread lock destruction is not fail-safe... meh! */
-exit_mutex:
- pthread_mutex_destroy(&sp->lock);
-exit_free:
- free(sp);
- return r;
-}
-
-SharedPolicy *shared_policy_free(SharedPolicy *sp) {
- if (!sp)
- return NULL;
-
- policy_free(sp->policy);
- pthread_rwlock_destroy(&sp->rwlock);
- pthread_mutex_destroy(&sp->lock);
- strv_free(sp->configuration);
- free(sp);
-
- return NULL;
-}
-
-static int shared_policy_reload_unlocked(SharedPolicy *sp, char **configuration) {
- Policy old, buffer = {};
- bool free_old;
- int r;
-
- assert(sp);
-
- r = policy_load(&buffer, configuration);
- if (r < 0)
- return log_error_errno(r, "Failed to load policy: %m");
-
- log_debug("Reloading configuration");
- /* policy_dump(&buffer); */
-
- pthread_rwlock_wrlock(&sp->rwlock);
- memcpy(&old, &sp->buffer, sizeof(old));
- memcpy(&sp->buffer, &buffer, sizeof(buffer));
- free_old = !!sp->policy;
- sp->policy = &sp->buffer;
- pthread_rwlock_unlock(&sp->rwlock);
-
- if (free_old)
- policy_free(&old);
-
- return 0;
-}
-
-int shared_policy_reload(SharedPolicy *sp) {
- int r;
-
- assert(sp);
-
- pthread_mutex_lock(&sp->lock);
- r = shared_policy_reload_unlocked(sp, sp->configuration);
- pthread_mutex_unlock(&sp->lock);
-
- return r;
-}
-
-int shared_policy_preload(SharedPolicy *sp, char **configuration) {
- _cleanup_strv_free_ char **conf = NULL;
- int r = 0;
-
- assert(sp);
-
- conf = strv_copy(configuration);
- if (!conf)
- return log_oom();
-
- pthread_mutex_lock(&sp->lock);
- if (!sp->policy) {
- r = shared_policy_reload_unlocked(sp, conf);
- if (r >= 0) {
- sp->configuration = conf;
- conf = NULL;
- }
- }
- pthread_mutex_unlock(&sp->lock);
-
- return r;
-}
-
-Policy *shared_policy_acquire(SharedPolicy *sp) {
- assert(sp);
-
- pthread_rwlock_rdlock(&sp->rwlock);
- if (sp->policy)
- return sp->policy;
- pthread_rwlock_unlock(&sp->rwlock);
-
- return NULL;
-}
-
-void shared_policy_release(SharedPolicy *sp, Policy *p) {
- assert(sp);
- assert(!p || sp->policy == p);
-
- if (p)
- pthread_rwlock_unlock(&sp->rwlock);
-}
-
-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
deleted file mode 100644
index 3dcddaa048..0000000000
--- a/src/bus-proxyd/bus-xml-policy.h
+++ /dev/null
@@ -1,147 +0,0 @@
-#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 <http://www.gnu.org/licenses/>.
-***/
-
-#include <pthread.h>
-
-#include "hashmap.h"
-#include "list.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);
- LIST_HEAD(PolicyItem, on_console_items);
- LIST_HEAD(PolicyItem, no_console_items);
- Hashmap *user_items;
- Hashmap *group_items;
-} Policy;
-
-typedef struct SharedPolicy {
- char **configuration;
- pthread_mutex_t lock;
- pthread_rwlock_t rwlock;
- Policy buffer;
- Policy *policy;
-} SharedPolicy;
-
-/* 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_one_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_recv(Policy *p,
- uid_t uid,
- gid_t gid,
- int message_type,
- Set *names,
- char **namesv,
- const char *path,
- const char *interface,
- const char *member,
- bool dbus_to_kernel);
-bool policy_check_one_send(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,
- Set *names,
- char **namesv,
- const char *path,
- const char *interface,
- const char *member,
- bool dbus_to_kernel,
- char **out_used_name);
-
-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_;
-
-/* shared policy */
-
-int shared_policy_new(SharedPolicy **out);
-SharedPolicy *shared_policy_free(SharedPolicy *sp);
-
-int shared_policy_reload(SharedPolicy *sp);
-int shared_policy_preload(SharedPolicy *sp, char **configuration);
-Policy *shared_policy_acquire(SharedPolicy *sp);
-void shared_policy_release(SharedPolicy *sp, Policy *p);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(SharedPolicy*, shared_policy_free);
diff --git a/src/bus-proxyd/driver.c b/src/bus-proxyd/driver.c
deleted file mode 100644
index 1af5c310ea..0000000000
--- a/src/bus-proxyd/driver.c
+++ /dev/null
@@ -1,745 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Daniel Mack
- Copyright 2014 Kay Sievers
-
- 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <stddef.h>
-#include <string.h>
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "bus-internal.h"
-#include "bus-message.h"
-#include "bus-util.h"
-#include "driver.h"
-#include "env-util.h"
-#include "proxy.h"
-#include "set.h"
-#include "strv.h"
-#include "synthesize.h"
-#include "util.h"
-
-static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
- int r;
-
- assert(bus);
- assert(name);
- assert(_creds);
-
- r = sd_bus_get_name_creds(bus, name, mask, &c);
- if (r == -ESRCH || r == -ENXIO)
- return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
- if (r < 0)
- return r;
-
- *_creds = c;
- c = NULL;
-
- return 0;
-}
-
-static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
- const char *name;
- int r;
-
- assert(bus);
- assert(m);
- assert(_creds);
-
- r = sd_bus_message_read(m, "s", &name);
- if (r < 0)
- return r;
-
- return get_creds_by_name(bus, name, mask, _creds, error);
-}
-
-static int driver_activation(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- ProxyActivation *activation = userdata;
-
- /*
- * The org.freedesktop.DBus.Peer.Ping() call returned. We don't care
- * whether this succeeded, failed, was not implemented or timed out. We
- * cannot assume that the target reacts to this properly. Hence, just
- * send the reply to the activation request and be done.
- */
-
- m = activation->request; /* claim reference */
-
- --activation->proxy->n_activations;
- LIST_REMOVE(activations_by_proxy, activation->proxy->activations, activation);
- sd_bus_slot_unref(activation->slot);
- free(activation);
-
- return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
-}
-
-int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPolicy *sp, const struct ucred *ucred, Set *owned_names) {
- int r;
-
- assert(a);
- assert(b);
- assert(m);
-
- if (!a->is_kernel)
- return 0;
-
- if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
- return 0;
-
- /* The "Hello()" call is is handled in process_hello() */
-
- if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
-
- if (!sd_bus_message_has_signature(m, ""))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- return synthetic_reply_method_return(m, "s",
- "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
- "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
- "<node>\n"
- " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
- " <method name=\"Introspect\">\n"
- " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
- " </method>\n"
- " </interface>\n"
- " <interface name=\"org.freedesktop.DBus\">\n"
- " <method name=\"AddMatch\">\n"
- " <arg type=\"s\" direction=\"in\"/>\n"
- " </method>\n"
- " <method name=\"RemoveMatch\">\n"
- " <arg type=\"s\" direction=\"in\"/>\n"
- " </method>\n"
- " <method name=\"GetConnectionCredentials\">\n"
- " <arg type=\"s\" direction=\"in\"/>\n"
- " <arg type=\"a{sv}\" direction=\"out\"/>\n"
- " </method>\n"
- " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
- " <arg type=\"s\" direction=\"in\"/>\n"
- " <arg type=\"ay\" direction=\"out\"/>\n"
- " </method>\n"
- " <method name=\"GetConnectionUnixProcessID\">\n"
- " <arg type=\"s\" direction=\"in\"/>\n"
- " <arg type=\"u\" direction=\"out\"/>\n"
- " </method>\n"
- " <method name=\"GetConnectionUnixUser\">\n"
- " <arg type=\"s\" direction=\"in\"/>\n"
- " <arg type=\"u\" direction=\"out\"/>\n"
- " </method>\n"
- " <method name=\"GetId\">\n"
- " <arg type=\"s\" direction=\"out\"/>\n"
- " </method>\n"
- " <method name=\"GetNameOwner\">\n"
- " <arg type=\"s\" direction=\"in\"/>\n"
- " <arg type=\"s\" direction=\"out\"/>\n"
- " </method>\n"
- " <method name=\"Hello\">\n"
- " <arg type=\"s\" direction=\"out\"/>\n"
- " </method>\n"
- " <method name=\"ListActivatableNames\">\n"
- " <arg type=\"as\" direction=\"out\"/>\n"
- " </method>\n"
- " <method name=\"ListNames\">\n"
- " <arg type=\"as\" direction=\"out\"/>\n"
- " </method>\n"
- " <method name=\"ListQueuedOwners\">\n"
- " <arg type=\"s\" direction=\"in\"/>\n"
- " <arg type=\"as\" direction=\"out\"/>\n"
- " </method>\n"
- " <method name=\"NameHasOwner\">\n"
- " <arg type=\"s\" direction=\"in\"/>\n"
- " <arg type=\"b\" direction=\"out\"/>\n"
- " </method>\n"
- " <method name=\"ReleaseName\">\n"
- " <arg type=\"s\" direction=\"in\"/>\n"
- " <arg type=\"u\" direction=\"out\"/>\n"
- " </method>\n"
- " <method name=\"ReloadConfig\">\n"
- " </method>\n"
- " <method name=\"RequestName\">\n"
- " <arg type=\"s\" direction=\"in\"/>\n"
- " <arg type=\"u\" direction=\"in\"/>\n"
- " <arg type=\"u\" direction=\"out\"/>\n"
- " </method>\n"
- " <method name=\"StartServiceByName\">\n"
- " <arg type=\"s\" direction=\"in\"/>\n"
- " <arg type=\"u\" direction=\"in\"/>\n"
- " <arg type=\"u\" direction=\"out\"/>\n"
- " </method>\n"
- " <method name=\"UpdateActivationEnvironment\">\n"
- " <arg type=\"a{ss}\" direction=\"in\"/>\n"
- " </method>\n"
- " <signal name=\"NameAcquired\">\n"
- " <arg type=\"s\"/>\n"
- " </signal>\n"
- " <signal name=\"NameLost\">\n"
- " <arg type=\"s\"/>\n"
- " </signal>\n"
- " <signal name=\"NameOwnerChanged\">\n"
- " <arg type=\"s\"/>\n"
- " <arg type=\"s\"/>\n"
- " <arg type=\"s\"/>\n"
- " </signal>\n"
- " </interface>\n"
- "</node>\n");
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
- const char *match;
-
- if (!sd_bus_message_has_signature(m, "s"))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- r = sd_bus_message_read(m, "s", &match);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = sd_bus_add_match(a, NULL, match, proxy_match, p);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- return synthetic_reply_method_return(m, NULL);
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
- const char *match;
-
- if (!sd_bus_message_has_signature(m, "s"))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- r = sd_bus_message_read(m, "s", &match);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = bus_remove_match_by_string(a, match, NULL, NULL);
- if (r == 0)
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- return synthetic_reply_method_return(m, NULL);
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionCredentials")) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-
- if (!sd_bus_message_has_signature(m, "s"))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- r = get_creds_by_message(a, m, SD_BUS_CREDS_PID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, &error);
-
- r = sd_bus_message_new_method_return(m, &reply);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = sd_bus_message_open_container(reply, 'a', "{sv}");
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- /* Due to i.e. namespace translations some data might be missing */
-
- if (creds->mask & SD_BUS_CREDS_PID) {
- r = sd_bus_message_append(reply, "{sv}", "ProcessID", "u", (uint32_t) creds->pid);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
- }
-
- if (creds->mask & SD_BUS_CREDS_EUID) {
- r = sd_bus_message_append(reply, "{sv}", "UnixUserID", "u", (uint32_t) creds->euid);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
- }
-
- if (creds->mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
- r = sd_bus_message_open_container(reply, 'e', "sv");
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = sd_bus_message_append(reply, "s", "LinuxSecurityLabel");
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = sd_bus_message_open_container(reply, 'v', "ay");
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = sd_bus_message_append_array(reply, 'y', creds->label, strlen(creds->label));
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
- }
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- return synthetic_driver_send(m->bus, reply);
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-
- if (!sd_bus_message_has_signature(m, "s"))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, &error);
-
- if (!(creds->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
- return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL);
-
- r = sd_bus_message_new_method_return(m, &reply);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = sd_bus_message_append_array(reply, 'y', creds->label, strlen(creds->label));
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- return synthetic_driver_send(m->bus, reply);
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-
- if (!sd_bus_message_has_signature(m, "s"))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, &error);
-
- if (!(creds->mask & SD_BUS_CREDS_PID))
- return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL);
-
- return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-
- if (!sd_bus_message_has_signature(m, "s"))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- r = get_creds_by_message(a, m, SD_BUS_CREDS_EUID, &creds, &error);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, &error);
-
- if (!(creds->mask & SD_BUS_CREDS_EUID))
- return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL);
-
- return synthetic_reply_method_return(m, "u", (uint32_t) creds->euid);
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
- sd_id128_t server_id;
- char buf[SD_ID128_STRING_MAX];
-
- if (!sd_bus_message_has_signature(m, ""))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- r = sd_bus_get_bus_id(a, &server_id);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
- const char *name;
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-
- if (!sd_bus_message_has_signature(m, "s"))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- r = sd_bus_message_read(m, "s", &name);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- if (streq(name, "org.freedesktop.DBus"))
- return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
-
- r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, &error);
-
- if (!(creds->mask & SD_BUS_CREDS_UNIQUE_NAME))
- return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL);
-
- return synthetic_reply_method_return(m, "s", creds->unique_name);
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
- _cleanup_strv_free_ char **names = NULL;
-
- if (!sd_bus_message_has_signature(m, ""))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- r = sd_bus_list_names(a, NULL, &names);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- /* Let's sort the names list to make it stable */
- strv_sort(names);
-
- return synthetic_reply_method_return_strv(m, names);
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
- _cleanup_strv_free_ char **names = NULL;
-
- if (!sd_bus_message_has_signature(m, ""))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- r = sd_bus_list_names(a, &names, NULL);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = strv_extend(&names, "org.freedesktop.DBus");
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- /* Let's sort the names list to make it stable */
- strv_sort(names);
-
- return synthetic_reply_method_return_strv(m, names);
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
- struct kdbus_cmd_list cmd = {
- .flags = KDBUS_LIST_QUEUED,
- .size = sizeof(cmd),
- };
- struct kdbus_info *name_list, *name;
- _cleanup_strv_free_ char **owners = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- char *arg0;
- int err = 0;
-
- if (!sd_bus_message_has_signature(m, "s"))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- r = sd_bus_message_read(m, "s", &arg0);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = sd_bus_get_name_creds(a, arg0, 0, NULL);
- if (r == -ESRCH || r == -ENXIO) {
- sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0);
- return synthetic_reply_method_errno(m, r, &error);
- }
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = ioctl(a->input_fd, KDBUS_CMD_LIST, &cmd);
- if (r < 0)
- return synthetic_reply_method_errno(m, -errno, NULL);
-
- name_list = (struct kdbus_info *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
-
- KDBUS_FOREACH(name, name_list, cmd.list_size) {
- struct kdbus_item *item;
- char *n;
-
- KDBUS_ITEM_FOREACH(item, name, items) {
- if (item->type == KDBUS_ITEM_OWNED_NAME) {
- if (!streq_ptr(item->name.name, arg0))
- continue;
-
- if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) {
- err = -ENOMEM;
- break;
- }
-
- r = strv_consume(&owners, n);
- if (r < 0) {
- err = r;
- break;
- }
- }
- }
-
- if (err < 0)
- break;
- }
-
- r = bus_kernel_cmd_free(a, cmd.offset);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- if (err < 0)
- return synthetic_reply_method_errno(m, err, NULL);
-
- return synthetic_reply_method_return_strv(m, owners);
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
- const char *name;
-
- if (!sd_bus_message_has_signature(m, "s"))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- r = sd_bus_message_read(m, "s", &name);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- if (streq(name, "org.freedesktop.DBus"))
- return synthetic_reply_method_return(m, "b", true);
-
- r = sd_bus_get_name_creds(a, name, 0, NULL);
- if (r < 0 && r != -ESRCH && r != -ENXIO)
- return synthetic_reply_method_errno(m, r, NULL);
-
- return synthetic_reply_method_return(m, "b", r >= 0);
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
- const char *name;
-
- if (!sd_bus_message_has_signature(m, "s"))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- r = sd_bus_message_read(m, "s", &name);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = sd_bus_release_name(a, name);
- if (r < 0) {
- if (r == -ESRCH)
- return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
- if (r == -EADDRINUSE)
- return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
-
- return synthetic_reply_method_errno(m, r, NULL);
- }
-
- set_remove(owned_names, (char*) name);
-
- return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
- if (!sd_bus_message_has_signature(m, ""))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- r = shared_policy_reload(sp);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- return synthetic_reply_method_return(m, NULL);
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
- const char *name;
- uint32_t flags, param;
- bool in_queue;
-
- if (!sd_bus_message_has_signature(m, "su"))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- r = sd_bus_message_read(m, "su", &name, &flags);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- if (sp) {
- Policy *policy;
- bool denied;
-
- policy = shared_policy_acquire(sp);
- denied = !policy_check_own(policy, ucred->uid, ucred->gid, name);
- shared_policy_release(sp, policy);
- if (denied)
- return synthetic_reply_method_errno(m, -EPERM, NULL);
- }
-
- if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
- return synthetic_reply_method_errno(m, -EINVAL, NULL);
-
- param = 0;
- if (flags & BUS_NAME_ALLOW_REPLACEMENT)
- param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
- if (flags & BUS_NAME_REPLACE_EXISTING)
- param |= SD_BUS_NAME_REPLACE_EXISTING;
- if (!(flags & BUS_NAME_DO_NOT_QUEUE))
- param |= SD_BUS_NAME_QUEUE;
-
- r = set_put_strdup(owned_names, name);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = sd_bus_request_name(a, name, param);
- if (r < 0) {
- if (r == -EALREADY)
- return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
-
- set_remove(owned_names, (char*) name);
-
- if (r == -EEXIST)
- return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
- return synthetic_reply_method_errno(m, r, NULL);
- }
-
- in_queue = (r == 0);
-
- if (in_queue)
- return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
-
- return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *msg = NULL;
- ProxyActivation *activation;
- const char *name;
- uint64_t cookie;
- uint32_t flags;
-
- if (!sd_bus_message_has_signature(m, "su"))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- r = sd_bus_message_read(m, "su", &name, &flags);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- if (flags != 0)
- return synthetic_reply_method_errno(m, -EINVAL, NULL);
-
- r = sd_bus_get_name_creds(a, name, 0, NULL);
- if (r >= 0 || streq(name, "org.freedesktop.DBus"))
- return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
- if (r != -ESRCH)
- return synthetic_reply_method_errno(m, r, NULL);
-
- if (p->n_activations >= PROXY_ACTIVATIONS_MAX)
- return synthetic_reply_method_errno(m, -EMFILE, NULL);
-
- r = sd_bus_message_get_cookie(m, &cookie);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = sd_bus_message_new_method_call(a,
- &msg,
- name,
- "/",
- "org.freedesktop.DBus.Peer",
- "Ping");
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = bus_message_seal(msg, cookie, BUS_DEFAULT_TIMEOUT);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- activation = new0(ProxyActivation, 1);
- if (!activation)
- return synthetic_reply_method_errno(m, -ENOMEM, NULL);
-
- r = sd_bus_call_async(a,
- &activation->slot,
- msg,
- driver_activation,
- activation,
- 0);
- if (r < 0) {
- free(activation);
- return synthetic_reply_method_errno(m, r, NULL);
- }
-
- activation->proxy = p;
- activation->request = sd_bus_message_ref(m);
- LIST_PREPEND(activations_by_proxy, p->activations, activation);
- ++p->n_activations;
- return 1;
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *msg = NULL;
- _cleanup_strv_free_ char **args = NULL;
-
- if (!sd_bus_message_has_signature(m, "a{ss}"))
- return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
- _cleanup_free_ char *s = NULL;
- const char *key;
- const char *value;
-
- r = sd_bus_message_read(m, "ss", &key, &value);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- s = strjoin(key, "=", value, NULL);
- if (!s)
- return synthetic_reply_method_errno(m, -ENOMEM, NULL);
-
- if (!env_assignment_is_valid(s)) {
- log_warning("UpdateActivationEnvironment() called with invalid assignment, discarding: %s", s);
- } else {
- r = strv_extend(&args, s);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
- }
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
- }
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- if (strv_isempty(args)) /* nothing to do? */
- return synthetic_reply_method_return(m, NULL);
-
- r = sd_bus_message_new_method_call(
- a,
- &msg,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "SetEnvironment");
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = sd_bus_message_append_strv(msg, args);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- r = sd_bus_call(a, msg, 0, NULL, NULL);
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
-
- return synthetic_reply_method_return(m, NULL);
-
- } else {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-
- r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
-
- return synthetic_reply_method_errno(m, r, &error);
- }
-}
diff --git a/src/bus-proxyd/driver.h b/src/bus-proxyd/driver.h
deleted file mode 100644
index 1630cdc7b9..0000000000
--- a/src/bus-proxyd/driver.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
-
-#include "bus-xml-policy.h"
-#include "proxy.h"
-
-int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPolicy *sp, const struct ucred *ucred, Set *owned_names);
diff --git a/src/bus-proxyd/proxy.c b/src/bus-proxyd/proxy.c
deleted file mode 100644
index 907d93d4c7..0000000000
--- a/src/bus-proxyd/proxy.c
+++ /dev/null
@@ -1,953 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Daniel Mack
- Copyright 2014 Kay Sievers
- Copyright 2014 David Herrmann
-
- 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <poll.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-
-#include "sd-bus.h"
-#include "sd-daemon.h"
-
-#include "alloc-util.h"
-#include "bus-control.h"
-#include "bus-internal.h"
-#include "bus-message.h"
-#include "bus-util.h"
-#include "bus-xml-policy.h"
-#include "driver.h"
-#include "fd-util.h"
-#include "formats-util.h"
-#include "log.h"
-#include "proxy.h"
-#include "set.h"
-#include "strv.h"
-#include "synthesize.h"
-#include "user-util.h"
-#include "util.h"
-
-static int proxy_create_destination(Proxy *p, const char *destination, const char *local_sec, bool negotiate_fds) {
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *b = NULL;
- int r;
-
- r = sd_bus_new(&b);
- if (r < 0)
- return log_error_errno(r, "Failed to allocate bus: %m");
-
- r = sd_bus_set_description(b, "sd-proxy");
- if (r < 0)
- return log_error_errno(r, "Failed to set bus name: %m");
-
- r = sd_bus_set_address(b, destination);
- if (r < 0)
- return log_error_errno(r, "Failed to set address to connect to: %m");
-
- r = sd_bus_negotiate_fds(b, negotiate_fds);
- if (r < 0)
- return log_error_errno(r, "Failed to set FD negotiation: %m");
-
- r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT);
- if (r < 0)
- return log_error_errno(r, "Failed to set credential negotiation: %m");
-
- if (p->local_creds.pid > 0) {
- b->fake_pids.pid = p->local_creds.pid;
- b->fake_pids_valid = true;
-
- b->fake_creds.uid = UID_INVALID;
- b->fake_creds.euid = p->local_creds.uid;
- b->fake_creds.suid = UID_INVALID;
- b->fake_creds.fsuid = UID_INVALID;
- b->fake_creds.gid = GID_INVALID;
- b->fake_creds.egid = p->local_creds.gid;
- b->fake_creds.sgid = GID_INVALID;
- b->fake_creds.fsgid = GID_INVALID;
- b->fake_creds_valid = true;
- }
-
- if (local_sec) {
- b->fake_label = strdup(local_sec);
- if (!b->fake_label)
- return log_oom();
- }
-
- b->manual_peer_interface = true;
-
- r = sd_bus_start(b);
- if (r < 0)
- return log_error_errno(r, "Failed to start bus client: %m");
-
- p->destination_bus = b;
- b = NULL;
- return 0;
-}
-
-static int proxy_create_local(Proxy *p, bool negotiate_fds) {
- sd_id128_t server_id;
- sd_bus *b;
- int r;
-
- r = sd_bus_new(&b);
- if (r < 0)
- return log_error_errno(r, "Failed to allocate bus: %m");
-
- r = sd_bus_set_fd(b, p->local_in, p->local_out);
- if (r < 0) {
- sd_bus_unref(b);
- return log_error_errno(r, "Failed to set fds: %m");
- }
-
- /* The fds are now owned by the bus, and we indicate that by
- * storing the bus object in the proxy object. */
- p->local_bus = b;
-
- r = sd_bus_get_bus_id(p->destination_bus, &server_id);
- if (r < 0)
- return log_error_errno(r, "Failed to get server ID: %m");
-
- r = sd_bus_set_server(b, 1, server_id);
- if (r < 0)
- return log_error_errno(r, "Failed to set server mode: %m");
-
- r = sd_bus_negotiate_fds(b, negotiate_fds);
- if (r < 0)
- return log_error_errno(r, "Failed to set FD negotiation: %m");
-
- r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT);
- if (r < 0)
- return log_error_errno(r, "Failed to set credential negotiation: %m");
-
- r = sd_bus_set_anonymous(b, true);
- if (r < 0)
- return log_error_errno(r, "Failed to set anonymous authentication: %m");
-
- b->manual_peer_interface = true;
-
- r = sd_bus_start(b);
- if (r < 0)
- return log_error_errno(r, "Failed to start bus client: %m");
-
- return 0;
-}
-
-static int proxy_match_synthetic(sd_bus_message *m, void *userdata, sd_bus_error *error) {
- Proxy *p = userdata;
-
- p->synthetic_matched = true;
- return 0; /* make sure to continue processing it in further handlers */
-}
-
-/*
- * We always need NameOwnerChanged so we can synthesize NameLost and
- * NameAcquired. Furthermore, dbus-1 always passes unicast-signals through, so
- * subscribe unconditionally.
- */
-static int proxy_prepare_matches(Proxy *p) {
- _cleanup_free_ char *match = NULL;
- const char *unique;
- int r;
-
- if (!p->destination_bus->is_kernel)
- return 0;
-
- r = sd_bus_get_unique_name(p->destination_bus, &unique);
- if (r < 0)
- return log_error_errno(r, "Failed to get unique name: %m");
-
- match = strjoin("type='signal',"
- "sender='org.freedesktop.DBus',"
- "path='/org/freedesktop/DBus',"
- "interface='org.freedesktop.DBus',"
- "member='NameOwnerChanged',"
- "arg1='",
- unique,
- "'",
- NULL);
- if (!match)
- return log_oom();
-
- r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
- if (r < 0)
- return log_error_errno(r, "Failed to add match for NameLost: %m");
-
- free(match);
- match = strjoin("type='signal',"
- "sender='org.freedesktop.DBus',"
- "path='/org/freedesktop/DBus',"
- "interface='org.freedesktop.DBus',"
- "member='NameOwnerChanged',"
- "arg2='",
- unique,
- "'",
- NULL);
- if (!match)
- return log_oom();
-
- r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
- if (r < 0)
- return log_error_errno(r, "Failed to add match for NameAcquired: %m");
-
- free(match);
- match = strjoin("type='signal',"
- "destination='",
- unique,
- "'",
- NULL);
- if (!match)
- return log_oom();
-
- r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
- if (r < 0)
- log_error_errno(r, "Failed to add match for directed signals: %m");
- /* FIXME: temporarily ignore error to support older kdbus versions */
-
- return 0;
-}
-
-int proxy_new(Proxy **out, int in_fd, int out_fd, const char *destination) {
- _cleanup_(proxy_freep) Proxy *p = NULL;
- _cleanup_free_ char *local_sec = NULL;
- bool is_unix;
- int r;
-
- /* This takes possession/destroys the file descriptors passed
- * in even on failure. The caller should hence forget about
- * the fds in all cases after calling this function and not
- * close them. */
-
- p = new0(Proxy, 1);
- if (!p) {
- safe_close(in_fd);
- safe_close(out_fd);
- return log_oom();
- }
-
- p->local_in = in_fd;
- p->local_out = out_fd;
-
- p->owned_names = set_new(&string_hash_ops);
- if (!p->owned_names)
- return log_oom();
-
- is_unix = sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
- sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
-
- if (is_unix) {
- (void) getpeercred(in_fd, &p->local_creds);
- (void) getpeersec(in_fd, &local_sec);
- }
-
- r = proxy_create_destination(p, destination, local_sec, is_unix);
- if (r < 0)
- return r;
-
- r = proxy_create_local(p, is_unix);
- if (r < 0)
- return r;
-
- r = proxy_prepare_matches(p);
- if (r < 0)
- return r;
-
- *out = p;
- p = NULL;
-
- return 0;
-}
-
-Proxy *proxy_free(Proxy *p) {
- ProxyActivation *activation;
-
- if (!p)
- return NULL;
-
- while ((activation = p->activations)) {
- LIST_REMOVE(activations_by_proxy, p->activations, activation);
- sd_bus_message_unref(activation->request);
- sd_bus_slot_unref(activation->slot);
- free(activation);
- }
-
- if (p->local_bus)
- sd_bus_flush_close_unref(p->local_bus);
- else {
- safe_close(p->local_in);
- if (p->local_out != p->local_in)
- safe_close(p->local_out);
- }
-
- sd_bus_flush_close_unref(p->destination_bus);
- set_free_free(p->owned_names);
- free(p);
-
- return NULL;
-}
-
-int proxy_set_policy(Proxy *p, SharedPolicy *sp, char **configuration) {
- _cleanup_strv_free_ char **strv = NULL;
- Policy *policy;
- int r;
-
- assert(p);
- assert(sp);
-
- /* no need to load legacy policy if destination is not kdbus */
- if (!p->destination_bus->is_kernel)
- return 0;
-
- p->policy = sp;
-
- policy = shared_policy_acquire(sp);
- if (policy) {
- /* policy already pre-loaded */
- shared_policy_release(sp, policy);
- return 0;
- }
-
- if (!configuration) {
- const char *scope;
-
- r = sd_bus_get_scope(p->destination_bus, &scope);
- if (r < 0)
- return log_error_errno(r, "Couldn't determine bus scope: %m");
-
- if (streq(scope, "system"))
- strv = strv_new("/usr/share/dbus-1/system.conf",
- "/etc/dbus-1/system.conf",
- "/usr/share/dbus-1/system.d/",
- "/etc/dbus-1/system.d/",
- "/etc/dbus-1/system-local.conf",
- NULL);
- else if (streq(scope, "user"))
- strv = strv_new("/usr/share/dbus-1/session.conf",
- "/etc/dbus-1/session.conf",
- "/usr/share/dbus-1/session.d/",
- "/etc/dbus-1/session.d/",
- "/etc/dbus-1/session-local.conf",
- NULL);
- else
- return log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope);
-
- if (!strv)
- return log_oom();
-
- configuration = strv;
- }
-
- return shared_policy_preload(sp, configuration);
-}
-
-int proxy_hello_policy(Proxy *p, uid_t original_uid) {
- Policy *policy;
- int r = 0;
-
- assert(p);
-
- if (!p->policy)
- return 0;
-
- policy = shared_policy_acquire(p->policy);
-
- if (p->local_creds.uid == original_uid)
- log_debug("Permitting access, since bus owner matches bus client.");
- else if (policy_check_hello(policy, p->local_creds.uid, p->local_creds.gid))
- log_debug("Permitting access due to XML policy.");
- else
- r = log_error_errno(EPERM, "Policy denied connection.");
-
- shared_policy_release(p->policy, policy);
-
- return r;
-}
-
-static int proxy_wait(Proxy *p) {
- uint64_t timeout_destination, timeout_local, t;
- int events_destination, events_local, fd;
- struct timespec _ts, *ts;
- struct pollfd *pollfd;
- int r;
-
- assert(p);
-
- fd = sd_bus_get_fd(p->destination_bus);
- if (fd < 0)
- return log_error_errno(fd, "Failed to get fd: %m");
-
- events_destination = sd_bus_get_events(p->destination_bus);
- if (events_destination < 0)
- return log_error_errno(events_destination, "Failed to get events mask: %m");
-
- r = sd_bus_get_timeout(p->destination_bus, &timeout_destination);
- if (r < 0)
- return log_error_errno(r, "Failed to get timeout: %m");
-
- events_local = sd_bus_get_events(p->local_bus);
- if (events_local < 0)
- return log_error_errno(events_local, "Failed to get events mask: %m");
-
- r = sd_bus_get_timeout(p->local_bus, &timeout_local);
- if (r < 0)
- return log_error_errno(r, "Failed to get timeout: %m");
-
- t = timeout_destination;
- if (t == (uint64_t) -1 || (timeout_local != (uint64_t) -1 && timeout_local < timeout_destination))
- t = timeout_local;
-
- if (t == (uint64_t) -1)
- ts = NULL;
- else {
- usec_t nw;
-
- nw = now(CLOCK_MONOTONIC);
- if (t > nw)
- t -= nw;
- else
- t = 0;
-
- ts = timespec_store(&_ts, t);
- }
-
- pollfd = (struct pollfd[3]) {
- { .fd = fd, .events = events_destination, },
- { .fd = p->local_in, .events = events_local & POLLIN, },
- { .fd = p->local_out, .events = events_local & POLLOUT, },
- };
-
- r = ppoll(pollfd, 3, ts, NULL);
- if (r < 0)
- return log_error_errno(errno, "ppoll() failed: %m");
-
- return 0;
-}
-
-static int handle_policy_error(sd_bus_message *m, int r) {
- if (r == -ESRCH || r == -ENXIO)
- return synthetic_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination);
-
- return r;
-}
-
-static int process_policy_unlocked(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
- int r;
-
- assert(from);
- assert(to);
- assert(m);
-
- if (!policy)
- return 0;
-
- /*
- * dbus-1 distinguishes expected and non-expected replies by tracking
- * method-calls and timeouts. By default, DENY rules are *NEVER* applied
- * on expected replies, unless explicitly specified. But we dont track
- * method-calls, thus, we cannot know whether a reply is expected.
- * Fortunately, the kdbus forbids non-expected replies, so we can safely
- * ignore any policy on those and let the kernel deal with it.
- *
- * TODO: To be correct, we should only ignore policy-tags that are
- * applied on non-expected replies. However, so far we don't parse those
- * tags so we let everything pass. I haven't seen a DENY policy tag on
- * expected-replies, ever, so don't bother..
- */
- if (m->reply_cookie > 0)
- return 0;
-
- if (from->is_kernel) {
- uid_t sender_uid = UID_INVALID;
- gid_t sender_gid = GID_INVALID;
- char **sender_names = NULL;
-
- /* Driver messages are always OK */
- if (streq_ptr(m->sender, "org.freedesktop.DBus"))
- return 0;
-
- /* The message came from the kernel, and is sent to our legacy client. */
- (void) sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
-
- (void) sd_bus_creds_get_euid(&m->creds, &sender_uid);
- (void) sd_bus_creds_get_egid(&m->creds, &sender_gid);
-
- if (sender_uid == UID_INVALID || sender_gid == GID_INVALID) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *sender_creds = NULL;
-
- /* If the message came from another legacy
- * client, then the message creds will be
- * missing, simply because on legacy clients
- * per-message creds were unknown. In this
- * case, query the creds of the peer
- * instead. */
-
- r = bus_get_name_creds_kdbus(from, m->sender, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID, true, &sender_creds);
- if (r < 0)
- return handle_policy_error(m, r);
-
- (void) sd_bus_creds_get_euid(sender_creds, &sender_uid);
- (void) sd_bus_creds_get_egid(sender_creds, &sender_gid);
- }
-
- /* First check whether the sender can send the message to our name */
- if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, false, NULL) &&
- policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, sender_names, m->path, m->interface, m->member, false))
- return 0;
-
- /* Return an error back to the caller */
- if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
- return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
-
- /* Return 1, indicating that the message shall not be processed any further */
- return 1;
- }
-
- if (to->is_kernel) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *destination_creds = NULL;
- uid_t destination_uid = UID_INVALID;
- gid_t destination_gid = GID_INVALID;
- const char *destination_unique = NULL;
- char **destination_names = NULL;
- char *n;
-
- /* Driver messages are always OK */
- if (streq_ptr(m->destination, "org.freedesktop.DBus"))
- return 0;
-
- /* The message came from the legacy client, and is sent to kdbus. */
- if (m->destination) {
- r = bus_get_name_creds_kdbus(to, m->destination,
- SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
- SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID,
- true, &destination_creds);
- if (r < 0)
- return handle_policy_error(m, r);
-
- r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
- if (r < 0)
- return handle_policy_error(m, r);
-
- (void) sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
-
- (void) sd_bus_creds_get_euid(destination_creds, &destination_uid);
- (void) sd_bus_creds_get_egid(destination_creds, &destination_gid);
- }
-
- /* First check if we (the sender) can send to this name */
- if (sd_bus_message_is_signal(m, NULL, NULL)) {
- /* If we forward a signal from dbus-1 to kdbus, we have
- * no idea who the recipient is. Therefore, we cannot
- * apply any dbus-1 policies that match on receiver
- * credentials. We know sd-bus always sets
- * KDBUS_MSG_SIGNAL, so the kernel applies policies to
- * the message. Therefore, skip policy checks in this
- * case. */
- return 0;
- } else if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, destination_names, m->path, m->interface, m->member, true, &n)) {
- if (n) {
- /* If we made a receiver decision, then remember which
- * name's policy we used, and to which unique ID it
- * mapped when we made the decision. Then, let's pass
- * this to the kernel when sending the message, so that
- * it refuses the operation should the name and unique
- * ID not map to each other anymore. */
-
- r = free_and_strdup(&m->destination_ptr, n);
- if (r < 0)
- return r;
-
- r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
- if (r < 0)
- return r;
- }
-
- if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, true))
- return 0;
- }
-
- /* Return an error back to the caller */
- if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
- return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
-
- /* Return 1, indicating that the message shall not be processed any further */
- return 1;
- }
-
- return 0;
-}
-
-static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, SharedPolicy *sp, const struct ucred *our_ucred, Set *owned_names) {
- Policy *policy;
- int r;
-
- assert(sp);
-
- policy = shared_policy_acquire(sp);
- r = process_policy_unlocked(from, to, m, policy, our_ucred, owned_names);
- shared_policy_release(sp, policy);
-
- return r;
-}
-
-static int process_hello(Proxy *p, sd_bus_message *m) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
- bool is_hello;
- int r;
-
- assert(p);
- assert(m);
-
- /* As reaction to hello we need to respond with two messages:
- * the callback reply and the NameAcquired for the unique
- * name, since hello is otherwise obsolete on kdbus. */
-
- is_hello =
- sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
- streq_ptr(m->destination, "org.freedesktop.DBus");
-
- if (!is_hello) {
- if (p->got_hello)
- return 0;
-
- return log_error_errno(EIO, "First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
- }
-
- if (p->got_hello)
- return log_error_errno(EIO, "Got duplicate hello, aborting.");
-
- p->got_hello = true;
-
- if (!p->destination_bus->is_kernel)
- return 0;
-
- r = sd_bus_message_new_method_return(m, &n);
- if (r < 0)
- return log_error_errno(r, "Failed to generate HELLO reply: %m");
-
- r = sd_bus_message_append(n, "s", p->destination_bus->unique_name);
- if (r < 0)
- return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
-
- r = bus_message_append_sender(n, "org.freedesktop.DBus");
- if (r < 0)
- return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
-
- r = bus_seal_synthetic_message(p->local_bus, n);
- if (r < 0)
- return log_error_errno(r, "Failed to seal HELLO reply: %m");
-
- r = sd_bus_send(p->local_bus, n, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to send HELLO reply: %m");
-
- n = sd_bus_message_unref(n);
- r = sd_bus_message_new_signal(
- p->local_bus,
- &n,
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "NameAcquired");
- if (r < 0)
- return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
-
- r = sd_bus_message_append(n, "s", p->destination_bus->unique_name);
- if (r < 0)
- return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
-
- r = bus_message_append_sender(n, "org.freedesktop.DBus");
- if (r < 0)
- return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
-
- r = sd_bus_message_set_destination(n, p->destination_bus->unique_name);
- if (r < 0)
- return log_error_errno(r, "Failed to set destination for NameAcquired message: %m");
-
- r = bus_seal_synthetic_message(p->local_bus, n);
- if (r < 0)
- return log_error_errno(r, "Failed to seal NameAcquired message: %m");
-
- r = sd_bus_send(p->local_bus, n, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to send NameAcquired message: %m");
-
- return 1;
-}
-
-static int patch_sender(sd_bus *a, sd_bus_message *m) {
- char **well_known = NULL;
- sd_bus_creds *c;
- int r;
-
- assert(a);
- assert(m);
-
- if (!a->is_kernel)
- return 0;
-
- /* We will change the sender of messages from the bus driver
- * so that they originate from the bus driver. This is a
- * speciality originating from dbus1, where the bus driver did
- * not have a unique id, but only the well-known name. */
-
- c = sd_bus_message_get_creds(m);
- if (!c)
- return 0;
-
- r = sd_bus_creds_get_well_known_names(c, &well_known);
- if (r < 0)
- return r;
-
- if (strv_contains(well_known, "org.freedesktop.DBus"))
- m->sender = "org.freedesktop.DBus";
-
- return 0;
-}
-
-static int proxy_process_destination_to_local(Proxy *p) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- bool matched, matched_synthetic;
- int r;
-
- assert(p);
-
- /*
- * Usually, we would just take any message that the bus passes to us
- * and forward it to the local connection. However, there are actually
- * applications that fail if they receive broadcasts that they didn't
- * subscribe to. Therefore, we actually emulate a real broadcast
- * matching here, and discard any broadcasts that weren't matched. Our
- * match-handlers remembers whether a message was matched by any rule,
- * by marking it in @p->message_matched.
- */
-
- r = sd_bus_process(p->destination_bus, &m);
-
- matched = p->message_matched;
- matched_synthetic = p->synthetic_matched;
- p->message_matched = false;
- p->synthetic_matched = false;
-
- if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
- return r;
- if (r < 0) {
- log_error_errno(r, "Failed to process destination bus: %m");
- return r;
- }
- if (r == 0)
- return 0;
- if (!m)
- return 1;
-
- /* We officially got EOF, let's quit */
- if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
- return -ECONNRESET;
-
- r = synthesize_name_acquired(p, p->destination_bus, p->local_bus, m);
- if (r == -ECONNRESET || r == -ENOTCONN)
- return r;
- if (r < 0)
- return log_error_errno(r, "Failed to synthesize message: %m");
-
- /* discard broadcasts that were not matched by any MATCH rule */
- if (!matched && !sd_bus_message_get_destination(m)) {
- if (!matched_synthetic)
- log_debug("Dropped unmatched broadcast: uid=" UID_FMT " gid=" GID_FMT " pid=" PID_FMT " message=%s path=%s interface=%s member=%s sender=%s destination=%s",
- p->local_creds.uid, p->local_creds.gid, p->local_creds.pid, bus_message_type_to_string(m->header->type),
- strna(m->path), strna(m->interface), strna(m->member), strna(m->sender), strna(m->destination));
- return 1;
- }
-
- patch_sender(p->destination_bus, m);
-
- if (p->policy) {
- r = process_policy(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
- if (r == -ECONNRESET || r == -ENOTCONN)
- return r;
- if (r < 0)
- return log_error_errno(r, "Failed to process policy: %m");
- if (r > 0)
- return 1;
- }
-
- r = sd_bus_send(p->local_bus, m, NULL);
- if (r < 0) {
- if (r == -ECONNRESET || r == -ENOTCONN)
- return r;
-
- /* If the peer tries to send a reply and it is
- * rejected with EBADSLT by the kernel, we ignore the
- * error. This catches cases where the original
- * method-call didn't had EXPECT_REPLY set, but the
- * proxy-peer still sends a reply. This is allowed in
- * dbus1, but not in kdbus. We don't want to track
- * reply-windows in the proxy, so we simply ignore
- * EBADSLT for all replies. The only downside is, that
- * callers are no longer notified if their replies are
- * dropped. However, this is equivalent to the
- * caller's timeout to expire, so this should be
- * acceptable. Nobody sane sends replies without a
- * matching method-call, so nobody should care. */
-
- /* FIXME: remove -EPERM when kdbus is updated */
- if ((r == -EPERM || r == -EBADSLT) && m->reply_cookie > 0)
- return 1;
-
- /* Return the error to the client, if we can */
- synthetic_reply_method_errnof(m, r, "Failed to forward message we got from destination: %m");
- if (r == -ENOBUFS) {
- /* if local dbus1 peer does not dispatch its queue, warn only once */
- if (!p->queue_overflow)
- log_error("Dropped messages due to queue overflow of local peer (pid: "PID_FMT" uid: "UID_FMT")", p->local_creds.pid, p->local_creds.uid);
- p->queue_overflow = true;
- } else
- log_error_errno(r,
- "Failed to forward message we got from destination: uid=" UID_FMT " gid=" GID_FMT" message=%s destination=%s path=%s interface=%s member=%s: %m",
- p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type),
- strna(m->destination), strna(m->path), strna(m->interface), strna(m->member));
-
- return 1;
- }
-
- p->queue_overflow = false;
- return 1;
-}
-
-static int proxy_process_local_to_destination(Proxy *p) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- int r;
-
- assert(p);
-
- r = sd_bus_process(p->local_bus, &m);
- if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
- return r;
- if (r < 0) {
- log_error_errno(r, "Failed to process local bus: %m");
- return r;
- }
- if (r == 0)
- return 0;
- if (!m)
- return 1;
-
- /* We officially got EOF, let's quit */
- if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
- return -ECONNRESET;
-
- r = process_hello(p, m);
- if (r == -ECONNRESET || r == -ENOTCONN)
- return r;
- if (r < 0)
- return log_error_errno(r, "Failed to process HELLO: %m");
- if (r > 0)
- return 1;
-
- r = bus_proxy_process_driver(p, p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
- if (r == -ECONNRESET || r == -ENOTCONN)
- return r;
- if (r < 0)
- return log_error_errno(r, "Failed to process driver calls: %m");
- if (r > 0)
- return 1;
-
- for (;;) {
- if (p->policy) {
- r = process_policy(p->local_bus, p->destination_bus, m, p->policy, &p->local_creds, p->owned_names);
- if (r == -ECONNRESET || r == -ENOTCONN)
- return r;
- if (r < 0)
- return log_error_errno(r, "Failed to process policy: %m");
- if (r > 0)
- return 1;
- }
-
- r = sd_bus_send(p->destination_bus, m, NULL);
- if (r < 0) {
- if (r == -ECONNRESET || r == -ENOTCONN)
- return r;
-
- /* The name database changed since the policy check, hence let's check again */
- if (r == -EREMCHG)
- continue;
-
- /* see above why EBADSLT is ignored for replies */
- if ((r == -EPERM || r == -EBADSLT) && m->reply_cookie > 0)
- return 1;
-
- synthetic_reply_method_errnof(m, r, "Failed to forward message we got from local: %m");
- log_error_errno(r,
- "Failed to forward message we got from local: uid=" UID_FMT " gid=" GID_FMT" message=%s destination=%s path=%s interface=%s member=%s: %m",
- p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type),
- strna(m->destination), strna(m->path), strna(m->interface), strna(m->member));
- return 1;
- }
-
- break;
- }
-
- return 1;
-}
-
-int proxy_match(sd_bus_message *m, void *userdata, sd_bus_error *error) {
- Proxy *p = userdata;
-
- p->message_matched = true;
- return 0; /* make sure to continue processing it in further handlers */
-}
-
-int proxy_run(Proxy *p) {
- int r;
-
- assert(p);
-
- for (;;) {
- bool busy = false;
-
- if (p->got_hello) {
- /* Read messages from bus, to pass them on to our client */
- r = proxy_process_destination_to_local(p);
- if (r == -ECONNRESET || r == -ENOTCONN)
- return 0;
- if (r < 0)
- return r;
- if (r > 0)
- busy = true;
- }
-
- /* Read messages from our client, to pass them on to the bus */
- r = proxy_process_local_to_destination(p);
- if (r == -ECONNRESET || r == -ENOTCONN)
- return 0;
- if (r < 0)
- return r;
- if (r > 0)
- busy = true;
-
- if (!busy) {
- r = proxy_wait(p);
- if (r == -ECONNRESET || r == -ENOTCONN)
- return 0;
- if (r < 0)
- return r;
- }
- }
-
- return 0;
-}
diff --git a/src/bus-proxyd/proxy.h b/src/bus-proxyd/proxy.h
deleted file mode 100644
index d9e75cf73b..0000000000
--- a/src/bus-proxyd/proxy.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 David Herrmann
-
- 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
-
-#include "bus-xml-policy.h"
-
-typedef struct Proxy Proxy;
-typedef struct ProxyActivation ProxyActivation;
-
-#define PROXY_ACTIVATIONS_MAX (16) /* max parallel activation requests */
-
-struct Proxy {
- sd_bus *local_bus;
- struct ucred local_creds;
- int local_in;
- int local_out;
-
- sd_bus *destination_bus;
-
- Set *owned_names;
- SharedPolicy *policy;
-
- LIST_HEAD(ProxyActivation, activations);
- size_t n_activations;
-
- bool got_hello : 1;
- bool queue_overflow : 1;
- bool message_matched : 1;
- bool synthetic_matched : 1;
-};
-
-struct ProxyActivation {
- LIST_FIELDS(ProxyActivation, activations_by_proxy);
- Proxy *proxy;
- sd_bus_message *request;
- sd_bus_slot *slot;
-};
-
-int proxy_new(Proxy **out, int in_fd, int out_fd, const char *dest);
-Proxy *proxy_free(Proxy *p);
-
-int proxy_set_policy(Proxy *p, SharedPolicy *policy, char **configuration);
-int proxy_hello_policy(Proxy *p, uid_t original_uid);
-int proxy_match(sd_bus_message *m, void *userdata, sd_bus_error *error);
-int proxy_run(Proxy *p);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(Proxy*, proxy_free);
diff --git a/src/bus-proxyd/stdio-bridge.c b/src/bus-proxyd/stdio-bridge.c
deleted file mode 100644
index 291c1b09e3..0000000000
--- a/src/bus-proxyd/stdio-bridge.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Daniel Mack
- Copyright 2014 Kay Sievers
-
- 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <getopt.h>
-#include <stddef.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "sd-bus.h"
-#include "sd-daemon.h"
-
-#include "alloc-util.h"
-#include "bus-internal.h"
-#include "bus-util.h"
-#include "def.h"
-#include "formats-util.h"
-#include "log.h"
-#include "proxy.h"
-#include "strv.h"
-#include "user-util.h"
-#include "util.h"
-
-static char *arg_address = NULL;
-static char *arg_command_line_buffer = NULL;
-
-static int help(void) {
-
- printf("%s [OPTIONS...]\n\n"
- "Connect STDIO to a given bus address.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --machine=MACHINE Connect to specified machine\n"
- " --address=ADDRESS Connect to the bus specified by ADDRESS\n"
- " (default: " DEFAULT_SYSTEM_BUS_ADDRESS ")\n",
- program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_ADDRESS,
- ARG_MACHINE,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "address", required_argument, NULL, ARG_ADDRESS },
- { "machine", required_argument, NULL, ARG_MACHINE },
- {},
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- return version();
-
- case ARG_ADDRESS: {
- char *a;
-
- a = strdup(optarg);
- if (!a)
- return log_oom();
-
- free(arg_address);
- arg_address = a;
- break;
- }
-
- case ARG_MACHINE: {
- _cleanup_free_ char *e = NULL;
- char *a;
-
- e = bus_address_escape(optarg);
- if (!e)
- return log_oom();
-
- a = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL);
- if (!a)
- return log_oom();
-
- free(arg_address);
- arg_address = a;
-
- break;
- }
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached("Unhandled option");
- }
-
- /* If the first command line argument is only "x" characters
- * we'll write who we are talking to into it, so that "ps" is
- * explanatory */
- arg_command_line_buffer = argv[optind];
- if (argc > optind + 1 || (arg_command_line_buffer && !in_charset(arg_command_line_buffer, "x"))) {
- log_error("Too many arguments");
- return -EINVAL;
- }
-
- if (!arg_address) {
- arg_address = strdup(DEFAULT_SYSTEM_BUS_ADDRESS);
- if (!arg_address)
- return log_oom();
- }
-
- return 1;
-}
-
-static int rename_service(sd_bus *a, sd_bus *b) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- _cleanup_free_ char *p = NULL, *name = NULL;
- const char *comm;
- char **cmdline;
- uid_t uid;
- pid_t pid;
- int r;
-
- assert(a);
- assert(b);
-
- r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_AUGMENT, &creds);
- if (r < 0)
- return r;
-
- r = sd_bus_creds_get_euid(creds, &uid);
- if (r < 0)
- return r;
-
- r = sd_bus_creds_get_pid(creds, &pid);
- if (r < 0)
- return r;
-
- r = sd_bus_creds_get_cmdline(creds, &cmdline);
- if (r < 0)
- return r;
-
- r = sd_bus_creds_get_comm(creds, &comm);
- if (r < 0)
- return r;
-
- name = uid_to_name(uid);
- if (!name)
- return -ENOMEM;
-
- p = strv_join(cmdline, " ");
- if (!p)
- return -ENOMEM;
-
- /* The status string gets the full command line ... */
- sd_notifyf(false,
- "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)",
- pid, p,
- uid, name);
-
- /* ... and the argv line only the short comm */
- if (arg_command_line_buffer) {
- size_t m, w;
-
- m = strlen(arg_command_line_buffer);
- w = snprintf(arg_command_line_buffer, m,
- "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]",
- pid, comm,
- uid, name);
-
- if (m > w)
- memzero(arg_command_line_buffer + w, m - w);
- }
-
- log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s",
- pid, p,
- uid, name,
- a->unique_name);
-
- return 0;
-}
-
-int main(int argc, char *argv[]) {
- _cleanup_(proxy_freep) Proxy *p = NULL;
- int r;
-
- log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
-
- r = proxy_new(&p, STDIN_FILENO, STDOUT_FILENO, arg_address);
- if (r < 0)
- goto finish;
-
- r = rename_service(p->destination_bus, p->local_bus);
- if (r < 0)
- log_debug_errno(r, "Failed to rename process: %m");
-
- r = proxy_run(p);
-
-finish:
- sd_notify(false,
- "STOPPING=1\n"
- "STATUS=Shutting down.");
-
- free(arg_address);
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/bus-proxyd/synthesize.c b/src/bus-proxyd/synthesize.c
deleted file mode 100644
index 8eea7dc5b9..0000000000
--- a/src/bus-proxyd/synthesize.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2013 Daniel Mack
- Copyright 2014 Kay Sievers
-
- 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include <stddef.h>
-
-#include "sd-bus.h"
-
-#include "bus-internal.h"
-#include "bus-match.h"
-#include "bus-message.h"
-#include "bus-util.h"
-#include "synthesize.h"
-#include "util.h"
-
-int synthetic_driver_send(sd_bus *b, sd_bus_message *m) {
- int r;
-
- assert(b);
- assert(m);
-
- r = bus_message_append_sender(m, "org.freedesktop.DBus");
- if (r < 0)
- return r;
-
- r = bus_seal_synthetic_message(b, m);
- if (r < 0)
- return r;
-
- return sd_bus_send(b, m, NULL);
-}
-
-int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- int r;
-
- assert(call);
-
- if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
- return 0;
-
- r = sd_bus_message_new_method_error(call, &m, e);
- if (r < 0)
- return r;
-
- return synthetic_driver_send(call->bus, m);
-}
-
-int synthetic_reply_method_errorf(sd_bus_message *call, const char *name, const char *format, ...) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- va_list ap;
-
- va_start(ap, format);
- bus_error_setfv(&error, name, format, ap);
- va_end(ap);
-
- return synthetic_reply_method_error(call, &error);
-}
-
-int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) {
- _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
-
- assert(call);
-
- if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
- return 0;
-
- if (sd_bus_error_is_set(p))
- return synthetic_reply_method_error(call, p);
-
- sd_bus_error_set_errno(&berror, error);
-
- return synthetic_reply_method_error(call, &berror);
-}
-
-int synthetic_reply_method_errnof(sd_bus_message *call, int error, const char *format, ...) {
- _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
- va_list ap;
-
- assert(call);
-
- if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
- return 0;
-
- va_start(ap, format);
- sd_bus_error_set_errnofv(&berror, error, format, ap);
- va_end(ap);
-
- return synthetic_reply_method_error(call, &berror);
-}
-
-int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- int r;
-
- assert(call);
-
- if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
- return 0;
-
- r = sd_bus_message_new_method_return(call, &m);
- if (r < 0)
- return r;
-
- if (!isempty(types)) {
- va_list ap;
-
- va_start(ap, types);
- r = bus_message_append_ap(m, types, ap);
- va_end(ap);
- if (r < 0)
- return r;
- }
-
- return synthetic_driver_send(call->bus, m);
-}
-
-int synthetic_reply_method_return_strv(sd_bus_message *call, char **l) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- int r;
-
- assert(call);
-
- if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
- return 0;
-
- r = sd_bus_message_new_method_return(call, &m);
- if (r < 0)
- return synthetic_reply_method_errno(call, r, NULL);
-
- r = sd_bus_message_append_strv(m, l);
- if (r < 0)
- return synthetic_reply_method_errno(call, r, NULL);
-
- return synthetic_driver_send(call->bus, m);
-}
-
-int synthesize_name_acquired(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
- const char *name, *old_owner, *new_owner;
- int r;
-
- assert(p);
- assert(a);
- assert(b);
- assert(m);
-
- /* If we get NameOwnerChanged for our own name, we need to
- * synthesize NameLost/NameAcquired, since socket clients need
- * that, even though it is obsoleted on kdbus */
-
- if (!a->is_kernel)
- return 0;
-
- if (!sd_bus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged") ||
- !streq_ptr(m->path, "/org/freedesktop/DBus") ||
- !streq_ptr(m->sender, "org.freedesktop.DBus"))
- return 0;
-
- r = sd_bus_message_read(m, "sss", &name, &old_owner, &new_owner);
- if (r < 0)
- return r;
-
- r = sd_bus_message_rewind(m, true);
- if (r < 0)
- return r;
-
- if (streq(old_owner, a->unique_name)) {
-
- r = sd_bus_message_new_signal(
- b,
- &n,
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "NameLost");
-
- } else if (streq(new_owner, a->unique_name)) {
-
- r = sd_bus_message_new_signal(
- b,
- &n,
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "NameAcquired");
- } else
- return 0;
-
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(n, "s", name);
- if (r < 0)
- return r;
-
- r = bus_message_append_sender(n, "org.freedesktop.DBus");
- if (r < 0)
- return r;
-
- r = sd_bus_message_set_destination(n, a->unique_name);
- if (r < 0)
- return r;
-
- r = bus_seal_synthetic_message(b, n);
- if (r < 0)
- return r;
-
- return sd_bus_send(b, n, NULL);
-}
diff --git a/src/bus-proxyd/synthesize.h b/src/bus-proxyd/synthesize.h
deleted file mode 100644
index 1b7197f8ec..0000000000
--- a/src/bus-proxyd/synthesize.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
-
-#include "proxy.h"
-
-int synthetic_driver_send(sd_bus *b, sd_bus_message *m);
-
-int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...);
-int synthetic_reply_method_return_strv(sd_bus_message *call, char **l);
-
-int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e);
-int synthetic_reply_method_errorf(sd_bus_message *call, const char *name, const char *format, ...) _sd_printf_(3, 4);
-int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p);
-int synthetic_reply_method_errnof(sd_bus_message *call, int error, const char *format, ...) _sd_printf_(3, 4);
-
-int synthesize_name_acquired(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m);
diff --git a/src/bus-proxyd/test-bus-xml-policy.c b/src/bus-proxyd/test-bus-xml-policy.c
deleted file mode 100644
index af7c9128a2..0000000000
--- a/src/bus-proxyd/test-bus-xml-policy.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/***
- 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 <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <stddef.h>
-#include <unistd.h>
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "bus-xml-policy.h"
-#include "log.h"
-#include "string-util.h"
-#include "strv.h"
-#include "util.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)
- r = policy_load(p, STRV_MAKE(path));
- else
- r = -ENOENT;
-
- return r;
-}
-
-static int show_policy(const char *fn) {
- Policy p = {};
- int r;
-
- r = policy_load(&p, STRV_MAKE(fn));
- if (r < 0) {
- log_error_errno(r, "Failed to load policy %s: %m", fn);
- return r;
- }
-
- policy_dump(&p);
- policy_free(&p);
-
- return 0;
-}
-
-int main(int argc, char *argv[]) {
-
- Policy p = {};
-
- printf("Showing session policy BEGIN\n");
- show_policy("/etc/dbus-1/session.conf");
- printf("Showing session policy END\n");
-
- printf("Showing system policy BEGIN\n");
- show_policy("/etc/dbus-1/system.conf");
- printf("Showing system policy END\n");
-
- /* 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_one_send(&p, 0, 0, SD_BUS_MESSAGE_SIGNAL, "bli.bla.blubb", NULL, "/an/object/path", NULL) == true);
- assert_se(policy_check_one_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_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "bli.bla.blubb", "Member") == false);
- assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "bli.bla.blubb", "Member") == false);
- assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int1", "Member") == true);
- assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == true);
-
- assert_se(policy_check_one_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_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == false);
- assert_se(policy_check_one_send(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true);
- assert_se(policy_check_one_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true);
- assert_se(policy_check_one_recv(&p, 0, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface2", "Member") == false);
- assert_se(policy_check_one_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_one_send(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.test.int2", "Member") == false);
- assert_se(policy_check_one_send(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.test.test1", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == false);
- assert_se(policy_check_one_recv(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface", "Member") == true);
- assert_se(policy_check_one_recv(&p, 100, 0, SD_BUS_MESSAGE_METHOD_CALL, "org.foo.FooService", "/an/object/path", "org.foo.FooBroadcastInterface2", "Member") == false);
- assert_se(policy_check_one_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;
-}