proxy.c revision 418e4cb07d56e365b9b77b24d3c851e85940d68b
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit This file is part of systemd.
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit Copyright 2010 Lennart Poettering
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit Copyright 2013 Daniel Mack
685810e390056c123842842f5104daa3179cf2c9Phill Cunnington Copyright 2014 Kay Sievers
685810e390056c123842842f5104daa3179cf2c9Phill Cunnington Copyright 2014 David Herrmann
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit systemd is free software; you can redistribute it and/or modify it
685810e390056c123842842f5104daa3179cf2c9Phill Cunnington under the terms of the GNU Lesser General Public License as published by
685810e390056c123842842f5104daa3179cf2c9Phill Cunnington the Free Software Foundation; either version 2.1 of the License, or
685810e390056c123842842f5104daa3179cf2c9Phill Cunnington (at your option) any later version.
685810e390056c123842842f5104daa3179cf2c9Phill Cunnington systemd is distributed in the hope that it will be useful, but
685810e390056c123842842f5104daa3179cf2c9Phill Cunnington WITHOUT ANY WARRANTY; without even the implied warranty of
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
685810e390056c123842842f5104daa3179cf2c9Phill Cunnington Lesser General Public License for more details.
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit You should have received a copy of the GNU Lesser General Public License
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavit along with systemd; If not, see <http://www.gnu.org/licenses/>.
80802511792d4e59a4ac67ad19677009d332b37dBruno Lavitstatic 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);
return -ECONNRESET;
if (p->policy) {
r = process_policy(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
if (r != -ECONNRESET)
assert(p);
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) {
if (r != -ECONNRESET)
assert(p);
bool busy = false;
if (p->got_hello) {
if (r == -ECONNRESET)
busy = true;
if (r == -ECONNRESET)
busy = true;
if (!busy) {
r = proxy_wait(p);