1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/socket.h>
23 #include <sys/capability.h>
33 #include "bus-error.h"
34 #include "bus-message.h"
36 #include "bus-internal.h"
38 static int quit_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
39 sd_event *e = userdata;
45 sd_event_request_quit(e);
49 int bus_async_unregister_and_quit(sd_event *e, sd_bus *bus, const char *name) {
50 _cleanup_free_ char *match = NULL;
57 r = asprintf(&match, "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameLost',arg0='%s'", name);
61 r = sd_bus_add_match(bus, match, quit_callback, e);
65 r = sd_bus_release_name(bus, name);
69 if (r != BUS_NAME_RELEASED)
75 int bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t timeout) {
84 r = sd_event_get_state(e);
88 if (r == SD_EVENT_FINISHED)
91 r = sd_event_run(e, exiting ? (uint64_t) -1 : timeout);
95 if (r == 0 && !exiting) {
96 r = bus_async_unregister_and_quit(e, bus, name);
107 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
108 _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
109 int r, has_owner = 0;
114 r = sd_bus_call_method(c,
115 "org.freedesktop.DBus",
116 "/org/freedesktop/dbus",
117 "org.freedesktop.DBus",
126 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
128 return sd_bus_error_set_errno(error, r);
133 int bus_verify_polkit(
141 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
149 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
153 r = sd_bus_creds_get_uid(creds, &uid);
162 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
163 int authorized = false, challenge = false;
166 sender = sd_bus_message_get_sender(m);
170 r = sd_bus_call_method(
172 "org.freedesktop.PolicyKit1",
173 "/org/freedesktop/PolicyKit1/Authority",
174 "org.freedesktop.PolicyKit1.Authority",
175 "CheckAuthorization",
179 "system-bus-name", 1, "name", "s", sender,
186 /* Treat no PK available as access denied */
187 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
188 sd_bus_error_free(e);
195 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
197 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
203 *_challenge = challenge;
214 typedef struct AsyncPolkitQuery {
215 sd_bus_message *request, *reply;
216 sd_bus_message_handler_t callback;
222 static void async_polkit_query_free(sd_bus *b, AsyncPolkitQuery *q) {
227 if (q->serial > 0 && b)
228 sd_bus_call_async_cancel(b, q->serial);
230 if (q->registry && q->request)
231 hashmap_remove(q->registry, q->request);
233 sd_bus_message_unref(q->request);
234 sd_bus_message_unref(q->reply);
239 static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
240 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
241 AsyncPolkitQuery *q = userdata;
248 q->reply = sd_bus_message_ref(reply);
251 r = sd_bus_message_rewind(q->request, true);
253 r = sd_bus_reply_method_errno(q->request, r, NULL);
257 r = q->callback(bus, q->request, q->userdata, &error_buffer);
258 r = bus_maybe_reply_error(q->request, r, &error_buffer);
261 async_polkit_query_free(bus, q);
267 int bus_verify_polkit_async(
274 sd_bus_message_handler_t callback,
278 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
282 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
292 q = hashmap_get(*registry, m);
294 int authorized, challenge;
296 /* This is the second invocation of this function, and
297 * there's already a response from polkit, let's
301 if (sd_bus_message_is_method_error(q->reply, NULL)) {
302 const sd_bus_error *e;
304 /* Copy error from polkit reply */
305 e = sd_bus_message_get_error(q->reply);
306 sd_bus_error_copy(error, e);
308 /* Treat no PK available as access denied */
309 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
312 return sd_bus_error_get_errno(e);
315 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
317 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
329 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
333 r = sd_bus_creds_get_uid(creds, &uid);
341 sender = sd_bus_message_get_sender(m);
345 r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
349 r = sd_bus_message_new_method_call(
351 "org.freedesktop.PolicyKit1",
352 "/org/freedesktop/PolicyKit1/Authority",
353 "org.freedesktop.PolicyKit1.Authority",
354 "CheckAuthorization",
359 r = sd_bus_message_append(
362 "system-bus-name", 1, "name", "s", sender,
370 q = new0(AsyncPolkitQuery, 1);
374 q->request = sd_bus_message_ref(m);
375 q->callback = callback;
376 q->userdata = userdata;
378 r = hashmap_put(*registry, m, q);
380 async_polkit_query_free(bus, q);
384 q->registry = *registry;
386 r = sd_bus_call_async(bus, pk, async_polkit_callback, q, 0, &q->serial);
388 async_polkit_query_free(bus, q);
398 void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
402 while ((q = hashmap_steal_first(registry)))
403 async_polkit_query_free(bus, q);
405 hashmap_free(registry);
409 int bus_check_peercred(sd_bus *c) {
416 fd = sd_bus_get_fd(c);
420 l = sizeof(struct ucred);
421 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
424 if (l != sizeof(struct ucred))
427 if (ucred.uid != 0 && ucred.uid != geteuid())
433 int bus_open_system_systemd(sd_bus **_bus) {
434 _cleanup_bus_unref_ sd_bus *bus = NULL;
440 return sd_bus_open_system(_bus);
442 /* If we are root and kdbus is not available, then let's talk
443 * directly to the system instance, instead of going via the
447 r = sd_bus_new(&bus);
451 r = sd_bus_set_address(bus, "kernel:path=/dev/kdbus/0-system/bus");
455 bus->bus_client = true;
457 r = sd_bus_start(bus);
464 bus = sd_bus_unref(bus);
467 r = sd_bus_new(&bus);
471 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
475 r = sd_bus_start(bus);
477 return sd_bus_open_system(_bus);
479 r = bus_check_peercred(bus);
489 int bus_open_user_systemd(sd_bus **_bus) {
490 _cleanup_bus_unref_ sd_bus *bus = NULL;
491 _cleanup_free_ char *ee = NULL;
495 /* Try via kdbus first, and then directly */
500 r = sd_bus_new(&bus);
504 if (asprintf(&bus->address, "kernel:path=/dev/kdbus/%lu-user/bus", (unsigned long) getuid()) < 0)
507 bus->bus_client = true;
509 r = sd_bus_start(bus);
516 bus = sd_bus_unref(bus);
519 e = secure_getenv("XDG_RUNTIME_DIR");
521 return sd_bus_open_system(_bus);
523 ee = bus_address_escape(e);
527 r = sd_bus_new(&bus);
531 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
535 r = sd_bus_start(bus);
537 return sd_bus_open_system(_bus);
539 r = bus_check_peercred(bus);
549 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
551 const char *contents;
557 r = sd_bus_message_peek_type(property, &type, &contents);
563 case SD_BUS_TYPE_STRING: {
566 r = sd_bus_message_read_basic(property, type, &s);
570 if (all || !isempty(s))
571 printf("%s=%s\n", name, s);
576 case SD_BUS_TYPE_BOOLEAN: {
579 r = sd_bus_message_read_basic(property, type, &b);
583 printf("%s=%s\n", name, yes_no(b));
588 case SD_BUS_TYPE_UINT64: {
591 r = sd_bus_message_read_basic(property, type, &u);
595 /* Yes, heuristics! But we can change this check
596 * should it turn out to not be sufficient */
598 if (endswith(name, "Timestamp")) {
599 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
601 t = format_timestamp(timestamp, sizeof(timestamp), u);
603 printf("%s=%s\n", name, strempty(t));
605 } else if (strstr(name, "USec")) {
606 char timespan[FORMAT_TIMESPAN_MAX];
608 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
610 printf("%s=%llu\n", name, (unsigned long long) u);
615 case SD_BUS_TYPE_UINT32: {
618 r = sd_bus_message_read_basic(property, type, &u);
622 if (strstr(name, "UMask") || strstr(name, "Mode"))
623 printf("%s=%04o\n", name, u);
625 printf("%s=%u\n", name, (unsigned) u);
630 case SD_BUS_TYPE_INT32: {
633 r = sd_bus_message_read_basic(property, type, &i);
637 printf("%s=%i\n", name, (int) i);
641 case SD_BUS_TYPE_DOUBLE: {
644 r = sd_bus_message_read_basic(property, type, &d);
648 printf("%s=%g\n", name, d);
652 case SD_BUS_TYPE_ARRAY:
653 if (streq(contents, "s")) {
657 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
661 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
665 printf("%s%s", first ? "" : " ", str);
677 r = sd_bus_message_exit_container(property);
683 } else if (streq(contents, "y")) {
687 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
696 for (i = 0; i < n; i++)
697 printf("%02x", u[i]);
704 } else if (streq(contents, "u")) {
708 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
717 for (i = 0; i < n; i++)
718 printf("%08x", u[i]);
732 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
733 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
734 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
740 r = sd_bus_call_method(bus,
743 "org.freedesktop.DBus.Properties",
751 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
755 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
757 const char *contents;
759 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
763 if (!filter || strv_find(filter, name)) {
764 r = sd_bus_message_peek_type(reply, NULL, &contents);
768 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
772 r = bus_print_property(name, reply, all);
777 printf("%s=[unprintable]\n", name);
778 /* skip what we didn't read */
779 r = sd_bus_message_skip(reply, contents);
784 r = sd_bus_message_exit_container(reply);
788 r = sd_bus_message_skip(reply, "v");
793 r = sd_bus_message_exit_container(reply);
800 r = sd_bus_message_exit_container(reply);
807 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
808 sd_id128_t *p = userdata;
813 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
820 memcpy((*p).bytes, v, n);
827 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
831 r = sd_bus_message_peek_type(m, &type, NULL);
836 case SD_BUS_TYPE_STRING: {
841 r = sd_bus_message_read_basic(m, type, &s);
859 case SD_BUS_TYPE_ARRAY: {
860 _cleanup_strv_free_ char **l = NULL;
861 char ***p = userdata;
863 r = bus_message_read_strv_extend(m, &l);
874 case SD_BUS_TYPE_BOOLEAN: {
878 r = sd_bus_message_read_basic(m, type, &b);
887 case SD_BUS_TYPE_UINT32: {
889 uint32_t *p = userdata;
891 r = sd_bus_message_read_basic(m, type, &u);
900 case SD_BUS_TYPE_UINT64: {
902 uint64_t *p = userdata;
904 r = sd_bus_message_read_basic(m, type, &t);
920 int bus_map_all_properties(sd_bus *bus,
921 const char *destination,
923 const struct bus_properties_map *map,
925 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
926 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
934 r = sd_bus_call_method( bus,
937 "org.freedesktop.DBus.Properties",
945 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
949 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
950 const struct bus_properties_map *prop;
952 const char *contents;
956 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
960 for (i = 0, prop = NULL; map[i].member; i++)
961 if (streq(map[i].member, member)) {
967 r = sd_bus_message_peek_type(m, NULL, &contents);
971 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
975 v = (uint8_t *)userdata + prop->offset;
977 r = prop->set(bus, member, m, &error, v);
979 r = map_basic(bus, member, m, &error, v);
981 r = sd_bus_message_exit_container(m);
985 r = sd_bus_message_skip(m, "v");
990 r = sd_bus_message_exit_container(m);
998 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1001 assert(transport >= 0);
1002 assert(transport < _BUS_TRANSPORT_MAX);
1005 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1006 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1008 switch (transport) {
1010 case BUS_TRANSPORT_LOCAL:
1012 r = sd_bus_default_user(bus);
1014 r = sd_bus_default_system(bus);
1018 case BUS_TRANSPORT_REMOTE:
1019 r = sd_bus_open_system_remote(host, bus);
1022 case BUS_TRANSPORT_CONTAINER:
1023 r = sd_bus_open_system_container(host, bus);
1027 assert_not_reached("Hmm, unknown transport type.");
1033 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1036 assert(transport >= 0);
1037 assert(transport < _BUS_TRANSPORT_MAX);
1040 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1041 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1043 switch (transport) {
1045 case BUS_TRANSPORT_LOCAL:
1047 r = bus_open_user_systemd(bus);
1049 r = bus_open_system_systemd(bus);
1053 case BUS_TRANSPORT_REMOTE:
1054 r = sd_bus_open_system_remote(host, bus);
1057 case BUS_TRANSPORT_CONTAINER:
1058 r = sd_bus_open_system_container(host, bus);
1062 assert_not_reached("Hmm, unknown transport type.");
1068 int bus_property_get_tristate(
1071 const char *interface,
1072 const char *property,
1073 sd_bus_message *reply,
1075 sd_bus_error *error) {
1077 int *tristate = userdata;
1079 return sd_bus_message_append(reply, "b", *tristate > 0);
1082 int bus_property_get_bool(
1085 const char *interface,
1086 const char *property,
1087 sd_bus_message *reply,
1089 sd_bus_error *error) {
1091 int b = *(bool*) userdata;
1093 return sd_bus_message_append_basic(reply, 'b', &b);
1096 #if __SIZEOF_SIZE_T__ != 8
1097 int bus_property_get_size(
1100 const char *interface,
1101 const char *property,
1102 sd_bus_message *reply,
1104 sd_bus_error *error) {
1106 uint64_t sz = *(size_t*) userdata;
1108 return sd_bus_message_append_basic(reply, 't', &sz);
1112 #if __SIZEOF_LONG__ != 8
1113 int bus_property_get_long(
1116 const char *interface,
1117 const char *property,
1118 sd_bus_message *reply,
1120 sd_bus_error *error) {
1122 int64_t l = *(long*) userdata;
1124 return sd_bus_message_append_basic(reply, 'x', &l);
1127 int bus_property_get_ulong(
1130 const char *interface,
1131 const char *property,
1132 sd_bus_message *reply,
1134 sd_bus_error *error) {
1136 uint64_t ul = *(unsigned long*) userdata;
1138 return sd_bus_message_append_basic(reply, 't', &ul);
1142 int bus_log_parse_error(int r) {
1143 log_error("Failed to parse message: %s", strerror(-r));
1147 int bus_log_create_error(int r) {
1148 log_error("Failed to create message: %s", strerror(-r));
1152 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1156 return sd_bus_message_read(
1171 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1175 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1176 sd_bus_reply_method_errno(m, r, error);
1178 } else if (sd_bus_error_is_set(error)) {
1179 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1180 sd_bus_reply_method_error(m, error);
1184 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1185 bus_message_type_to_string(m->header->type),
1188 strna(m->interface),
1190 strna(m->root_container.signature),
1191 bus_error_message(error, r));