bus-util.c revision 4d7859d173282e16bb75254c2b4ec14a915ef30b
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) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_append(reply, "b", *tristate > 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_get_owner_uid(bus, sender, &uid);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unsigned authorized = false, challenge = false;
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,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Treat no PK available as access denied */
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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) {
a3e7f417d72ba3251fd6b3a228a2721a4b725a03Zbigniew Jędrzejewski-Szmek _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void async_polkit_query_free(sd_bus *b, AsyncPolkitQuery *q) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (q->serial > 0 && b)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_send_with_reply_cancel(b, q->serial);
a3e7f417d72ba3251fd6b3a228a2721a4b725a03Zbigniew Jędrzejewski-Szmek sd_bus_message_unref(q->request);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _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,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_send_with_reply(bus, pk, async_polkit_callback, q, 0, &q->serial);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringvoid bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while ((q = hashmap_steal_first(registry)))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int bus_check_peercred(sd_bus *c) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering l = sizeof(struct ucred);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (l != sizeof(struct ucred))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (ucred.uid != 0 && ucred.uid != geteuid())
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint bus_open_system_systemd(sd_bus **_bus) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* If we are root, then let's talk directly to the system
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * instance, instead of going via the bus */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint bus_generic_print_property(const char *name, sd_bus_message *property, bool all) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_message_peek_type(property, &type, &contents);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *s;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_message_read_basic(property, type, &s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_message_read_basic(property, type, &b);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_message_read_basic(property, type, &u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Yes, heuristics! But we can change this check
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * should it turn out to not be sufficient */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char timestamp[FORMAT_TIMESTAMP_MAX], *t;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering t = format_timestamp(timestamp, sizeof(timestamp), u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering printf("%s=%llu\n", name, (unsigned long long) u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_message_read_basic(property, type, &u);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (strstr(name, "UMask") || strstr(name, "Mode"))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_message_read_basic(property, type, &i);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_message_read_basic(property, type, &d);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_message_peek_type(property, &tp, &cnt);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering while(sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (all || n > 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unsigned int i;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 0; i < n; i++)
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering if (all || n > 0) {
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering unsigned int i;
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering for (i = 0; i < n; i++)
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poetteringint bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_open_system_remote(host, bus);
554604b3073467af75dc94fac9e2343148603289Lennart Poettering r = sd_bus_open_system_container(host, bus);
554604b3073467af75dc94fac9e2343148603289Lennart Poettering assert_not_reached("Hmm, unknown transport type.");