proxy.c revision 557b5d4a94967198b3181fcb83879d4569cbf456
d6170d27b26eeeace966bb9720d66fcac2a6ef1bZbigniew Jędrzejewski-Szmek/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d6170d27b26eeeace966bb9720d66fcac2a6ef1bZbigniew Jędrzejewski-Szmek This file is part of systemd.
d6170d27b26eeeace966bb9720d66fcac2a6ef1bZbigniew Jędrzejewski-Szmek Copyright 2010 Lennart Poettering
d6170d27b26eeeace966bb9720d66fcac2a6ef1bZbigniew Jędrzejewski-Szmek Copyright 2013 Daniel Mack
d6170d27b26eeeace966bb9720d66fcac2a6ef1bZbigniew Jędrzejewski-Szmek Copyright 2014 Kay Sievers
d6170d27b26eeeace966bb9720d66fcac2a6ef1bZbigniew Jędrzejewski-Szmek Copyright 2014 David Herrmann
d6170d27b26eeeace966bb9720d66fcac2a6ef1bZbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it
d6170d27b26eeeace966bb9720d66fcac2a6ef1bZbigniew Jędrzejewski-Szmek under the terms of the GNU Lesser General Public License as published by
d6170d27b26eeeace966bb9720d66fcac2a6ef1bZbigniew Jędrzejewski-Szmek the Free Software Foundation; either version 2.1 of the License, or
d6170d27b26eeeace966bb9720d66fcac2a6ef1bZbigniew Jędrzejewski-Szmek (at your option) any later version.
d6170d27b26eeeace966bb9720d66fcac2a6ef1bZbigniew Jędrzejewski-Szmek systemd is distributed in the hope that it will be useful, but
d6170d27b26eeeace966bb9720d66fcac2a6ef1bZbigniew Jędrzejewski-Szmek WITHOUT ANY WARRANTY; without even the implied warranty of
d6170d27b26eeeace966bb9720d66fcac2a6ef1bZbigniew Jędrzejewski-Szmek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d6170d27b26eeeace966bb9720d66fcac2a6ef1bZbigniew Jędrzejewski-Szmek Lesser General Public License for more details.
d6170d27b26eeeace966bb9720d66fcac2a6ef1bZbigniew Jędrzejewski-Szmek You should have received a copy of the GNU Lesser General Public License
d6170d27b26eeeace966bb9720d66fcac2a6ef1bZbigniew Jędrzejewski-Szmek along with systemd; If not, see <http://www.gnu.org/licenses/>.
#include "set.h"
#include "bus-xml-policy.h"
#include "driver.h"
#include "proxy.h"
#include "synthesize.h"
static int proxy_create_destination(Proxy *p, const char *destination, const char *local_sec, bool negotiate_fds) {
r = sd_bus_new(&b);
r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT);
b->fake_pids_valid = true;
b->fake_creds_valid = true;
if (local_sec) {
if (!b->fake_label)
return log_oom();
b->manual_peer_interface = true;
r = sd_bus_start(b);
p->destination_bus = b;
b = NULL;
r = sd_bus_new(&b);
r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT);
r = sd_bus_set_anonymous(b, true);
b->manual_peer_interface = true;
r = sd_bus_start(b);
p->local_bus = b;
b = NULL;
const char *unique;
"path='/org/freedesktop/DBus',"
NULL);
if (!match)
return log_oom();
"path='/org/freedesktop/DBus',"
NULL);
if (!match)
return log_oom();
bool is_unix;
return log_oom();
if (!p->owned_names)
return log_oom();
if (is_unix) {
r = proxy_prepare_matches(p);
*out = p;
p = NULL;
return NULL;
free(p);
return NULL;
assert(p);
if (policy) {
if (!configuration) {
const char *scope;
NULL);
NULL);
if (!strv)
return log_oom();
assert(p);
if (!p->policy)
assert(p);
if (fd < 0)
if (events_destination < 0)
if (events_local < 0)
t = timeout_destination;
t = timeout_local;
if (t > nw)
t -= nw;
return synthetic_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination);
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) {
assert(m);
if (!policy)
if (m->reply_cookie > 0)
r = bus_get_name_creds_kdbus(from, m->sender, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID, true, &sender_creds);
return handle_policy_error(m, r);
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 synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
if (m->destination) {
true, &destination_creds);
return handle_policy_error(m, r);
return handle_policy_error(m, r);
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)) {
} else if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, true)) {
return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, SharedPolicy *sp, const struct ucred *our_ucred, Set *owned_names) {
bool is_hello;
assert(p);
assert(m);
is_hello =
if (!is_hello) {
if (p->got_hello)
return log_error_errno(EIO, "First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
if (p->got_hello)
p->got_hello = true;
r = sd_bus_message_new_method_return(m, &n);
n = sd_bus_message_unref(n);
p->local_bus,
"/org/freedesktop/DBus",
sd_bus_creds *c;
assert(a);
assert(m);
if (!a->is_kernel)
c = sd_bus_message_get_creds(m);
assert(p);
if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
return -ECONNRESET;
if (p->policy) {
r = process_policy(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
assert(p);
if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
return -ECONNRESET;
r = process_hello(p, m);
r = bus_proxy_process_driver(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
if (p->policy) {
r = process_policy(p->local_bus, p->destination_bus, m, p->policy, &p->local_creds, p->owned_names);
if (r == -EREMCHG)
assert(p);
bool busy = false;
if (p->got_hello) {
busy = true;
busy = true;
if (!busy) {
r = proxy_wait(p);