c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann/***
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann This file is part of systemd.
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann Copyright 2010 Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann Copyright 2013 Daniel Mack
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann Copyright 2014 Kay Sievers
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann Copyright 2014 David Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann systemd is free software; you can redistribute it and/or modify it
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann under the terms of the GNU Lesser General Public License as published by
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann the Free Software Foundation; either version 2.1 of the License, or
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann (at your option) any later version.
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann systemd is distributed in the hope that it will be useful, but
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann WITHOUT ANY WARRANTY; without even the implied warranty of
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann Lesser General Public License for more details.
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann You should have received a copy of the GNU Lesser General Public License
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann along with systemd; If not, see <http://www.gnu.org/licenses/>.
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann***/
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include <errno.h>
0a6f50c0afdfc434b492493bd9efab20cbee8623Thomas Hindoe Paaboel Andersen#include <poll.h>
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include <string.h>
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include <sys/socket.h>
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include <sys/types.h>
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "sd-bus.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "sd-daemon.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "alloc-util.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "bus-control.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "bus-internal.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "bus-message.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "bus-util.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "bus-xml-policy.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "driver.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "fd-util.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "formats-util.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "log.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "proxy.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "set.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "strv.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann#include "synthesize.h"
ee104e11e303499a637c5cd8157bd12ad5cc116dLennart Poettering#include "user-util.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "util.h"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poetteringstatic int proxy_create_destination(Proxy *p, const char *destination, const char *local_sec, bool negotiate_fds) {
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_flush_close_unrefp) sd_bus *b = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_new(&b);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to allocate bus: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_set_description(b, "sd-proxy");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to set bus name: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering r = sd_bus_set_address(b, destination);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to set address to connect to: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_negotiate_fds(b, negotiate_fds);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to set FD negotiation: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to set credential negotiation: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (p->local_creds.pid > 0) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann b->fake_pids.pid = p->local_creds.pid;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann b->fake_pids_valid = true;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d90c154eb180783098683ce8e1c03cd29d9b77ceDavid Herrmann b->fake_creds.uid = UID_INVALID;
e23f4bb525991c5908be0d0e7f8374c964d9996cDavid Herrmann b->fake_creds.euid = p->local_creds.uid;
d90c154eb180783098683ce8e1c03cd29d9b77ceDavid Herrmann b->fake_creds.suid = UID_INVALID;
d90c154eb180783098683ce8e1c03cd29d9b77ceDavid Herrmann b->fake_creds.fsuid = UID_INVALID;
d90c154eb180783098683ce8e1c03cd29d9b77ceDavid Herrmann b->fake_creds.gid = GID_INVALID;
e23f4bb525991c5908be0d0e7f8374c964d9996cDavid Herrmann b->fake_creds.egid = p->local_creds.gid;
d90c154eb180783098683ce8e1c03cd29d9b77ceDavid Herrmann b->fake_creds.sgid = GID_INVALID;
d90c154eb180783098683ce8e1c03cd29d9b77ceDavid Herrmann b->fake_creds.fsgid = GID_INVALID;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann b->fake_creds_valid = true;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (local_sec) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann b->fake_label = strdup(local_sec);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!b->fake_label)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_oom();
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann b->manual_peer_interface = true;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_start(b);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to start bus client: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering p->destination_bus = b;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann b = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poetteringstatic int proxy_create_local(Proxy *p, bool negotiate_fds) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann sd_id128_t server_id;
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering sd_bus *b;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_new(&b);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to allocate bus: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering r = sd_bus_set_fd(b, p->local_in, p->local_out);
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering if (r < 0) {
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering sd_bus_unref(b);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to set fds: %m");
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering }
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering /* The fds are now owned by the bus, and we indicate that by
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering * storing the bus object in the proxy object. */
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering p->local_bus = b;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering r = sd_bus_get_bus_id(p->destination_bus, &server_id);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to get server ID: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_set_server(b, 1, server_id);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to set server mode: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_negotiate_fds(b, negotiate_fds);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to set FD negotiation: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to set credential negotiation: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_set_anonymous(b, true);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to set anonymous authentication: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann b->manual_peer_interface = true;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_start(b);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to start bus client: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmannstatic int proxy_match_synthetic(sd_bus_message *m, void *userdata, sd_bus_error *error) {
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann Proxy *p = userdata;
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann p->synthetic_matched = true;
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann return 0; /* make sure to continue processing it in further handlers */
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann}
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann
619b80a1c7caeb1d910d8d68a3700b8bdfc29a90Kay Sievers/*
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann * We always need NameOwnerChanged so we can synthesize NameLost and
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann * NameAcquired. Furthermore, dbus-1 always passes unicast-signals through, so
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann * subscribe unconditionally.
619b80a1c7caeb1d910d8d68a3700b8bdfc29a90Kay Sievers */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int proxy_prepare_matches(Proxy *p) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_free_ char *match = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann const char *unique;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering if (!p->destination_bus->is_kernel)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering r = sd_bus_get_unique_name(p->destination_bus, &unique);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to get unique name: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann match = strjoin("type='signal',"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "sender='org.freedesktop.DBus',"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "path='/org/freedesktop/DBus',"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "interface='org.freedesktop.DBus',"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "member='NameOwnerChanged',"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "arg1='",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann unique,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "'",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann NULL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!match)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_oom();
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to add match for NameLost: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann free(match);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann match = strjoin("type='signal',"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "sender='org.freedesktop.DBus',"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "path='/org/freedesktop/DBus',"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "interface='org.freedesktop.DBus',"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "member='NameOwnerChanged',"
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "arg2='",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann unique,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "'",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann NULL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!match)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_oom();
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to add match for NameAcquired: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
de865432f887e68ac7add166cf618c88431d6538Kay Sievers free(match);
de865432f887e68ac7add166cf618c88431d6538Kay Sievers match = strjoin("type='signal',"
de865432f887e68ac7add166cf618c88431d6538Kay Sievers "destination='",
de865432f887e68ac7add166cf618c88431d6538Kay Sievers unique,
de865432f887e68ac7add166cf618c88431d6538Kay Sievers "'",
de865432f887e68ac7add166cf618c88431d6538Kay Sievers NULL);
de865432f887e68ac7add166cf618c88431d6538Kay Sievers if (!match)
de865432f887e68ac7add166cf618c88431d6538Kay Sievers return log_oom();
de865432f887e68ac7add166cf618c88431d6538Kay Sievers
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
de865432f887e68ac7add166cf618c88431d6538Kay Sievers if (r < 0)
619b80a1c7caeb1d910d8d68a3700b8bdfc29a90Kay Sievers log_error_errno(r, "Failed to add match for directed signals: %m");
619b80a1c7caeb1d910d8d68a3700b8bdfc29a90Kay Sievers /* FIXME: temporarily ignore error to support older kdbus versions */
de865432f887e68ac7add166cf618c88431d6538Kay Sievers
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poetteringint proxy_new(Proxy **out, int in_fd, int out_fd, const char *destination) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_(proxy_freep) Proxy *p = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_free_ char *local_sec = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann bool is_unix;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering /* This takes possession/destroys the file descriptors passed
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering * in even on failure. The caller should hence forget about
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering * the fds in all cases after calling this function and not
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering * close them. */
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann p = new0(Proxy, 1);
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering if (!p) {
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering safe_close(in_fd);
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering safe_close(out_fd);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_oom();
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann p->local_in = in_fd;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann p->local_out = out_fd;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann p->owned_names = set_new(&string_hash_ops);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!p->owned_names)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_oom();
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann is_unix = sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (is_unix) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann (void) getpeercred(in_fd, &p->local_creds);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann (void) getpeersec(in_fd, &local_sec);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering r = proxy_create_destination(p, destination, local_sec, is_unix);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering r = proxy_create_local(p, is_unix);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = proxy_prepare_matches(p);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann *out = p;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann p = NULL;
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid HerrmannProxy *proxy_free(Proxy *p) {
11f254be0c27b1944a1df8e7c14d83e56ebe7d9bDavid Herrmann ProxyActivation *activation;
11f254be0c27b1944a1df8e7c14d83e56ebe7d9bDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!p)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
11f254be0c27b1944a1df8e7c14d83e56ebe7d9bDavid Herrmann while ((activation = p->activations)) {
11f254be0c27b1944a1df8e7c14d83e56ebe7d9bDavid Herrmann LIST_REMOVE(activations_by_proxy, p->activations, activation);
11f254be0c27b1944a1df8e7c14d83e56ebe7d9bDavid Herrmann sd_bus_message_unref(activation->request);
11f254be0c27b1944a1df8e7c14d83e56ebe7d9bDavid Herrmann sd_bus_slot_unref(activation->slot);
11f254be0c27b1944a1df8e7c14d83e56ebe7d9bDavid Herrmann free(activation);
11f254be0c27b1944a1df8e7c14d83e56ebe7d9bDavid Herrmann }
11f254be0c27b1944a1df8e7c14d83e56ebe7d9bDavid Herrmann
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering if (p->local_bus)
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering sd_bus_flush_close_unref(p->local_bus);
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering else {
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering safe_close(p->local_in);
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering if (p->local_out != p->local_in)
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering safe_close(p->local_out);
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering }
1a37c9756f0c55917192e1a229977734b1f7ea45Lennart Poettering
03976f7b4a84b8b1492a549a3470b2bba8f37008Lennart Poettering sd_bus_flush_close_unref(p->destination_bus);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann set_free_free(p->owned_names);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann free(p);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmannint proxy_set_policy(Proxy *p, SharedPolicy *sp, char **configuration) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann _cleanup_strv_free_ char **strv = NULL;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann Policy *policy;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(p);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann assert(sp);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* no need to load legacy policy if destination is not kdbus */
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering if (!p->destination_bus->is_kernel)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann p->policy = sp;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann policy = shared_policy_acquire(sp);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann if (policy) {
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann /* policy already pre-loaded */
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann shared_policy_release(sp, policy);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann return 0;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann }
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!configuration) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann const char *scope;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering r = sd_bus_get_scope(p->destination_bus, &scope);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Couldn't determine bus scope: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (streq(scope, "system"))
97af81cffa6891b361521d3fc0b6ea10b478d59dLennart Poettering strv = strv_new("/usr/share/dbus-1/system.conf",
97af81cffa6891b361521d3fc0b6ea10b478d59dLennart Poettering "/etc/dbus-1/system.conf",
97af81cffa6891b361521d3fc0b6ea10b478d59dLennart Poettering "/usr/share/dbus-1/system.d/",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "/etc/dbus-1/system.d/",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "/etc/dbus-1/system-local.conf",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann NULL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann else if (streq(scope, "user"))
97af81cffa6891b361521d3fc0b6ea10b478d59dLennart Poettering strv = strv_new("/usr/share/dbus-1/session.conf",
97af81cffa6891b361521d3fc0b6ea10b478d59dLennart Poettering "/etc/dbus-1/session.conf",
97af81cffa6891b361521d3fc0b6ea10b478d59dLennart Poettering "/usr/share/dbus-1/session.d/",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "/etc/dbus-1/session.d/",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "/etc/dbus-1/session-local.conf",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann NULL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann else
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!strv)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_oom();
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann configuration = strv;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann return shared_policy_preload(sp, configuration);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannint proxy_hello_policy(Proxy *p, uid_t original_uid) {
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann Policy *policy;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann int r = 0;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(p);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!p->policy)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann policy = shared_policy_acquire(p->policy);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (p->local_creds.uid == original_uid)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_debug("Permitting access, since bus owner matches bus client.");
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann else if (policy_check_hello(policy, p->local_creds.uid, p->local_creds.gid))
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann log_debug("Permitting access due to XML policy.");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann else
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann r = log_error_errno(EPERM, "Policy denied connection.");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann shared_policy_release(p->policy, policy);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int proxy_wait(Proxy *p) {
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering uint64_t timeout_destination, timeout_local, t;
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering int events_destination, events_local, fd;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann struct timespec _ts, *ts;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann struct pollfd *pollfd;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(p);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering fd = sd_bus_get_fd(p->destination_bus);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (fd < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(fd, "Failed to get fd: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering events_destination = sd_bus_get_events(p->destination_bus);
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering if (events_destination < 0)
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering return log_error_errno(events_destination, "Failed to get events mask: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering r = sd_bus_get_timeout(p->destination_bus, &timeout_destination);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to get timeout: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann events_local = sd_bus_get_events(p->local_bus);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (events_local < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(events_local, "Failed to get events mask: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_get_timeout(p->local_bus, &timeout_local);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to get timeout: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering t = timeout_destination;
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering if (t == (uint64_t) -1 || (timeout_local != (uint64_t) -1 && timeout_local < timeout_destination))
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann t = timeout_local;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (t == (uint64_t) -1)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann ts = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann else {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann usec_t nw;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann nw = now(CLOCK_MONOTONIC);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (t > nw)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann t -= nw;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann else
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann t = 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann ts = timespec_store(&_ts, t);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann pollfd = (struct pollfd[3]) {
c74f883c6f7d5901b3c543d47f64082ccd91a895Lennart Poettering { .fd = fd, .events = events_destination, },
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann { .fd = p->local_in, .events = events_local & POLLIN, },
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann { .fd = p->local_out, .events = events_local & POLLOUT, },
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann };
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = ppoll(pollfd, 3, ts, NULL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(errno, "ppoll() failed: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int handle_policy_error(sd_bus_message *m, int r) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r == -ESRCH || r == -ENXIO)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return synthetic_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmannstatic int process_policy_unlocked(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(from);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(to);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(m);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!policy)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /*
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * dbus-1 distinguishes expected and non-expected replies by tracking
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * method-calls and timeouts. By default, DENY rules are *NEVER* applied
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * on expected replies, unless explicitly specified. But we dont track
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * method-calls, thus, we cannot know whether a reply is expected.
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * Fortunately, the kdbus forbids non-expected replies, so we can safely
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * ignore any policy on those and let the kernel deal with it.
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann *
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * TODO: To be correct, we should only ignore policy-tags that are
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * applied on non-expected replies. However, so far we don't parse those
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * tags so we let everything pass. I haven't seen a DENY policy tag on
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * expected-replies, ever, so don't bother..
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (m->reply_cookie > 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (from->is_kernel) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann uid_t sender_uid = UID_INVALID;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann gid_t sender_gid = GID_INVALID;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann char **sender_names = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Driver messages are always OK */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (streq_ptr(m->sender, "org.freedesktop.DBus"))
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* The message came from the kernel, and is sent to our legacy client. */
1140e154100f7224fb8bab55ba7fc087409f9d76Lennart Poettering (void) sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann (void) sd_bus_creds_get_euid(&m->creds, &sender_uid);
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann (void) sd_bus_creds_get_egid(&m->creds, &sender_gid);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (sender_uid == UID_INVALID || sender_gid == GID_INVALID) {
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *sender_creds = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* If the message came from another legacy
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * client, then the message creds will be
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * missing, simply because on legacy clients
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * per-message creds were unknown. In this
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * case, query the creds of the peer
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * instead. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann r = bus_get_name_creds_kdbus(from, m->sender, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID, true, &sender_creds);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return handle_policy_error(m, r);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann (void) sd_bus_creds_get_euid(sender_creds, &sender_uid);
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann (void) sd_bus_creds_get_egid(sender_creds, &sender_gid);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* First check whether the sender can send the message to our name */
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, false, NULL) &&
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, sender_names, m->path, m->interface, m->member, false))
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Return an error back to the caller */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Return 1, indicating that the message shall not be processed any further */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 1;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (to->is_kernel) {
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *destination_creds = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann uid_t destination_uid = UID_INVALID;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann gid_t destination_gid = GID_INVALID;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann const char *destination_unique = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann char **destination_names = NULL;
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann char *n;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Driver messages are always OK */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (streq_ptr(m->destination, "org.freedesktop.DBus"))
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* The message came from the legacy client, and is sent to kdbus. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (m->destination) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = bus_get_name_creds_kdbus(to, m->destination,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann true, &destination_creds);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return handle_policy_error(m, r);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return handle_policy_error(m, r);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
1140e154100f7224fb8bab55ba7fc087409f9d76Lennart Poettering (void) sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann (void) sd_bus_creds_get_euid(destination_creds, &destination_uid);
05bae4a60c32e29797597979cee2f3684eb3bc1eDavid Herrmann (void) sd_bus_creds_get_egid(destination_creds, &destination_gid);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* First check if we (the sender) can send to this name */
3723263f4989ebeb087cf0a1259884de962bc85eDavid Herrmann if (sd_bus_message_is_signal(m, NULL, NULL)) {
3723263f4989ebeb087cf0a1259884de962bc85eDavid Herrmann /* If we forward a signal from dbus-1 to kdbus, we have
3723263f4989ebeb087cf0a1259884de962bc85eDavid Herrmann * no idea who the recipient is. Therefore, we cannot
3723263f4989ebeb087cf0a1259884de962bc85eDavid Herrmann * apply any dbus-1 policies that match on receiver
3723263f4989ebeb087cf0a1259884de962bc85eDavid Herrmann * credentials. We know sd-bus always sets
3723263f4989ebeb087cf0a1259884de962bc85eDavid Herrmann * KDBUS_MSG_SIGNAL, so the kernel applies policies to
3723263f4989ebeb087cf0a1259884de962bc85eDavid Herrmann * the message. Therefore, skip policy checks in this
3723263f4989ebeb087cf0a1259884de962bc85eDavid Herrmann * case. */
3723263f4989ebeb087cf0a1259884de962bc85eDavid Herrmann return 0;
3723263f4989ebeb087cf0a1259884de962bc85eDavid Herrmann } 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)) {
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann if (n) {
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann /* If we made a receiver decision, then remember which
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann * name's policy we used, and to which unique ID it
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann * mapped when we made the decision. Then, let's pass
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann * this to the kernel when sending the message, so that
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann * it refuses the operation should the name and unique
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann * ID not map to each other anymore. */
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann r = free_and_strdup(&m->destination_ptr, n);
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann if (r < 0)
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann return r;
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann if (r < 0)
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
3723263f4989ebeb087cf0a1259884de962bc85eDavid Herrmann if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, true))
7447362c530e3f7128f16a35d1e43da4251144ccDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Return an error back to the caller */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Return 1, indicating that the message shall not be processed any further */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 1;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmannstatic int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, SharedPolicy *sp, const struct ucred *our_ucred, Set *owned_names) {
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann Policy *policy;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann int r;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann assert(sp);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann policy = shared_policy_acquire(sp);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann r = process_policy_unlocked(from, to, m, policy, our_ucred, owned_names);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann shared_policy_release(sp, policy);
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann return r;
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann}
c4bc1a8434f2a34840ea6f63064fa998ecfae738David Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int process_hello(Proxy *p, sd_bus_message *m) {
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann bool is_hello;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(p);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(m);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* As reaction to hello we need to respond with two messages:
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * the callback reply and the NameAcquired for the unique
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * name, since hello is otherwise obsolete on kdbus. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann is_hello =
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann streq_ptr(m->destination, "org.freedesktop.DBus");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!is_hello) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (p->got_hello)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
61adca52f6f0b119e501c523008a454887cdf2b9Lennart Poettering return log_error_errno(EIO, "First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (p->got_hello)
61adca52f6f0b119e501c523008a454887cdf2b9Lennart Poettering return log_error_errno(EIO, "Got duplicate hello, aborting.");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann p->got_hello = true;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering if (!p->destination_bus->is_kernel)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_message_new_method_return(m, &n);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to generate HELLO reply: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering r = sd_bus_message_append(n, "s", p->destination_bus->unique_name);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = bus_message_append_sender(n, "org.freedesktop.DBus");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = bus_seal_synthetic_message(p->local_bus, n);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to seal HELLO reply: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_send(p->local_bus, n, NULL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to send HELLO reply: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann n = sd_bus_message_unref(n);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_message_new_signal(
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann p->local_bus,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann &n,
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "/org/freedesktop/DBus",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "org.freedesktop.DBus",
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann "NameAcquired");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering r = sd_bus_message_append(n, "s", p->destination_bus->unique_name);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = bus_message_append_sender(n, "org.freedesktop.DBus");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
e3c57a86f6ede89651e600d168389be4a78c1b33David Herrmann r = sd_bus_message_set_destination(n, p->destination_bus->unique_name);
e3c57a86f6ede89651e600d168389be4a78c1b33David Herrmann if (r < 0)
e3c57a86f6ede89651e600d168389be4a78c1b33David Herrmann return log_error_errno(r, "Failed to set destination for NameAcquired message: %m");
e3c57a86f6ede89651e600d168389be4a78c1b33David Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = bus_seal_synthetic_message(p->local_bus, n);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to seal NameAcquired message: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_send(p->local_bus, n, NULL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to send NameAcquired message: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 1;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannstatic int patch_sender(sd_bus *a, sd_bus_message *m) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann char **well_known = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann sd_bus_creds *c;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(a);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(m);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!a->is_kernel)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* We will change the sender of messages from the bus driver
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * so that they originate from the bus driver. This is a
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * speciality originating from dbus1, where the bus driver did
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann * not have a unique id, but only the well-known name. */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann c = sd_bus_message_get_creds(m);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!c)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_creds_get_well_known_names(c, &well_known);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (strv_contains(well_known, "org.freedesktop.DBus"))
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann m->sender = "org.freedesktop.DBus";
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poetteringstatic int proxy_process_destination_to_local(Proxy *p) {
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann bool matched, matched_synthetic;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(p);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann /*
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann * Usually, we would just take any message that the bus passes to us
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann * and forward it to the local connection. However, there are actually
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann * applications that fail if they receive broadcasts that they didn't
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann * subscribe to. Therefore, we actually emulate a real broadcast
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann * matching here, and discard any broadcasts that weren't matched. Our
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann * match-handlers remembers whether a message was matched by any rule,
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann * by marking it in @p->message_matched.
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann */
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering r = sd_bus_process(p->destination_bus, &m);
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann matched = p->message_matched;
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann matched_synthetic = p->synthetic_matched;
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann p->message_matched = false;
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann p->synthetic_matched = false;
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann
557b5d4a94967198b3181fcb83879d4569cbf456Lennart Poettering if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
418e4cb07d56e365b9b77b24d3c851e85940d68bLennart Poettering return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0) {
418e4cb07d56e365b9b77b24d3c851e85940d68bLennart Poettering log_error_errno(r, "Failed to process destination bus: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r == 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!m)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 1;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* We officially got EOF, let's quit */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return -ECONNRESET;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann r = synthesize_name_acquired(p, p->destination_bus, p->local_bus, m);
c74f883c6f7d5901b3c543d47f64082ccd91a895Lennart Poettering if (r == -ECONNRESET || r == -ENOTCONN)
c74f883c6f7d5901b3c543d47f64082ccd91a895Lennart Poettering return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to synthesize message: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann /* discard broadcasts that were not matched by any MATCH rule */
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann if (!matched && !sd_bus_message_get_destination(m)) {
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann if (!matched_synthetic)
ad8373e9e3e9c86a79bfc29bb731b130ae2dab85Daniel Mack 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",
ad8373e9e3e9c86a79bfc29bb731b130ae2dab85Daniel Mack p->local_creds.uid, p->local_creds.gid, p->local_creds.pid, bus_message_type_to_string(m->header->type),
ad8373e9e3e9c86a79bfc29bb731b130ae2dab85Daniel Mack strna(m->path), strna(m->interface), strna(m->member), strna(m->sender), strna(m->destination));
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann return 1;
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann }
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering patch_sender(p->destination_bus, m);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (p->policy) {
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering r = process_policy(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
c74f883c6f7d5901b3c543d47f64082ccd91a895Lennart Poettering if (r == -ECONNRESET || r == -ENOTCONN)
c74f883c6f7d5901b3c543d47f64082ccd91a895Lennart Poettering return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to process policy: %m");
418e4cb07d56e365b9b77b24d3c851e85940d68bLennart Poettering if (r > 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 1;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_send(p->local_bus, m, NULL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0) {
557b5d4a94967198b3181fcb83879d4569cbf456Lennart Poettering if (r == -ECONNRESET || r == -ENOTCONN)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering /* If the peer tries to send a reply and it is
2c960818c8887386fce216a1bbbadbe8d35d59c3David Herrmann * rejected with EBADSLT by the kernel, we ignore the
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering * error. This catches cases where the original
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering * method-call didn't had EXPECT_REPLY set, but the
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering * proxy-peer still sends a reply. This is allowed in
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering * dbus1, but not in kdbus. We don't want to track
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering * reply-windows in the proxy, so we simply ignore
2c960818c8887386fce216a1bbbadbe8d35d59c3David Herrmann * EBADSLT for all replies. The only downside is, that
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering * callers are no longer notified if their replies are
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering * dropped. However, this is equivalent to the
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering * caller's timeout to expire, so this should be
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering * acceptable. Nobody sane sends replies without a
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering * matching method-call, so nobody should care. */
855fc9744f63c04b220392f2ee30a83e4d6a7610Kay Sievers
855fc9744f63c04b220392f2ee30a83e4d6a7610Kay Sievers /* FIXME: remove -EPERM when kdbus is updated */
2c960818c8887386fce216a1bbbadbe8d35d59c3David Herrmann if ((r == -EPERM || r == -EBADSLT) && m->reply_cookie > 0)
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering return 1;
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering /* Return the error to the client, if we can */
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering synthetic_reply_method_errnof(m, r, "Failed to forward message we got from destination: %m");
ec2c7b56599981a7d9e76b15c75af3e1af3e6f81David Herrmann if (r == -ENOBUFS) {
ec2c7b56599981a7d9e76b15c75af3e1af3e6f81David Herrmann /* if local dbus1 peer does not dispatch its queue, warn only once */
ec2c7b56599981a7d9e76b15c75af3e1af3e6f81David Herrmann if (!p->queue_overflow)
ec2c7b56599981a7d9e76b15c75af3e1af3e6f81David Herrmann 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);
ec2c7b56599981a7d9e76b15c75af3e1af3e6f81David Herrmann p->queue_overflow = true;
ec2c7b56599981a7d9e76b15c75af3e1af3e6f81David Herrmann } else
ec2c7b56599981a7d9e76b15c75af3e1af3e6f81David Herrmann log_error_errno(r,
ec2c7b56599981a7d9e76b15c75af3e1af3e6f81David Herrmann "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",
ec2c7b56599981a7d9e76b15c75af3e1af3e6f81David Herrmann p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type),
ec2c7b56599981a7d9e76b15c75af3e1af3e6f81David Herrmann strna(m->destination), strna(m->path), strna(m->interface), strna(m->member));
ec2c7b56599981a7d9e76b15c75af3e1af3e6f81David Herrmann
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering return 1;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
ec2c7b56599981a7d9e76b15c75af3e1af3e6f81David Herrmann p->queue_overflow = false;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 1;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poetteringstatic int proxy_process_local_to_destination(Proxy *p) {
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(p);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = sd_bus_process(p->local_bus, &m);
557b5d4a94967198b3181fcb83879d4569cbf456Lennart Poettering if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
418e4cb07d56e365b9b77b24d3c851e85940d68bLennart Poettering return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0) {
418e4cb07d56e365b9b77b24d3c851e85940d68bLennart Poettering log_error_errno(r, "Failed to process local bus: %m");
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r == 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!m)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 1;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* We officially got EOF, let's quit */
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return -ECONNRESET;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = process_hello(p, m);
c74f883c6f7d5901b3c543d47f64082ccd91a895Lennart Poettering if (r == -ECONNRESET || r == -ENOTCONN)
c74f883c6f7d5901b3c543d47f64082ccd91a895Lennart Poettering return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to process HELLO: %m");
418e4cb07d56e365b9b77b24d3c851e85940d68bLennart Poettering if (r > 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 1;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann r = bus_proxy_process_driver(p, p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
c74f883c6f7d5901b3c543d47f64082ccd91a895Lennart Poettering if (r == -ECONNRESET || r == -ENOTCONN)
c74f883c6f7d5901b3c543d47f64082ccd91a895Lennart Poettering return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to process driver calls: %m");
418e4cb07d56e365b9b77b24d3c851e85940d68bLennart Poettering if (r > 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 1;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann for (;;) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (p->policy) {
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering r = process_policy(p->local_bus, p->destination_bus, m, p->policy, &p->local_creds, p->owned_names);
c74f883c6f7d5901b3c543d47f64082ccd91a895Lennart Poettering if (r == -ECONNRESET || r == -ENOTCONN)
c74f883c6f7d5901b3c543d47f64082ccd91a895Lennart Poettering return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return log_error_errno(r, "Failed to process policy: %m");
c74f883c6f7d5901b3c543d47f64082ccd91a895Lennart Poettering if (r > 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 1;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering r = sd_bus_send(p->destination_bus, m, NULL);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0) {
557b5d4a94967198b3181fcb83879d4569cbf456Lennart Poettering if (r == -ECONNRESET || r == -ENOTCONN)
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering return r;
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering /* The name database changed since the policy check, hence let's check again */
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering if (r == -EREMCHG)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann continue;
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering
2c960818c8887386fce216a1bbbadbe8d35d59c3David Herrmann /* see above why EBADSLT is ignored for replies */
2c960818c8887386fce216a1bbbadbe8d35d59c3David Herrmann if ((r == -EPERM || r == -EBADSLT) && m->reply_cookie > 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 1;
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering synthetic_reply_method_errnof(m, r, "Failed to forward message we got from local: %m");
e28569311f5385cde76e4b84adbec6609b451cf9David Herrmann log_error_errno(r,
e28569311f5385cde76e4b84adbec6609b451cf9David Herrmann "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",
e28569311f5385cde76e4b84adbec6609b451cf9David Herrmann p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type),
e28569311f5385cde76e4b84adbec6609b451cf9David Herrmann strna(m->destination), strna(m->path), strna(m->interface), strna(m->member));
5f6cb091278906423f8b7e70c40131db7269916aLennart Poettering return 1;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann break;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 1;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmannint proxy_match(sd_bus_message *m, void *userdata, sd_bus_error *error) {
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann Proxy *p = userdata;
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann p->message_matched = true;
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann return 0; /* make sure to continue processing it in further handlers */
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann}
e23bc0e7cac8ba79f4e14ab98ecd68c79cc87aabDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmannint proxy_run(Proxy *p) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann int r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann assert(p);
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann for (;;) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann bool busy = false;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (p->got_hello) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Read messages from bus, to pass them on to our client */
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering r = proxy_process_destination_to_local(p);
557b5d4a94967198b3181fcb83879d4569cbf456Lennart Poettering if (r == -ECONNRESET || r == -ENOTCONN)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
418e4cb07d56e365b9b77b24d3c851e85940d68bLennart Poettering if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
418e4cb07d56e365b9b77b24d3c851e85940d68bLennart Poettering if (r > 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann busy = true;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann /* Read messages from our client, to pass them on to the bus */
d27efd93841a2ac2127fd53321368cc3f975c564Lennart Poettering r = proxy_process_local_to_destination(p);
557b5d4a94967198b3181fcb83879d4569cbf456Lennart Poettering if (r == -ECONNRESET || r == -ENOTCONN)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
418e4cb07d56e365b9b77b24d3c851e85940d68bLennart Poettering if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
418e4cb07d56e365b9b77b24d3c851e85940d68bLennart Poettering if (r > 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann busy = true;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (!busy) {
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann r = proxy_wait(p);
c74f883c6f7d5901b3c543d47f64082ccd91a895Lennart Poettering if (r == -ECONNRESET || r == -ENOTCONN)
c74f883c6f7d5901b3c543d47f64082ccd91a895Lennart Poettering return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann if (r < 0)
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return r;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann }
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann return 0;
c0395aeb903cde25bd9e81fba3334f63335fe0efDavid Herrmann}