bus-util.c revision abc5fe72503fcc30998334e73c5d8e58f9a9d85e
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/***
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2013 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering***/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/socket.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "sd-event.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "sd-bus.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "macro.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "def.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "bus-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int quit_callback(sd_bus *bus, sd_bus_message *m, void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_event *e = userdata;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(e);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_event_request_quit(e);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering return 1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint bus_async_unregister_and_quit(sd_event *e, sd_bus *bus, const char *name) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_free_ char *match = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(e);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering assert(name);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering r = asprintf(&match, "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameLost',arg0='%s'", name);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_add_match(bus, match, quit_callback, e);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_release_name(bus, name);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r != SD_BUS_NAME_RELEASED)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EIO;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t timeout) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bool exiting = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(e);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(bus);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(name);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen for (;;) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_event_get_state(e);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r == SD_EVENT_FINISHED)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen break;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_event_run(e, exiting ? (uint64_t) -1 : timeout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r == 0 && !exiting) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = bus_async_unregister_and_quit(e, bus, name);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering exiting = true;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenint bus_property_get_tristate(
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen sd_bus *bus,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const char *path,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const char *interface,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const char *property,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_message *reply,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_error *error,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int *tristate = userdata;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_message_append(reply, "b", *tristate > 0);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 1;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringint bus_verify_polkit(
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering sd_bus *bus,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering sd_bus_message *m,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering const char *action,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering bool interactive,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering bool *_challenge,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering sd_bus_error *e) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering const char *sender;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering uid_t uid;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering int r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(bus);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(m);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(action);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering sender = sd_bus_message_get_sender(m);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (!sender)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return -EBADMSG;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering r = sd_bus_get_owner_uid(bus, sender, &uid);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return r;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (uid == 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 1;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering#ifdef ENABLE_POLKIT
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering else {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen bool authorized = false, challenge = false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_call_method(
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering bus,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "org.freedesktop.PolicyKit1",
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering "/org/freedesktop/PolicyKit1/Authority",
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering "org.freedesktop.PolicyKit1.Authority",
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering "CheckAuthorization",
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering e,
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering &reply,
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering "(sa{sv})sa{ss}us",
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "system-bus-name", 1, "name", "s", sender,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering action,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering 0,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering interactive ? 1 : 0,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "");
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (r < 0) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering /* Treat no PK available as access denied */
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering sd_bus_error_free(e);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering return -EACCES;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering }
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_read(reply, "(bb)", &authorized, &challenge);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (authorized)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (_challenge) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *_challenge = challenge;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EACCES;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef ENABLE_POLKIT
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringtypedef struct AsyncPolkitQuery {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_message *request, *reply;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_message_handler_t callback;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering void *userdata;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint64_t serial;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering} AsyncPolkitQuery;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering AsyncPolkitQuery *q = userdata;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(reply);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(q);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering q->reply = sd_bus_message_ref(reply);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering q->serial = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m = sd_bus_message_ref(q->request);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_rewind(m, true);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = q->callback(bus, m, q->userdata);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void async_polkit_query_free(sd_bus *b, AsyncPolkitQuery *q) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!q)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering if (q->serial > 0 && b)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_send_with_reply_cancel(b, q->serial);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_message_unref(q->request);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen sd_bus_message_unref(q->reply);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen free(q);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#endif
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenint bus_verify_polkit_async(
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus *bus,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Hashmap **registry,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen sd_bus_message *m,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const char *action,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen bool interactive,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen sd_bus_error *error,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen sd_bus_message_handler_t callback,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen void *userdata) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef ENABLE_POLKIT
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering AsyncPolkitQuery *q;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const char *sender;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uid_t uid;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(registry);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(action);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering#ifdef ENABLE_POLKIT
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering q = hashmap_remove(*registry, m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (q) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bool authorized, challenge;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* This is the second invocation of this function, and
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * there's already a response from polkit, let's
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * process it */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(q->reply);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (sd_bus_message_is_method_error(q->reply, NULL)) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const sd_bus_error *e;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Treat no PK available as access denied */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (sd_bus_message_is_method_error(q->reply, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering async_polkit_query_free(bus, q);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EACCES;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen e = sd_bus_message_get_error(q->reply);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_error_copy(error, e);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_error_get_errno(e);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering async_polkit_query_free(bus, q);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r >= 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen async_polkit_query_free(bus, q);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (authorized)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EACCES;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sender = sd_bus_message_get_sender(m);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!sender)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EBADMSG;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_get_owner_uid(bus, sender, &uid);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (uid == 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef ENABLE_POLKIT
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_new_method_call(
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bus,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.PolicyKit1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "/org/freedesktop/PolicyKit1/Authority",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.PolicyKit1.Authority",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "CheckAuthorization",
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen &pk);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_append(
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering pk,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "(sa{sv})sa{ss}us",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "system-bus-name", 1, "name", "s", sender,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering action,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen 0,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering interactive ? 1 : 0,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen q = new0(AsyncPolkitQuery, 1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!q)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -ENOMEM;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen q->request = sd_bus_message_ref(m);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen q->callback = callback;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering q->userdata = userdata;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = hashmap_put(*registry, m, q);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering async_polkit_query_free(bus, q);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_send_with_reply(bus, pk, async_polkit_callback, q, 0, &q->serial);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EACCES;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenvoid bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef ENABLE_POLKIT
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen AsyncPolkitQuery *q;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen while ((q = hashmap_steal_first(registry)))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering async_polkit_query_free(bus, q);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen hashmap_free(registry);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#endif
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic int bus_check_peercred(sd_bus *c) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int fd;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen struct ucred ucred;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen socklen_t l;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(c);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen fd = sd_bus_get_fd(c);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(fd >= 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen l = sizeof(struct ucred);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("SO_PEERCRED failed: %m");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -errno;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (l != sizeof(struct ucred)) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error("SO_PEERCRED returned wrong size.");
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -E2BIG;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (ucred.uid != 0 && ucred.uid != geteuid())
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EPERM;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 1;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poetteringint bus_connect_system(sd_bus **_bus) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus *bus = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen bool private = true;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(_bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (geteuid() == 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* If we are root, then let's talk directly to the
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * system instance, instead of going via the bus */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_new(&bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_start(bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_open_system(&bus);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen private = false;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (private) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = bus_check_peercred(bus);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen sd_bus_unref(bus);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return -EACCES;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen *_bus = bus;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen