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 AsyncPolkitQuery *q = userdata;
216 q->reply = sd_bus_message_ref(reply);
219 r = sd_bus_message_rewind(q->request, true);
221 r = sd_bus_reply_method_errno(q->request, r, NULL);
225 r = q->callback(bus, q->request, q->userdata, &error_buffer);
226 r = bus_maybe_reply_error(q->request, r, &error_buffer);
229 async_polkit_query_free(bus, q);
235 int bus_verify_polkit_async(
242 sd_bus_message_handler_t callback,
246 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
259 q = hashmap_get(*registry, m);
261 int authorized, challenge;
263 /* This is the second invocation of this function, and
264 * there's already a response from polkit, let's
268 if (sd_bus_message_is_method_error(q->reply, NULL)) {
269 const sd_bus_error *e;
271 /* Copy error from polkit reply */
272 e = sd_bus_message_get_error(q->reply);
273 sd_bus_error_copy(error, e);
275 /* Treat no PK available as access denied */
276 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
279 return sd_bus_error_get_errno(e);
282 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
284 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
296 sender = sd_bus_message_get_sender(m);
300 r = sd_bus_get_owner_uid(bus, sender, &uid);
308 r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
312 r = sd_bus_message_new_method_call(
314 "org.freedesktop.PolicyKit1",
315 "/org/freedesktop/PolicyKit1/Authority",
316 "org.freedesktop.PolicyKit1.Authority",
317 "CheckAuthorization",
322 r = sd_bus_message_append(
325 "system-bus-name", 1, "name", "s", sender,
333 q = new0(AsyncPolkitQuery, 1);
337 q->request = sd_bus_message_ref(m);
338 q->callback = callback;
339 q->userdata = userdata;
341 r = hashmap_put(*registry, m, q);
343 async_polkit_query_free(bus, q);
347 q->registry = *registry;
349 r = sd_bus_call_async(bus, pk, async_polkit_callback, q, 0, &q->serial);
351 async_polkit_query_free(bus, q);
361 void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
365 while ((q = hashmap_steal_first(registry)))
366 async_polkit_query_free(bus, q);
368 hashmap_free(registry);
372 int bus_check_peercred(sd_bus *c) {
379 fd = sd_bus_get_fd(c);
383 l = sizeof(struct ucred);
384 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
387 if (l != sizeof(struct ucred))
390 if (ucred.uid != 0 && ucred.uid != geteuid())
396 int bus_open_system_systemd(sd_bus **_bus) {
397 _cleanup_bus_unref_ sd_bus *bus = NULL;
403 return sd_bus_open_system(_bus);
405 /* If we are root, then let's talk directly to the system
406 * instance, instead of going via the bus */
408 r = sd_bus_new(&bus);
412 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
416 r = sd_bus_start(bus);
420 r = bus_check_peercred(bus);
430 int bus_open_user_systemd(sd_bus **_bus) {
431 _cleanup_bus_unref_ sd_bus *bus = NULL;
432 _cleanup_free_ char *p = NULL;
436 /* If we are supposed to talk to the instance, try via
437 * XDG_RUNTIME_DIR first, then fallback to normal bus
442 e = secure_getenv("XDG_RUNTIME_DIR");
444 if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0)
448 r = sd_bus_new(&bus);
452 r = sd_bus_set_address(bus, p);
456 r = sd_bus_start(bus);
460 r = bus_check_peercred(bus);
470 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
472 const char *contents;
478 r = sd_bus_message_peek_type(property, &type, &contents);
484 case SD_BUS_TYPE_STRING: {
487 r = sd_bus_message_read_basic(property, type, &s);
491 if (all || !isempty(s))
492 printf("%s=%s\n", name, s);
497 case SD_BUS_TYPE_BOOLEAN: {
500 r = sd_bus_message_read_basic(property, type, &b);
504 printf("%s=%s\n", name, yes_no(b));
509 case SD_BUS_TYPE_UINT64: {
512 r = sd_bus_message_read_basic(property, type, &u);
516 /* Yes, heuristics! But we can change this check
517 * should it turn out to not be sufficient */
519 if (endswith(name, "Timestamp")) {
520 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
522 t = format_timestamp(timestamp, sizeof(timestamp), u);
524 printf("%s=%s\n", name, strempty(t));
526 } else if (strstr(name, "USec")) {
527 char timespan[FORMAT_TIMESPAN_MAX];
529 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
531 printf("%s=%llu\n", name, (unsigned long long) u);
536 case SD_BUS_TYPE_UINT32: {
539 r = sd_bus_message_read_basic(property, type, &u);
543 if (strstr(name, "UMask") || strstr(name, "Mode"))
544 printf("%s=%04o\n", name, u);
546 printf("%s=%u\n", name, (unsigned) u);
551 case SD_BUS_TYPE_INT32: {
554 r = sd_bus_message_read_basic(property, type, &i);
558 printf("%s=%i\n", name, (int) i);
562 case SD_BUS_TYPE_DOUBLE: {
565 r = sd_bus_message_read_basic(property, type, &d);
569 printf("%s=%g\n", name, d);
573 case SD_BUS_TYPE_ARRAY:
574 if (streq(contents, "s")) {
578 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
582 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
586 printf("%s%s", first ? "" : " ", str);
598 r = sd_bus_message_exit_container(property);
604 } else if (streq(contents, "y")) {
608 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
617 for (i = 0; i < n; i++)
618 printf("%02x", u[i]);
625 } else if (streq(contents, "u")) {
629 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
638 for (i = 0; i < n; i++)
639 printf("%08x", u[i]);
653 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
654 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
655 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
661 r = sd_bus_call_method(bus,
664 "org.freedesktop.DBus.Properties",
672 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
676 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
678 const char *contents;
680 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
684 if (!filter || strv_find(filter, name)) {
685 r = sd_bus_message_peek_type(reply, NULL, &contents);
689 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
693 r = bus_print_property(name, reply, all);
698 printf("%s=[unprintable]\n", name);
699 /* skip what we didn't read */
700 r = sd_bus_message_skip(reply, contents);
705 r = sd_bus_message_exit_container(reply);
709 r = sd_bus_message_skip(reply, "v");
714 r = sd_bus_message_exit_container(reply);
721 r = sd_bus_message_exit_container(reply);
728 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
729 sd_id128_t *p = userdata;
734 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
741 memcpy((*p).bytes, v, n);
748 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
752 r = sd_bus_message_peek_type(m, &type, NULL);
757 case SD_BUS_TYPE_STRING: {
762 r = sd_bus_message_read_basic(m, type, &s);
780 case SD_BUS_TYPE_ARRAY: {
781 _cleanup_strv_free_ char **l = NULL;
782 char ***p = userdata;
784 r = bus_message_read_strv_extend(m, &l);
795 case SD_BUS_TYPE_BOOLEAN: {
799 r = sd_bus_message_read_basic(m, type, &b);
808 case SD_BUS_TYPE_UINT32: {
810 uint32_t *p = userdata;
812 r = sd_bus_message_read_basic(m, type, &u);
821 case SD_BUS_TYPE_UINT64: {
823 uint64_t *p = userdata;
825 r = sd_bus_message_read_basic(m, type, &t);
841 int bus_map_all_properties(sd_bus *bus,
842 const char *destination,
844 const struct bus_properties_map *map,
846 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
847 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
855 r = sd_bus_call_method( bus,
858 "org.freedesktop.DBus.Properties",
866 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
870 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
871 const struct bus_properties_map *prop;
873 const char *contents;
877 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
881 for (i = 0, prop = NULL; map[i].member; i++)
882 if (streq(map[i].member, member)) {
888 r = sd_bus_message_peek_type(m, NULL, &contents);
892 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
896 v = (uint8_t *)userdata + prop->offset;
898 r = prop->set(bus, member, m, &error, v);
900 r = map_basic(bus, member, m, &error, v);
902 r = sd_bus_message_exit_container(m);
906 r = sd_bus_message_skip(m, "v");
911 r = sd_bus_message_exit_container(m);
919 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
922 assert(transport >= 0);
923 assert(transport < _BUS_TRANSPORT_MAX);
926 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
927 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
931 case BUS_TRANSPORT_LOCAL:
933 r = sd_bus_default_user(bus);
935 r = sd_bus_default_system(bus);
939 case BUS_TRANSPORT_REMOTE:
940 r = sd_bus_open_system_remote(host, bus);
943 case BUS_TRANSPORT_CONTAINER:
944 r = sd_bus_open_system_container(host, bus);
948 assert_not_reached("Hmm, unknown transport type.");
954 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
957 assert(transport >= 0);
958 assert(transport < _BUS_TRANSPORT_MAX);
961 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
962 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
966 case BUS_TRANSPORT_LOCAL:
968 r = bus_open_user_systemd(bus);
970 r = bus_open_system_systemd(bus);
974 case BUS_TRANSPORT_REMOTE:
975 r = sd_bus_open_system_remote(host, bus);
978 case BUS_TRANSPORT_CONTAINER:
979 r = sd_bus_open_system_container(host, bus);
983 assert_not_reached("Hmm, unknown transport type.");
989 int bus_property_get_tristate(
992 const char *interface,
993 const char *property,
994 sd_bus_message *reply,
996 sd_bus_error *error) {
998 int *tristate = userdata;
1000 return sd_bus_message_append(reply, "b", *tristate > 0);
1003 int bus_property_get_bool(
1006 const char *interface,
1007 const char *property,
1008 sd_bus_message *reply,
1010 sd_bus_error *error) {
1012 int b = *(bool*) userdata;
1014 return sd_bus_message_append_basic(reply, 'b', &b);
1017 #if __SIZEOF_SIZE_T__ != 8
1018 int bus_property_get_size(
1021 const char *interface,
1022 const char *property,
1023 sd_bus_message *reply,
1025 sd_bus_error *error) {
1027 uint64_t sz = *(size_t*) userdata;
1029 return sd_bus_message_append_basic(reply, 't', &sz);
1033 #if __SIZEOF_LONG__ != 8
1034 int bus_property_get_long(
1037 const char *interface,
1038 const char *property,
1039 sd_bus_message *reply,
1041 sd_bus_error *error) {
1043 int64_t l = *(long*) userdata;
1045 return sd_bus_message_append_basic(reply, 'x', &l);
1048 int bus_property_get_ulong(
1051 const char *interface,
1052 const char *property,
1053 sd_bus_message *reply,
1055 sd_bus_error *error) {
1057 uint64_t ul = *(unsigned long*) userdata;
1059 return sd_bus_message_append_basic(reply, 't', &ul);
1063 int bus_log_parse_error(int r) {
1064 log_error("Failed to parse message: %s", strerror(-r));
1068 int bus_log_create_error(int r) {
1069 log_error("Failed to create message: %s", strerror(-r));
1073 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1077 return sd_bus_message_read(
1092 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1096 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1097 sd_bus_reply_method_errno(m, r, error);
1099 } else if (sd_bus_error_is_set(error)) {
1100 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1101 sd_bus_reply_method_error(m, error);
1105 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1106 bus_message_type_to_string(m->header->type),
1109 strna(m->interface),
1111 strna(m->root_container.signature),
1112 bus_error_message(error, r));