bus-util.c revision abc5fe72503fcc30998334e73c5d8e58f9a9d85e
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2013 Lennart 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 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 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 Poetteringstatic int quit_callback(sd_bus *bus, sd_bus_message *m, void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint bus_async_unregister_and_quit(sd_event *e, sd_bus *bus, const char *name) {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering r = asprintf(&match, "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameLost',arg0='%s'", name);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_add_match(bus, match, quit_callback, e);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t timeout) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_event_run(e, exiting ? (uint64_t) -1 : timeout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r == 0 && !exiting) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = bus_async_unregister_and_quit(e, bus, name);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_message_append(reply, "b", *tristate > 0);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering r = sd_bus_get_owner_uid(bus, sender, &uid);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "org.freedesktop.PolicyKit1",
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering "org.freedesktop.PolicyKit1.Authority",
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering "CheckAuthorization",
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering "(sa{sv})sa{ss}us",
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "system-bus-name", 1, "name", "s", sender,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering /* Treat no PK available as access denied */
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_read(reply, "(bb)", &authorized, &challenge);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void async_polkit_query_free(sd_bus *b, AsyncPolkitQuery *q) {
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering if (q->serial > 0 && b)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_send_with_reply_cancel(b, q->serial);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
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 */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (sd_bus_message_is_method_error(q->reply, NULL)) {
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 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_get_owner_uid(bus, sender, &uid);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.PolicyKit1",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.PolicyKit1.Authority",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "CheckAuthorization",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "(sa{sv})sa{ss}us",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "system-bus-name", 1, "name", "s", sender,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = sd_bus_send_with_reply(bus, pk, async_polkit_callback, q, 0, &q->serial);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenvoid bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen l = sizeof(struct ucred);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (l != sizeof(struct ucred)) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error("SO_PEERCRED returned wrong size.");
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (ucred.uid != 0 && ucred.uid != geteuid())
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 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");