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(
938 "org.freedesktop.DBus.Properties",
946 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
950 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
951 const struct bus_properties_map *prop;
953 const char *contents;
957 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
961 for (i = 0, prop = NULL; map[i].member; i++)
962 if (streq(map[i].member, member)) {
968 r = sd_bus_message_peek_type(m, NULL, &contents);
972 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
976 v = (uint8_t *)userdata + prop->offset;
978 r = prop->set(bus, member, m, &error, v);
980 r = map_basic(bus, member, m, &error, v);
982 r = sd_bus_message_exit_container(m);
986 r = sd_bus_message_skip(m, "v");
991 r = sd_bus_message_exit_container(m);
999 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1002 assert(transport >= 0);
1003 assert(transport < _BUS_TRANSPORT_MAX);
1006 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1007 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1009 switch (transport) {
1011 case BUS_TRANSPORT_LOCAL:
1013 r = sd_bus_default_user(bus);
1015 r = sd_bus_default_system(bus);
1019 case BUS_TRANSPORT_REMOTE:
1020 r = sd_bus_open_system_remote(host, bus);
1023 case BUS_TRANSPORT_CONTAINER:
1024 r = sd_bus_open_system_container(host, bus);
1028 assert_not_reached("Hmm, unknown transport type.");
1034 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1037 assert(transport >= 0);
1038 assert(transport < _BUS_TRANSPORT_MAX);
1041 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1042 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1044 switch (transport) {
1046 case BUS_TRANSPORT_LOCAL:
1048 r = bus_open_user_systemd(bus);
1050 r = bus_open_system_systemd(bus);
1054 case BUS_TRANSPORT_REMOTE:
1055 r = sd_bus_open_system_remote(host, bus);
1058 case BUS_TRANSPORT_CONTAINER:
1059 r = sd_bus_open_system_container(host, bus);
1063 assert_not_reached("Hmm, unknown transport type.");
1069 int bus_property_get_tristate(
1072 const char *interface,
1073 const char *property,
1074 sd_bus_message *reply,
1076 sd_bus_error *error) {
1078 int *tristate = userdata;
1080 return sd_bus_message_append(reply, "b", *tristate > 0);
1083 int bus_property_get_bool(
1086 const char *interface,
1087 const char *property,
1088 sd_bus_message *reply,
1090 sd_bus_error *error) {
1092 int b = *(bool*) userdata;
1094 return sd_bus_message_append_basic(reply, 'b', &b);
1097 #if __SIZEOF_SIZE_T__ != 8
1098 int bus_property_get_size(
1101 const char *interface,
1102 const char *property,
1103 sd_bus_message *reply,
1105 sd_bus_error *error) {
1107 uint64_t sz = *(size_t*) userdata;
1109 return sd_bus_message_append_basic(reply, 't', &sz);
1113 #if __SIZEOF_LONG__ != 8
1114 int bus_property_get_long(
1117 const char *interface,
1118 const char *property,
1119 sd_bus_message *reply,
1121 sd_bus_error *error) {
1123 int64_t l = *(long*) userdata;
1125 return sd_bus_message_append_basic(reply, 'x', &l);
1128 int bus_property_get_ulong(
1131 const char *interface,
1132 const char *property,
1133 sd_bus_message *reply,
1135 sd_bus_error *error) {
1137 uint64_t ul = *(unsigned long*) userdata;
1139 return sd_bus_message_append_basic(reply, 't', &ul);
1143 int bus_log_parse_error(int r) {
1144 log_error("Failed to parse message: %s", strerror(-r));
1148 int bus_log_create_error(int r) {
1149 log_error("Failed to create message: %s", strerror(-r));
1153 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1157 return sd_bus_message_read(
1172 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1176 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1177 sd_bus_reply_method_errno(m, r, error);
1179 } else if (sd_bus_error_is_set(error)) {
1180 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1181 sd_bus_reply_method_error(m, error);
1185 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1186 bus_message_type_to_string(m->header->type),
1189 strna(m->interface),
1191 strna(m->root_container.signature),
1192 bus_error_message(error, r));