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 name_owner_change_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
39 sd_event *e = userdata;
49 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
50 _cleanup_free_ char *match = NULL;
58 /* We unregister the name here and then wait for the
59 * NameOwnerChanged signal for this event to arrive before we
60 * quit. We do this in order to make sure that any queued
61 * requests are still processed before we really exit. */
63 r = sd_bus_get_unique_name(bus, &unique);
68 "sender='org.freedesktop.DBus',"
70 "interface='org.freedesktop.DBus',"
71 "member='NameOwnerChanged',"
72 "path='/org/freedesktop/DBus',"
75 "arg2=''", name, unique);
79 r = sd_bus_add_match(bus, match, name_owner_change_callback, e);
83 r = sd_bus_release_name(bus, name);
90 int bus_event_loop_with_idle(
95 check_idle_t check_idle,
107 r = sd_event_get_state(e);
110 if (r == SD_EVENT_FINISHED)
114 idle = check_idle(userdata);
118 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
122 if (r == 0 && !exiting) {
123 r = bus_async_unregister_and_exit(e, bus, name);
131 r = sd_event_get_exit_code(e, &code);
138 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
139 _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
140 int r, has_owner = 0;
145 r = sd_bus_call_method(c,
146 "org.freedesktop.DBus",
147 "/org/freedesktop/dbus",
148 "org.freedesktop.DBus",
157 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
159 return sd_bus_error_set_errno(error, r);
164 int bus_verify_polkit(
172 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
180 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
184 r = sd_bus_creds_get_uid(creds, &uid);
193 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
194 int authorized = false, challenge = false;
197 sender = sd_bus_message_get_sender(m);
201 r = sd_bus_call_method(
203 "org.freedesktop.PolicyKit1",
204 "/org/freedesktop/PolicyKit1/Authority",
205 "org.freedesktop.PolicyKit1.Authority",
206 "CheckAuthorization",
210 "system-bus-name", 1, "name", "s", sender,
217 /* Treat no PK available as access denied */
218 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
219 sd_bus_error_free(e);
226 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
230 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
238 *_challenge = challenge;
249 typedef struct AsyncPolkitQuery {
250 sd_bus_message *request, *reply;
251 sd_bus_message_handler_t callback;
257 static void async_polkit_query_free(sd_bus *b, AsyncPolkitQuery *q) {
262 if (q->serial > 0 && b)
263 sd_bus_call_async_cancel(b, q->serial);
265 if (q->registry && q->request)
266 hashmap_remove(q->registry, q->request);
268 sd_bus_message_unref(q->request);
269 sd_bus_message_unref(q->reply);
274 static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
275 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
276 AsyncPolkitQuery *q = userdata;
283 q->reply = sd_bus_message_ref(reply);
286 r = sd_bus_message_rewind(q->request, true);
288 r = sd_bus_reply_method_errno(q->request, r, NULL);
292 r = q->callback(bus, q->request, q->userdata, &error_buffer);
293 r = bus_maybe_reply_error(q->request, r, &error_buffer);
296 async_polkit_query_free(bus, q);
302 int bus_verify_polkit_async(
309 sd_bus_message_handler_t callback,
313 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
317 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
327 q = hashmap_get(*registry, m);
329 int authorized, challenge;
331 /* This is the second invocation of this function, and
332 * there's already a response from polkit, let's
336 if (sd_bus_message_is_method_error(q->reply, NULL)) {
337 const sd_bus_error *e;
339 /* Copy error from polkit reply */
340 e = sd_bus_message_get_error(q->reply);
341 sd_bus_error_copy(error, e);
343 /* Treat no PK available as access denied */
344 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
347 return -sd_bus_error_get_errno(e);
350 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
352 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
364 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
368 r = sd_bus_creds_get_uid(creds, &uid);
376 sender = sd_bus_message_get_sender(m);
380 r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
384 r = sd_bus_message_new_method_call(
386 "org.freedesktop.PolicyKit1",
387 "/org/freedesktop/PolicyKit1/Authority",
388 "org.freedesktop.PolicyKit1.Authority",
389 "CheckAuthorization",
394 r = sd_bus_message_append(
397 "system-bus-name", 1, "name", "s", sender,
405 q = new0(AsyncPolkitQuery, 1);
409 q->request = sd_bus_message_ref(m);
410 q->callback = callback;
411 q->userdata = userdata;
413 r = hashmap_put(*registry, m, q);
415 async_polkit_query_free(bus, q);
419 q->registry = *registry;
421 r = sd_bus_call_async(bus, pk, async_polkit_callback, q, 0, &q->serial);
423 async_polkit_query_free(bus, q);
433 void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
437 while ((q = hashmap_steal_first(registry)))
438 async_polkit_query_free(bus, q);
440 hashmap_free(registry);
444 int bus_check_peercred(sd_bus *c) {
451 fd = sd_bus_get_fd(c);
455 l = sizeof(struct ucred);
456 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
459 if (l != sizeof(struct ucred))
462 if (ucred.uid != 0 && ucred.uid != geteuid())
468 int bus_open_system_systemd(sd_bus **_bus) {
469 _cleanup_bus_unref_ sd_bus *bus = NULL;
475 return sd_bus_open_system(_bus);
477 /* If we are root and kdbus is not available, then let's talk
478 * directly to the system instance, instead of going via the
482 r = sd_bus_new(&bus);
486 r = sd_bus_set_address(bus, "kernel:path=/dev/kdbus/0-system/bus");
490 bus->bus_client = true;
492 r = sd_bus_start(bus);
499 bus = sd_bus_unref(bus);
502 r = sd_bus_new(&bus);
506 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
510 r = sd_bus_start(bus);
512 return sd_bus_open_system(_bus);
514 r = bus_check_peercred(bus);
524 int bus_open_user_systemd(sd_bus **_bus) {
525 _cleanup_bus_unref_ sd_bus *bus = NULL;
526 _cleanup_free_ char *ee = NULL;
530 /* Try via kdbus first, and then directly */
535 r = sd_bus_new(&bus);
539 if (asprintf(&bus->address, "kernel:path=/dev/kdbus/%lu-user/bus", (unsigned long) getuid()) < 0)
542 bus->bus_client = true;
544 r = sd_bus_start(bus);
551 bus = sd_bus_unref(bus);
554 e = secure_getenv("XDG_RUNTIME_DIR");
556 return sd_bus_open_system(_bus);
558 ee = bus_address_escape(e);
562 r = sd_bus_new(&bus);
566 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
570 r = sd_bus_start(bus);
572 return sd_bus_open_system(_bus);
574 r = bus_check_peercred(bus);
584 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
586 const char *contents;
592 r = sd_bus_message_peek_type(property, &type, &contents);
598 case SD_BUS_TYPE_STRING: {
601 r = sd_bus_message_read_basic(property, type, &s);
605 if (all || !isempty(s))
606 printf("%s=%s\n", name, s);
611 case SD_BUS_TYPE_BOOLEAN: {
614 r = sd_bus_message_read_basic(property, type, &b);
618 printf("%s=%s\n", name, yes_no(b));
623 case SD_BUS_TYPE_UINT64: {
626 r = sd_bus_message_read_basic(property, type, &u);
630 /* Yes, heuristics! But we can change this check
631 * should it turn out to not be sufficient */
633 if (endswith(name, "Timestamp")) {
634 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
636 t = format_timestamp(timestamp, sizeof(timestamp), u);
638 printf("%s=%s\n", name, strempty(t));
640 } else if (strstr(name, "USec")) {
641 char timespan[FORMAT_TIMESPAN_MAX];
643 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
645 printf("%s=%llu\n", name, (unsigned long long) u);
650 case SD_BUS_TYPE_UINT32: {
653 r = sd_bus_message_read_basic(property, type, &u);
657 if (strstr(name, "UMask") || strstr(name, "Mode"))
658 printf("%s=%04o\n", name, u);
660 printf("%s=%u\n", name, (unsigned) u);
665 case SD_BUS_TYPE_INT32: {
668 r = sd_bus_message_read_basic(property, type, &i);
672 printf("%s=%i\n", name, (int) i);
676 case SD_BUS_TYPE_DOUBLE: {
679 r = sd_bus_message_read_basic(property, type, &d);
683 printf("%s=%g\n", name, d);
687 case SD_BUS_TYPE_ARRAY:
688 if (streq(contents, "s")) {
692 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
696 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
700 printf("%s%s", first ? "" : " ", str);
712 r = sd_bus_message_exit_container(property);
718 } else if (streq(contents, "y")) {
722 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
731 for (i = 0; i < n; i++)
732 printf("%02x", u[i]);
739 } else if (streq(contents, "u")) {
743 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
752 for (i = 0; i < n; i++)
753 printf("%08x", u[i]);
767 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
768 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
769 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
775 r = sd_bus_call_method(bus,
778 "org.freedesktop.DBus.Properties",
786 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
790 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
792 const char *contents;
794 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
798 if (!filter || strv_find(filter, name)) {
799 r = sd_bus_message_peek_type(reply, NULL, &contents);
803 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
807 r = bus_print_property(name, reply, all);
812 printf("%s=[unprintable]\n", name);
813 /* skip what we didn't read */
814 r = sd_bus_message_skip(reply, contents);
819 r = sd_bus_message_exit_container(reply);
823 r = sd_bus_message_skip(reply, "v");
828 r = sd_bus_message_exit_container(reply);
835 r = sd_bus_message_exit_container(reply);
842 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
843 sd_id128_t *p = userdata;
848 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
855 memcpy((*p).bytes, v, n);
862 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
866 r = sd_bus_message_peek_type(m, &type, NULL);
871 case SD_BUS_TYPE_STRING: {
876 r = sd_bus_message_read_basic(m, type, &s);
894 case SD_BUS_TYPE_ARRAY: {
895 _cleanup_strv_free_ char **l = NULL;
896 char ***p = userdata;
898 r = bus_message_read_strv_extend(m, &l);
909 case SD_BUS_TYPE_BOOLEAN: {
913 r = sd_bus_message_read_basic(m, type, &b);
922 case SD_BUS_TYPE_UINT32: {
924 uint32_t *p = userdata;
926 r = sd_bus_message_read_basic(m, type, &u);
935 case SD_BUS_TYPE_UINT64: {
937 uint64_t *p = userdata;
939 r = sd_bus_message_read_basic(m, type, &t);
955 int bus_map_all_properties(sd_bus *bus,
956 const char *destination,
958 const struct bus_properties_map *map,
960 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
961 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
969 r = sd_bus_call_method(
973 "org.freedesktop.DBus.Properties",
981 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
985 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
986 const struct bus_properties_map *prop;
988 const char *contents;
992 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
996 for (i = 0, prop = NULL; map[i].member; i++)
997 if (streq(map[i].member, member)) {
1003 r = sd_bus_message_peek_type(m, NULL, &contents);
1007 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1011 v = (uint8_t *)userdata + prop->offset;
1013 r = prop->set(bus, member, m, &error, v);
1015 r = map_basic(bus, member, m, &error, v);
1019 r = sd_bus_message_exit_container(m);
1023 r = sd_bus_message_skip(m, "v");
1028 r = sd_bus_message_exit_container(m);
1036 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1039 assert(transport >= 0);
1040 assert(transport < _BUS_TRANSPORT_MAX);
1043 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1044 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1046 switch (transport) {
1048 case BUS_TRANSPORT_LOCAL:
1050 r = sd_bus_default_user(bus);
1052 r = sd_bus_default_system(bus);
1056 case BUS_TRANSPORT_REMOTE:
1057 r = sd_bus_open_system_remote(host, bus);
1060 case BUS_TRANSPORT_CONTAINER:
1061 r = sd_bus_open_system_container(host, bus);
1065 assert_not_reached("Hmm, unknown transport type.");
1071 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1074 assert(transport >= 0);
1075 assert(transport < _BUS_TRANSPORT_MAX);
1078 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1079 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1081 switch (transport) {
1083 case BUS_TRANSPORT_LOCAL:
1085 r = bus_open_user_systemd(bus);
1087 r = bus_open_system_systemd(bus);
1091 case BUS_TRANSPORT_REMOTE:
1092 r = sd_bus_open_system_remote(host, bus);
1095 case BUS_TRANSPORT_CONTAINER:
1096 r = sd_bus_open_system_container(host, bus);
1100 assert_not_reached("Hmm, unknown transport type.");
1106 int bus_property_get_tristate(
1109 const char *interface,
1110 const char *property,
1111 sd_bus_message *reply,
1113 sd_bus_error *error) {
1115 int *tristate = userdata;
1117 return sd_bus_message_append(reply, "b", *tristate > 0);
1120 int bus_property_get_bool(
1123 const char *interface,
1124 const char *property,
1125 sd_bus_message *reply,
1127 sd_bus_error *error) {
1129 int b = *(bool*) userdata;
1131 return sd_bus_message_append_basic(reply, 'b', &b);
1134 #if __SIZEOF_SIZE_T__ != 8
1135 int bus_property_get_size(
1138 const char *interface,
1139 const char *property,
1140 sd_bus_message *reply,
1142 sd_bus_error *error) {
1144 uint64_t sz = *(size_t*) userdata;
1146 return sd_bus_message_append_basic(reply, 't', &sz);
1150 #if __SIZEOF_LONG__ != 8
1151 int bus_property_get_long(
1154 const char *interface,
1155 const char *property,
1156 sd_bus_message *reply,
1158 sd_bus_error *error) {
1160 int64_t l = *(long*) userdata;
1162 return sd_bus_message_append_basic(reply, 'x', &l);
1165 int bus_property_get_ulong(
1168 const char *interface,
1169 const char *property,
1170 sd_bus_message *reply,
1172 sd_bus_error *error) {
1174 uint64_t ul = *(unsigned long*) userdata;
1176 return sd_bus_message_append_basic(reply, 't', &ul);
1180 int bus_log_parse_error(int r) {
1181 log_error("Failed to parse message: %s", strerror(-r));
1185 int bus_log_create_error(int r) {
1186 log_error("Failed to create message: %s", strerror(-r));
1190 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1194 return sd_bus_message_read(
1209 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1213 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1214 sd_bus_reply_method_errno(m, r, error);
1216 } else if (sd_bus_error_is_set(error)) {
1217 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1218 sd_bus_reply_method_error(m, error);
1222 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1223 bus_message_type_to_string(m->header->type),
1226 strna(m->interface),
1228 strna(m->root_container.signature),
1229 bus_error_message(error, r));