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_verify_polkit(
122 sender = sd_bus_message_get_sender(m);
126 r = sd_bus_get_owner_uid(bus, sender, &uid);
135 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
136 int authorized = false, challenge = false;
138 r = sd_bus_call_method(
140 "org.freedesktop.PolicyKit1",
141 "/org/freedesktop/PolicyKit1/Authority",
142 "org.freedesktop.PolicyKit1.Authority",
143 "CheckAuthorization",
147 "system-bus-name", 1, "name", "s", sender,
154 /* Treat no PK available as access denied */
155 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
156 sd_bus_error_free(e);
163 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
165 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
171 *_challenge = challenge;
182 typedef struct AsyncPolkitQuery {
183 sd_bus_message *request, *reply;
184 sd_bus_message_handler_t callback;
190 static void async_polkit_query_free(sd_bus *b, AsyncPolkitQuery *q) {
195 if (q->serial > 0 && b)
196 sd_bus_call_async_cancel(b, q->serial);
198 if (q->registry && q->request)
199 hashmap_remove(q->registry, q->request);
201 sd_bus_message_unref(q->request);
202 sd_bus_message_unref(q->reply);
207 static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
208 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
209 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
210 AsyncPolkitQuery *q = userdata;
217 q->reply = sd_bus_message_ref(reply);
220 r = sd_bus_message_rewind(q->request, true);
222 r = sd_bus_reply_method_errno(q->request, r, NULL);
226 r = q->callback(bus, q->request, q->userdata, &error_buffer);
227 r = bus_maybe_reply_error(q->request, r, &error_buffer);
230 async_polkit_query_free(bus, q);
236 int bus_verify_polkit_async(
243 sd_bus_message_handler_t callback,
247 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
260 q = hashmap_get(*registry, m);
262 int authorized, challenge;
264 /* This is the second invocation of this function, and
265 * there's already a response from polkit, let's
269 if (sd_bus_message_is_method_error(q->reply, NULL)) {
270 const sd_bus_error *e;
272 /* Copy error from polkit reply */
273 e = sd_bus_message_get_error(q->reply);
274 sd_bus_error_copy(error, e);
276 /* Treat no PK available as access denied */
277 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
280 return sd_bus_error_get_errno(e);
283 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
285 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
297 sender = sd_bus_message_get_sender(m);
301 r = sd_bus_get_owner_uid(bus, sender, &uid);
309 r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
313 r = sd_bus_message_new_method_call(
315 "org.freedesktop.PolicyKit1",
316 "/org/freedesktop/PolicyKit1/Authority",
317 "org.freedesktop.PolicyKit1.Authority",
318 "CheckAuthorization",
323 r = sd_bus_message_append(
326 "system-bus-name", 1, "name", "s", sender,
334 q = new0(AsyncPolkitQuery, 1);
338 q->request = sd_bus_message_ref(m);
339 q->callback = callback;
340 q->userdata = userdata;
342 r = hashmap_put(*registry, m, q);
344 async_polkit_query_free(bus, q);
348 q->registry = *registry;
350 r = sd_bus_call_async(bus, pk, async_polkit_callback, q, 0, &q->serial);
352 async_polkit_query_free(bus, q);
362 void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
366 while ((q = hashmap_steal_first(registry)))
367 async_polkit_query_free(bus, q);
369 hashmap_free(registry);
373 int bus_check_peercred(sd_bus *c) {
380 fd = sd_bus_get_fd(c);
384 l = sizeof(struct ucred);
385 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
388 if (l != sizeof(struct ucred))
391 if (ucred.uid != 0 && ucred.uid != geteuid())
397 int bus_open_system_systemd(sd_bus **_bus) {
398 _cleanup_bus_unref_ sd_bus *bus = NULL;
404 return sd_bus_open_system(_bus);
406 /* If we are root, then let's talk directly to the system
407 * instance, instead of going via the bus */
409 r = sd_bus_new(&bus);
413 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
417 r = sd_bus_start(bus);
421 r = bus_check_peercred(bus);
431 int bus_open_user_systemd(sd_bus **_bus) {
432 _cleanup_bus_unref_ sd_bus *bus = NULL;
433 _cleanup_free_ char *p = NULL;
437 /* If we are supposed to talk to the instance, try via
438 * XDG_RUNTIME_DIR first, then fallback to normal bus
443 e = secure_getenv("XDG_RUNTIME_DIR");
445 if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0)
449 r = sd_bus_new(&bus);
453 r = sd_bus_set_address(bus, p);
457 r = sd_bus_start(bus);
461 r = bus_check_peercred(bus);
471 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
473 const char *contents;
479 r = sd_bus_message_peek_type(property, &type, &contents);
485 case SD_BUS_TYPE_STRING: {
488 r = sd_bus_message_read_basic(property, type, &s);
492 if (all || !isempty(s))
493 printf("%s=%s\n", name, s);
498 case SD_BUS_TYPE_BOOLEAN: {
501 r = sd_bus_message_read_basic(property, type, &b);
505 printf("%s=%s\n", name, yes_no(b));
510 case SD_BUS_TYPE_UINT64: {
513 r = sd_bus_message_read_basic(property, type, &u);
517 /* Yes, heuristics! But we can change this check
518 * should it turn out to not be sufficient */
520 if (endswith(name, "Timestamp")) {
521 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
523 t = format_timestamp(timestamp, sizeof(timestamp), u);
525 printf("%s=%s\n", name, strempty(t));
527 } else if (strstr(name, "USec")) {
528 char timespan[FORMAT_TIMESPAN_MAX];
530 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
532 printf("%s=%llu\n", name, (unsigned long long) u);
537 case SD_BUS_TYPE_UINT32: {
540 r = sd_bus_message_read_basic(property, type, &u);
544 if (strstr(name, "UMask") || strstr(name, "Mode"))
545 printf("%s=%04o\n", name, u);
547 printf("%s=%u\n", name, (unsigned) u);
552 case SD_BUS_TYPE_INT32: {
555 r = sd_bus_message_read_basic(property, type, &i);
559 printf("%s=%i\n", name, (int) i);
563 case SD_BUS_TYPE_DOUBLE: {
566 r = sd_bus_message_read_basic(property, type, &d);
570 printf("%s=%g\n", name, d);
574 case SD_BUS_TYPE_ARRAY:
575 if (streq(contents, "s")) {
579 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
583 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
587 printf("%s%s", first ? "" : " ", str);
599 r = sd_bus_message_exit_container(property);
605 } else if (streq(contents, "y")) {
609 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
618 for (i = 0; i < n; i++)
619 printf("%02x", u[i]);
626 } else if (streq(contents, "u")) {
630 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
639 for (i = 0; i < n; i++)
640 printf("%08x", u[i]);
654 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
655 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
656 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
662 r = sd_bus_call_method(bus,
665 "org.freedesktop.DBus.Properties",
673 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
677 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
679 const char *contents;
681 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
685 if (!filter || strv_find(filter, name)) {
686 r = sd_bus_message_peek_type(reply, NULL, &contents);
690 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
694 r = bus_print_property(name, reply, all);
699 printf("%s=[unprintable]\n", name);
700 /* skip what we didn't read */
701 r = sd_bus_message_skip(reply, contents);
706 r = sd_bus_message_exit_container(reply);
710 r = sd_bus_message_skip(reply, "v");
715 r = sd_bus_message_exit_container(reply);
722 r = sd_bus_message_exit_container(reply);
729 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
730 sd_id128_t *p = userdata;
735 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
742 memcpy((*p).bytes, v, n);
749 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
753 r = sd_bus_message_peek_type(m, &type, NULL);
758 case SD_BUS_TYPE_STRING: {
763 r = sd_bus_message_read_basic(m, type, &s);
781 case SD_BUS_TYPE_ARRAY: {
782 _cleanup_strv_free_ char **l = NULL;
783 char ***p = userdata;
785 r = bus_message_read_strv_extend(m, &l);
796 case SD_BUS_TYPE_BOOLEAN: {
800 r = sd_bus_message_read_basic(m, type, &b);
809 case SD_BUS_TYPE_UINT32: {
811 uint32_t *p = userdata;
813 r = sd_bus_message_read_basic(m, type, &u);
822 case SD_BUS_TYPE_UINT64: {
824 uint64_t *p = userdata;
826 r = sd_bus_message_read_basic(m, type, &t);
842 int bus_map_all_properties(sd_bus *bus,
843 const char *destination,
845 const struct bus_properties_map *map,
847 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
848 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
856 r = sd_bus_call_method( bus,
859 "org.freedesktop.DBus.Properties",
867 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
871 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
872 const struct bus_properties_map *prop;
874 const char *contents;
878 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
882 for (i = 0, prop = NULL; map[i].member; i++)
883 if (streq(map[i].member, member)) {
889 r = sd_bus_message_peek_type(m, NULL, &contents);
893 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
897 v = (uint8_t *)userdata + prop->offset;
899 r = prop->set(bus, member, m, &error, v);
901 r = map_basic(bus, member, m, &error, v);
903 r = sd_bus_message_exit_container(m);
907 r = sd_bus_message_skip(m, "v");
912 r = sd_bus_message_exit_container(m);
920 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
923 assert(transport >= 0);
924 assert(transport < _BUS_TRANSPORT_MAX);
927 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
928 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
932 case BUS_TRANSPORT_LOCAL:
934 r = sd_bus_default_user(bus);
936 r = sd_bus_default_system(bus);
940 case BUS_TRANSPORT_REMOTE:
941 r = sd_bus_open_system_remote(host, bus);
944 case BUS_TRANSPORT_CONTAINER:
945 r = sd_bus_open_system_container(host, bus);
949 assert_not_reached("Hmm, unknown transport type.");
955 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
958 assert(transport >= 0);
959 assert(transport < _BUS_TRANSPORT_MAX);
962 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
963 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
967 case BUS_TRANSPORT_LOCAL:
969 r = bus_open_user_systemd(bus);
971 r = bus_open_system_systemd(bus);
975 case BUS_TRANSPORT_REMOTE:
976 r = sd_bus_open_system_remote(host, bus);
979 case BUS_TRANSPORT_CONTAINER:
980 r = sd_bus_open_system_container(host, bus);
984 assert_not_reached("Hmm, unknown transport type.");
990 int bus_property_get_tristate(
993 const char *interface,
994 const char *property,
995 sd_bus_message *reply,
997 sd_bus_error *error) {
999 int *tristate = userdata;
1001 return sd_bus_message_append(reply, "b", *tristate > 0);
1004 int bus_property_get_bool(
1007 const char *interface,
1008 const char *property,
1009 sd_bus_message *reply,
1011 sd_bus_error *error) {
1013 int b = *(bool*) userdata;
1015 return sd_bus_message_append_basic(reply, 'b', &b);
1018 #if __SIZEOF_SIZE_T__ != 8
1019 int bus_property_get_size(
1022 const char *interface,
1023 const char *property,
1024 sd_bus_message *reply,
1026 sd_bus_error *error) {
1028 uint64_t sz = *(size_t*) userdata;
1030 return sd_bus_message_append_basic(reply, 't', &sz);
1034 #if __SIZEOF_LONG__ != 8
1035 int bus_property_get_long(
1038 const char *interface,
1039 const char *property,
1040 sd_bus_message *reply,
1042 sd_bus_error *error) {
1044 int64_t l = *(long*) userdata;
1046 return sd_bus_message_append_basic(reply, 'x', &l);
1049 int bus_property_get_ulong(
1052 const char *interface,
1053 const char *property,
1054 sd_bus_message *reply,
1056 sd_bus_error *error) {
1058 uint64_t ul = *(unsigned long*) userdata;
1060 return sd_bus_message_append_basic(reply, 't', &ul);
1064 int bus_log_parse_error(int r) {
1065 log_error("Failed to parse message: %s", strerror(-r));
1069 int bus_log_create_error(int r) {
1070 log_error("Failed to create message: %s", strerror(-r));
1074 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1078 return sd_bus_message_read(
1093 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1097 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1098 sd_bus_reply_method_errno(m, r, error);
1100 } else if (sd_bus_error_is_set(error)) {
1101 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1102 sd_bus_reply_method_error(m, error);
1106 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1107 bus_message_type_to_string(m->header->type),
1110 strna(m->interface),
1112 strna(m->root_container.signature),
1113 bus_error_message(error, r));