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>
32 #include "bus-error.h"
33 #include "bus-message.h"
35 #include "bus-internal.h"
37 static int quit_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
38 sd_event *e = userdata;
44 sd_event_request_quit(e);
48 int bus_async_unregister_and_quit(sd_event *e, sd_bus *bus, const char *name) {
49 _cleanup_free_ char *match = NULL;
56 r = asprintf(&match, "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameLost',arg0='%s'", name);
60 r = sd_bus_add_match(bus, match, quit_callback, e);
64 r = sd_bus_release_name(bus, name);
68 if (r != SD_BUS_NAME_RELEASED)
74 int bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t timeout) {
83 r = sd_event_get_state(e);
87 if (r == SD_EVENT_FINISHED)
90 r = sd_event_run(e, exiting ? (uint64_t) -1 : timeout);
94 if (r == 0 && !exiting) {
95 r = bus_async_unregister_and_quit(e, bus, name);
106 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
107 _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
108 int r, has_owner = 0;
113 r = sd_bus_call_method(c,
114 "org.freedesktop.DBus",
115 "/org/freedesktop/dbus",
116 "org.freedesktop.DBus",
125 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
127 return sd_bus_error_set_errno(error, r);
132 int bus_verify_polkit(
148 sender = sd_bus_message_get_sender(m);
152 r = sd_bus_get_owner_uid(bus, sender, &uid);
161 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
162 int authorized = false, challenge = false;
164 r = sd_bus_call_method(
166 "org.freedesktop.PolicyKit1",
167 "/org/freedesktop/PolicyKit1/Authority",
168 "org.freedesktop.PolicyKit1.Authority",
169 "CheckAuthorization",
173 "system-bus-name", 1, "name", "s", sender,
180 /* Treat no PK available as access denied */
181 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
182 sd_bus_error_free(e);
189 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
191 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
197 *_challenge = challenge;
208 typedef struct AsyncPolkitQuery {
209 sd_bus_message *request, *reply;
210 sd_bus_message_handler_t callback;
216 static void async_polkit_query_free(sd_bus *b, AsyncPolkitQuery *q) {
221 if (q->serial > 0 && b)
222 sd_bus_call_async_cancel(b, q->serial);
224 if (q->registry && q->request)
225 hashmap_remove(q->registry, q->request);
227 sd_bus_message_unref(q->request);
228 sd_bus_message_unref(q->reply);
233 static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
234 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
235 AsyncPolkitQuery *q = userdata;
242 q->reply = sd_bus_message_ref(reply);
245 r = sd_bus_message_rewind(q->request, true);
247 r = sd_bus_reply_method_errno(q->request, r, NULL);
251 r = q->callback(bus, q->request, q->userdata, &error_buffer);
252 r = bus_maybe_reply_error(q->request, r, &error_buffer);
255 async_polkit_query_free(bus, q);
261 int bus_verify_polkit_async(
268 sd_bus_message_handler_t callback,
272 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
285 q = hashmap_get(*registry, m);
287 int authorized, challenge;
289 /* This is the second invocation of this function, and
290 * there's already a response from polkit, let's
294 if (sd_bus_message_is_method_error(q->reply, NULL)) {
295 const sd_bus_error *e;
297 /* Copy error from polkit reply */
298 e = sd_bus_message_get_error(q->reply);
299 sd_bus_error_copy(error, e);
301 /* Treat no PK available as access denied */
302 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
305 return sd_bus_error_get_errno(e);
308 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
310 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
322 sender = sd_bus_message_get_sender(m);
326 r = sd_bus_get_owner_uid(bus, sender, &uid);
334 r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
338 r = sd_bus_message_new_method_call(
340 "org.freedesktop.PolicyKit1",
341 "/org/freedesktop/PolicyKit1/Authority",
342 "org.freedesktop.PolicyKit1.Authority",
343 "CheckAuthorization",
348 r = sd_bus_message_append(
351 "system-bus-name", 1, "name", "s", sender,
359 q = new0(AsyncPolkitQuery, 1);
363 q->request = sd_bus_message_ref(m);
364 q->callback = callback;
365 q->userdata = userdata;
367 r = hashmap_put(*registry, m, q);
369 async_polkit_query_free(bus, q);
373 q->registry = *registry;
375 r = sd_bus_call_async(bus, pk, async_polkit_callback, q, 0, &q->serial);
377 async_polkit_query_free(bus, q);
387 void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
391 while ((q = hashmap_steal_first(registry)))
392 async_polkit_query_free(bus, q);
394 hashmap_free(registry);
398 int bus_check_peercred(sd_bus *c) {
405 fd = sd_bus_get_fd(c);
409 l = sizeof(struct ucred);
410 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
413 if (l != sizeof(struct ucred))
416 if (ucred.uid != 0 && ucred.uid != geteuid())
422 int bus_open_system_systemd(sd_bus **_bus) {
423 _cleanup_bus_unref_ sd_bus *bus = NULL;
429 return sd_bus_open_system(_bus);
431 /* If we are root, then let's talk directly to the system
432 * instance, instead of going via the bus */
434 r = sd_bus_new(&bus);
438 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
442 r = sd_bus_start(bus);
446 r = bus_check_peercred(bus);
456 int bus_open_user_systemd(sd_bus **_bus) {
457 _cleanup_bus_unref_ sd_bus *bus = NULL;
458 _cleanup_free_ char *p = NULL;
462 /* If we are supposed to talk to the instance, try via
463 * XDG_RUNTIME_DIR first, then fallback to normal bus
468 e = secure_getenv("XDG_RUNTIME_DIR");
470 if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0)
474 r = sd_bus_new(&bus);
478 r = sd_bus_set_address(bus, p);
482 r = sd_bus_start(bus);
486 r = bus_check_peercred(bus);
496 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
498 const char *contents;
504 r = sd_bus_message_peek_type(property, &type, &contents);
510 case SD_BUS_TYPE_STRING: {
513 r = sd_bus_message_read_basic(property, type, &s);
517 if (all || !isempty(s))
518 printf("%s=%s\n", name, s);
523 case SD_BUS_TYPE_BOOLEAN: {
526 r = sd_bus_message_read_basic(property, type, &b);
530 printf("%s=%s\n", name, yes_no(b));
535 case SD_BUS_TYPE_UINT64: {
538 r = sd_bus_message_read_basic(property, type, &u);
542 /* Yes, heuristics! But we can change this check
543 * should it turn out to not be sufficient */
545 if (endswith(name, "Timestamp")) {
546 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
548 t = format_timestamp(timestamp, sizeof(timestamp), u);
550 printf("%s=%s\n", name, strempty(t));
552 } else if (strstr(name, "USec")) {
553 char timespan[FORMAT_TIMESPAN_MAX];
555 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
557 printf("%s=%llu\n", name, (unsigned long long) u);
562 case SD_BUS_TYPE_UINT32: {
565 r = sd_bus_message_read_basic(property, type, &u);
569 if (strstr(name, "UMask") || strstr(name, "Mode"))
570 printf("%s=%04o\n", name, u);
572 printf("%s=%u\n", name, (unsigned) u);
577 case SD_BUS_TYPE_INT32: {
580 r = sd_bus_message_read_basic(property, type, &i);
584 printf("%s=%i\n", name, (int) i);
588 case SD_BUS_TYPE_DOUBLE: {
591 r = sd_bus_message_read_basic(property, type, &d);
595 printf("%s=%g\n", name, d);
599 case SD_BUS_TYPE_ARRAY:
600 if (streq(contents, "s")) {
604 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
608 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
612 printf("%s%s", first ? "" : " ", str);
624 r = sd_bus_message_exit_container(property);
630 } else if (streq(contents, "y")) {
634 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
643 for (i = 0; i < n; i++)
644 printf("%02x", u[i]);
651 } else if (streq(contents, "u")) {
655 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
664 for (i = 0; i < n; i++)
665 printf("%08x", u[i]);
679 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
680 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
681 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
687 r = sd_bus_call_method(bus,
690 "org.freedesktop.DBus.Properties",
698 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
702 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
704 const char *contents;
706 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
710 if (!filter || strv_find(filter, name)) {
711 r = sd_bus_message_peek_type(reply, NULL, &contents);
715 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
719 r = bus_print_property(name, reply, all);
724 printf("%s=[unprintable]\n", name);
725 /* skip what we didn't read */
726 r = sd_bus_message_skip(reply, contents);
731 r = sd_bus_message_exit_container(reply);
735 r = sd_bus_message_skip(reply, "v");
740 r = sd_bus_message_exit_container(reply);
747 r = sd_bus_message_exit_container(reply);
754 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
755 sd_id128_t *p = userdata;
760 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
767 memcpy((*p).bytes, v, n);
774 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
778 r = sd_bus_message_peek_type(m, &type, NULL);
783 case SD_BUS_TYPE_STRING: {
788 r = sd_bus_message_read_basic(m, type, &s);
806 case SD_BUS_TYPE_ARRAY: {
807 _cleanup_strv_free_ char **l = NULL;
808 char ***p = userdata;
810 r = bus_message_read_strv_extend(m, &l);
821 case SD_BUS_TYPE_BOOLEAN: {
825 r = sd_bus_message_read_basic(m, type, &b);
834 case SD_BUS_TYPE_UINT32: {
836 uint32_t *p = userdata;
838 r = sd_bus_message_read_basic(m, type, &u);
847 case SD_BUS_TYPE_UINT64: {
849 uint64_t *p = userdata;
851 r = sd_bus_message_read_basic(m, type, &t);
867 int bus_map_all_properties(sd_bus *bus,
868 const char *destination,
870 const struct bus_properties_map *map,
872 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
873 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
881 r = sd_bus_call_method( bus,
884 "org.freedesktop.DBus.Properties",
892 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
896 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
897 const struct bus_properties_map *prop;
899 const char *contents;
903 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
907 for (i = 0, prop = NULL; map[i].member; i++)
908 if (streq(map[i].member, member)) {
914 r = sd_bus_message_peek_type(m, NULL, &contents);
918 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
922 v = (uint8_t *)userdata + prop->offset;
924 r = prop->set(bus, member, m, &error, v);
926 r = map_basic(bus, member, m, &error, v);
928 r = sd_bus_message_exit_container(m);
932 r = sd_bus_message_skip(m, "v");
937 r = sd_bus_message_exit_container(m);
945 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
948 assert(transport >= 0);
949 assert(transport < _BUS_TRANSPORT_MAX);
952 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
953 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
957 case BUS_TRANSPORT_LOCAL:
959 r = sd_bus_default_user(bus);
961 r = sd_bus_default_system(bus);
965 case BUS_TRANSPORT_REMOTE:
966 r = sd_bus_open_system_remote(host, bus);
969 case BUS_TRANSPORT_CONTAINER:
970 r = sd_bus_open_system_container(host, bus);
974 assert_not_reached("Hmm, unknown transport type.");
980 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
983 assert(transport >= 0);
984 assert(transport < _BUS_TRANSPORT_MAX);
987 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
988 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
992 case BUS_TRANSPORT_LOCAL:
994 r = bus_open_user_systemd(bus);
996 r = bus_open_system_systemd(bus);
1000 case BUS_TRANSPORT_REMOTE:
1001 r = sd_bus_open_system_remote(host, bus);
1004 case BUS_TRANSPORT_CONTAINER:
1005 r = sd_bus_open_system_container(host, bus);
1009 assert_not_reached("Hmm, unknown transport type.");
1015 int bus_property_get_tristate(
1018 const char *interface,
1019 const char *property,
1020 sd_bus_message *reply,
1022 sd_bus_error *error) {
1024 int *tristate = userdata;
1026 return sd_bus_message_append(reply, "b", *tristate > 0);
1029 int bus_property_get_bool(
1032 const char *interface,
1033 const char *property,
1034 sd_bus_message *reply,
1036 sd_bus_error *error) {
1038 int b = *(bool*) userdata;
1040 return sd_bus_message_append_basic(reply, 'b', &b);
1043 #if __SIZEOF_SIZE_T__ != 8
1044 int bus_property_get_size(
1047 const char *interface,
1048 const char *property,
1049 sd_bus_message *reply,
1051 sd_bus_error *error) {
1053 uint64_t sz = *(size_t*) userdata;
1055 return sd_bus_message_append_basic(reply, 't', &sz);
1059 #if __SIZEOF_LONG__ != 8
1060 int bus_property_get_long(
1063 const char *interface,
1064 const char *property,
1065 sd_bus_message *reply,
1067 sd_bus_error *error) {
1069 int64_t l = *(long*) userdata;
1071 return sd_bus_message_append_basic(reply, 'x', &l);
1074 int bus_property_get_ulong(
1077 const char *interface,
1078 const char *property,
1079 sd_bus_message *reply,
1081 sd_bus_error *error) {
1083 uint64_t ul = *(unsigned long*) userdata;
1085 return sd_bus_message_append_basic(reply, 't', &ul);
1089 int bus_log_parse_error(int r) {
1090 log_error("Failed to parse message: %s", strerror(-r));
1094 int bus_log_create_error(int r) {
1095 log_error("Failed to create message: %s", strerror(-r));
1099 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1103 return sd_bus_message_read(
1118 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1122 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1123 sd_bus_reply_method_errno(m, r, error);
1125 } else if (sd_bus_error_is_set(error)) {
1126 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1127 sd_bus_reply_method_error(m, error);
1131 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1132 bus_message_type_to_string(m->header->type),
1135 strna(m->interface),
1137 strna(m->root_container.signature),
1138 bus_error_message(error, r));