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;
58 r = sd_bus_get_unique_name(bus, &unique);
63 "sender='org.freedesktop.DBus',"
65 "interface='org.freedesktop.DBus',"
66 "member='NameOwnerChanged',"
67 "path='/org/freedesktop/DBus',"
70 "arg2=''", name, unique);
74 r = sd_bus_add_match(bus, match, quit_callback, e);
78 r = sd_bus_release_name(bus, name);
85 int bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t timeout) {
94 r = sd_event_get_state(e);
98 if (r == SD_EVENT_FINISHED)
101 r = sd_event_run(e, exiting ? (uint64_t) -1 : timeout);
105 if (r == 0 && !exiting) {
106 r = bus_async_unregister_and_quit(e, bus, name);
117 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
118 _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
119 int r, has_owner = 0;
124 r = sd_bus_call_method(c,
125 "org.freedesktop.DBus",
126 "/org/freedesktop/dbus",
127 "org.freedesktop.DBus",
136 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
138 return sd_bus_error_set_errno(error, r);
143 int bus_verify_polkit(
151 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
159 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
163 r = sd_bus_creds_get_uid(creds, &uid);
172 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
173 int authorized = false, challenge = false;
176 sender = sd_bus_message_get_sender(m);
180 r = sd_bus_call_method(
182 "org.freedesktop.PolicyKit1",
183 "/org/freedesktop/PolicyKit1/Authority",
184 "org.freedesktop.PolicyKit1.Authority",
185 "CheckAuthorization",
189 "system-bus-name", 1, "name", "s", sender,
196 /* Treat no PK available as access denied */
197 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
198 sd_bus_error_free(e);
205 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
207 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
213 *_challenge = challenge;
224 typedef struct AsyncPolkitQuery {
225 sd_bus_message *request, *reply;
226 sd_bus_message_handler_t callback;
232 static void async_polkit_query_free(sd_bus *b, AsyncPolkitQuery *q) {
237 if (q->serial > 0 && b)
238 sd_bus_call_async_cancel(b, q->serial);
240 if (q->registry && q->request)
241 hashmap_remove(q->registry, q->request);
243 sd_bus_message_unref(q->request);
244 sd_bus_message_unref(q->reply);
249 static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
250 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
251 AsyncPolkitQuery *q = userdata;
258 q->reply = sd_bus_message_ref(reply);
261 r = sd_bus_message_rewind(q->request, true);
263 r = sd_bus_reply_method_errno(q->request, r, NULL);
267 r = q->callback(bus, q->request, q->userdata, &error_buffer);
268 r = bus_maybe_reply_error(q->request, r, &error_buffer);
271 async_polkit_query_free(bus, q);
277 int bus_verify_polkit_async(
284 sd_bus_message_handler_t callback,
288 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
292 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
302 q = hashmap_get(*registry, m);
304 int authorized, challenge;
306 /* This is the second invocation of this function, and
307 * there's already a response from polkit, let's
311 if (sd_bus_message_is_method_error(q->reply, NULL)) {
312 const sd_bus_error *e;
314 /* Copy error from polkit reply */
315 e = sd_bus_message_get_error(q->reply);
316 sd_bus_error_copy(error, e);
318 /* Treat no PK available as access denied */
319 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
322 return sd_bus_error_get_errno(e);
325 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
327 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
339 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
343 r = sd_bus_creds_get_uid(creds, &uid);
351 sender = sd_bus_message_get_sender(m);
355 r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
359 r = sd_bus_message_new_method_call(
361 "org.freedesktop.PolicyKit1",
362 "/org/freedesktop/PolicyKit1/Authority",
363 "org.freedesktop.PolicyKit1.Authority",
364 "CheckAuthorization",
369 r = sd_bus_message_append(
372 "system-bus-name", 1, "name", "s", sender,
380 q = new0(AsyncPolkitQuery, 1);
384 q->request = sd_bus_message_ref(m);
385 q->callback = callback;
386 q->userdata = userdata;
388 r = hashmap_put(*registry, m, q);
390 async_polkit_query_free(bus, q);
394 q->registry = *registry;
396 r = sd_bus_call_async(bus, pk, async_polkit_callback, q, 0, &q->serial);
398 async_polkit_query_free(bus, q);
408 void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
412 while ((q = hashmap_steal_first(registry)))
413 async_polkit_query_free(bus, q);
415 hashmap_free(registry);
419 int bus_check_peercred(sd_bus *c) {
426 fd = sd_bus_get_fd(c);
430 l = sizeof(struct ucred);
431 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
434 if (l != sizeof(struct ucred))
437 if (ucred.uid != 0 && ucred.uid != geteuid())
443 int bus_open_system_systemd(sd_bus **_bus) {
444 _cleanup_bus_unref_ sd_bus *bus = NULL;
450 return sd_bus_open_system(_bus);
452 /* If we are root and kdbus is not available, then let's talk
453 * directly to the system instance, instead of going via the
457 r = sd_bus_new(&bus);
461 r = sd_bus_set_address(bus, "kernel:path=/dev/kdbus/0-system/bus");
465 bus->bus_client = true;
467 r = sd_bus_start(bus);
474 bus = sd_bus_unref(bus);
477 r = sd_bus_new(&bus);
481 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
485 r = sd_bus_start(bus);
487 return sd_bus_open_system(_bus);
489 r = bus_check_peercred(bus);
499 int bus_open_user_systemd(sd_bus **_bus) {
500 _cleanup_bus_unref_ sd_bus *bus = NULL;
501 _cleanup_free_ char *ee = NULL;
505 /* Try via kdbus first, and then directly */
510 r = sd_bus_new(&bus);
514 if (asprintf(&bus->address, "kernel:path=/dev/kdbus/%lu-user/bus", (unsigned long) getuid()) < 0)
517 bus->bus_client = true;
519 r = sd_bus_start(bus);
526 bus = sd_bus_unref(bus);
529 e = secure_getenv("XDG_RUNTIME_DIR");
531 return sd_bus_open_system(_bus);
533 ee = bus_address_escape(e);
537 r = sd_bus_new(&bus);
541 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
545 r = sd_bus_start(bus);
547 return sd_bus_open_system(_bus);
549 r = bus_check_peercred(bus);
559 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
561 const char *contents;
567 r = sd_bus_message_peek_type(property, &type, &contents);
573 case SD_BUS_TYPE_STRING: {
576 r = sd_bus_message_read_basic(property, type, &s);
580 if (all || !isempty(s))
581 printf("%s=%s\n", name, s);
586 case SD_BUS_TYPE_BOOLEAN: {
589 r = sd_bus_message_read_basic(property, type, &b);
593 printf("%s=%s\n", name, yes_no(b));
598 case SD_BUS_TYPE_UINT64: {
601 r = sd_bus_message_read_basic(property, type, &u);
605 /* Yes, heuristics! But we can change this check
606 * should it turn out to not be sufficient */
608 if (endswith(name, "Timestamp")) {
609 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
611 t = format_timestamp(timestamp, sizeof(timestamp), u);
613 printf("%s=%s\n", name, strempty(t));
615 } else if (strstr(name, "USec")) {
616 char timespan[FORMAT_TIMESPAN_MAX];
618 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
620 printf("%s=%llu\n", name, (unsigned long long) u);
625 case SD_BUS_TYPE_UINT32: {
628 r = sd_bus_message_read_basic(property, type, &u);
632 if (strstr(name, "UMask") || strstr(name, "Mode"))
633 printf("%s=%04o\n", name, u);
635 printf("%s=%u\n", name, (unsigned) u);
640 case SD_BUS_TYPE_INT32: {
643 r = sd_bus_message_read_basic(property, type, &i);
647 printf("%s=%i\n", name, (int) i);
651 case SD_BUS_TYPE_DOUBLE: {
654 r = sd_bus_message_read_basic(property, type, &d);
658 printf("%s=%g\n", name, d);
662 case SD_BUS_TYPE_ARRAY:
663 if (streq(contents, "s")) {
667 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
671 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
675 printf("%s%s", first ? "" : " ", str);
687 r = sd_bus_message_exit_container(property);
693 } else if (streq(contents, "y")) {
697 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
706 for (i = 0; i < n; i++)
707 printf("%02x", u[i]);
714 } else if (streq(contents, "u")) {
718 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
727 for (i = 0; i < n; i++)
728 printf("%08x", u[i]);
742 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
743 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
744 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
750 r = sd_bus_call_method(bus,
753 "org.freedesktop.DBus.Properties",
761 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
765 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
767 const char *contents;
769 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
773 if (!filter || strv_find(filter, name)) {
774 r = sd_bus_message_peek_type(reply, NULL, &contents);
778 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
782 r = bus_print_property(name, reply, all);
787 printf("%s=[unprintable]\n", name);
788 /* skip what we didn't read */
789 r = sd_bus_message_skip(reply, contents);
794 r = sd_bus_message_exit_container(reply);
798 r = sd_bus_message_skip(reply, "v");
803 r = sd_bus_message_exit_container(reply);
810 r = sd_bus_message_exit_container(reply);
817 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
818 sd_id128_t *p = userdata;
823 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
830 memcpy((*p).bytes, v, n);
837 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
841 r = sd_bus_message_peek_type(m, &type, NULL);
846 case SD_BUS_TYPE_STRING: {
851 r = sd_bus_message_read_basic(m, type, &s);
869 case SD_BUS_TYPE_ARRAY: {
870 _cleanup_strv_free_ char **l = NULL;
871 char ***p = userdata;
873 r = bus_message_read_strv_extend(m, &l);
884 case SD_BUS_TYPE_BOOLEAN: {
888 r = sd_bus_message_read_basic(m, type, &b);
897 case SD_BUS_TYPE_UINT32: {
899 uint32_t *p = userdata;
901 r = sd_bus_message_read_basic(m, type, &u);
910 case SD_BUS_TYPE_UINT64: {
912 uint64_t *p = userdata;
914 r = sd_bus_message_read_basic(m, type, &t);
930 int bus_map_all_properties(sd_bus *bus,
931 const char *destination,
933 const struct bus_properties_map *map,
935 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
936 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
944 r = sd_bus_call_method(
948 "org.freedesktop.DBus.Properties",
956 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
960 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
961 const struct bus_properties_map *prop;
963 const char *contents;
967 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
971 for (i = 0, prop = NULL; map[i].member; i++)
972 if (streq(map[i].member, member)) {
978 r = sd_bus_message_peek_type(m, NULL, &contents);
982 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
986 v = (uint8_t *)userdata + prop->offset;
988 r = prop->set(bus, member, m, &error, v);
990 r = map_basic(bus, member, m, &error, v);
992 r = sd_bus_message_exit_container(m);
996 r = sd_bus_message_skip(m, "v");
1001 r = sd_bus_message_exit_container(m);
1009 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1012 assert(transport >= 0);
1013 assert(transport < _BUS_TRANSPORT_MAX);
1016 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1017 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1019 switch (transport) {
1021 case BUS_TRANSPORT_LOCAL:
1023 r = sd_bus_default_user(bus);
1025 r = sd_bus_default_system(bus);
1029 case BUS_TRANSPORT_REMOTE:
1030 r = sd_bus_open_system_remote(host, bus);
1033 case BUS_TRANSPORT_CONTAINER:
1034 r = sd_bus_open_system_container(host, bus);
1038 assert_not_reached("Hmm, unknown transport type.");
1044 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1047 assert(transport >= 0);
1048 assert(transport < _BUS_TRANSPORT_MAX);
1051 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1052 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1054 switch (transport) {
1056 case BUS_TRANSPORT_LOCAL:
1058 r = bus_open_user_systemd(bus);
1060 r = bus_open_system_systemd(bus);
1064 case BUS_TRANSPORT_REMOTE:
1065 r = sd_bus_open_system_remote(host, bus);
1068 case BUS_TRANSPORT_CONTAINER:
1069 r = sd_bus_open_system_container(host, bus);
1073 assert_not_reached("Hmm, unknown transport type.");
1079 int bus_property_get_tristate(
1082 const char *interface,
1083 const char *property,
1084 sd_bus_message *reply,
1086 sd_bus_error *error) {
1088 int *tristate = userdata;
1090 return sd_bus_message_append(reply, "b", *tristate > 0);
1093 int bus_property_get_bool(
1096 const char *interface,
1097 const char *property,
1098 sd_bus_message *reply,
1100 sd_bus_error *error) {
1102 int b = *(bool*) userdata;
1104 return sd_bus_message_append_basic(reply, 'b', &b);
1107 #if __SIZEOF_SIZE_T__ != 8
1108 int bus_property_get_size(
1111 const char *interface,
1112 const char *property,
1113 sd_bus_message *reply,
1115 sd_bus_error *error) {
1117 uint64_t sz = *(size_t*) userdata;
1119 return sd_bus_message_append_basic(reply, 't', &sz);
1123 #if __SIZEOF_LONG__ != 8
1124 int bus_property_get_long(
1127 const char *interface,
1128 const char *property,
1129 sd_bus_message *reply,
1131 sd_bus_error *error) {
1133 int64_t l = *(long*) userdata;
1135 return sd_bus_message_append_basic(reply, 'x', &l);
1138 int bus_property_get_ulong(
1141 const char *interface,
1142 const char *property,
1143 sd_bus_message *reply,
1145 sd_bus_error *error) {
1147 uint64_t ul = *(unsigned long*) userdata;
1149 return sd_bus_message_append_basic(reply, 't', &ul);
1153 int bus_log_parse_error(int r) {
1154 log_error("Failed to parse message: %s", strerror(-r));
1158 int bus_log_create_error(int r) {
1159 log_error("Failed to create message: %s", strerror(-r));
1163 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1167 return sd_bus_message_read(
1182 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1186 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1187 sd_bus_reply_method_errno(m, r, error);
1189 } else if (sd_bus_error_is_set(error)) {
1190 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1191 sd_bus_reply_method_error(m, error);
1195 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1196 bus_message_type_to_string(m->header->type),
1199 strna(m->interface),
1201 strna(m->root_container.signature),
1202 bus_error_message(error, r));