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
;
57 r
= asprintf(&match
, "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameLost',arg0='%s'", name
);
61 r
= sd_bus_add_match(bus
, match
, quit_callback
, e
);
65 r
= sd_bus_release_name(bus
, name
);
69 if (r
!= SD_BUS_NAME_RELEASED
)
75 int bus_event_loop_with_idle(sd_event
*e
, sd_bus
*bus
, const char *name
, usec_t timeout
) {
84 r
= sd_event_get_state(e
);
88 if (r
== SD_EVENT_FINISHED
)
91 r
= sd_event_run(e
, exiting
? (uint64_t) -1 : timeout
);
95 if (r
== 0 && !exiting
) {
96 r
= bus_async_unregister_and_quit(e
, bus
, name
);
107 int bus_name_has_owner(sd_bus
*c
, const char *name
, sd_bus_error
*error
) {
108 _cleanup_bus_message_unref_ sd_bus_message
*rep
= NULL
;
109 int r
, has_owner
= 0;
114 r
= sd_bus_call_method(c
,
115 "org.freedesktop.DBus",
116 "/org/freedesktop/dbus",
117 "org.freedesktop.DBus",
126 r
= sd_bus_message_read_basic(rep
, 'b', &has_owner
);
128 return sd_bus_error_set_errno(error
, r
);
133 int bus_verify_polkit(
141 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
149 r
= sd_bus_query_sender_creds(m
, SD_BUS_CREDS_UID
, &creds
);
153 r
= sd_bus_creds_get_uid(creds
, &uid
);
162 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
163 int authorized
= false, challenge
= false;
166 sender
= sd_bus_message_get_sender(m
);
170 r
= sd_bus_call_method(
172 "org.freedesktop.PolicyKit1",
173 "/org/freedesktop/PolicyKit1/Authority",
174 "org.freedesktop.PolicyKit1.Authority",
175 "CheckAuthorization",
179 "system-bus-name", 1, "name", "s", sender
,
186 /* Treat no PK available as access denied */
187 if (sd_bus_error_has_name(e
, SD_BUS_ERROR_SERVICE_UNKNOWN
)) {
188 sd_bus_error_free(e
);
195 r
= sd_bus_message_enter_container(reply
, 'r', "bba{ss}");
197 r
= sd_bus_message_read(reply
, "bb", &authorized
, &challenge
);
203 *_challenge
= challenge
;
214 typedef struct AsyncPolkitQuery
{
215 sd_bus_message
*request
, *reply
;
216 sd_bus_message_handler_t callback
;
222 static void async_polkit_query_free(sd_bus
*b
, AsyncPolkitQuery
*q
) {
227 if (q
->serial
> 0 && b
)
228 sd_bus_call_async_cancel(b
, q
->serial
);
230 if (q
->registry
&& q
->request
)
231 hashmap_remove(q
->registry
, q
->request
);
233 sd_bus_message_unref(q
->request
);
234 sd_bus_message_unref(q
->reply
);
239 static int async_polkit_callback(sd_bus
*bus
, sd_bus_message
*reply
, void *userdata
, sd_bus_error
*error
) {
240 _cleanup_bus_error_free_ sd_bus_error error_buffer
= SD_BUS_ERROR_NULL
;
241 AsyncPolkitQuery
*q
= userdata
;
248 q
->reply
= sd_bus_message_ref(reply
);
251 r
= sd_bus_message_rewind(q
->request
, true);
253 r
= sd_bus_reply_method_errno(q
->request
, r
, NULL
);
257 r
= q
->callback(bus
, q
->request
, q
->userdata
, &error_buffer
);
258 r
= bus_maybe_reply_error(q
->request
, r
, &error_buffer
);
261 async_polkit_query_free(bus
, q
);
267 int bus_verify_polkit_async(
274 sd_bus_message_handler_t callback
,
278 _cleanup_bus_message_unref_ sd_bus_message
*pk
= NULL
;
282 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
292 q
= hashmap_get(*registry
, m
);
294 int authorized
, challenge
;
296 /* This is the second invocation of this function, and
297 * there's already a response from polkit, let's
301 if (sd_bus_message_is_method_error(q
->reply
, NULL
)) {
302 const sd_bus_error
*e
;
304 /* Copy error from polkit reply */
305 e
= sd_bus_message_get_error(q
->reply
);
306 sd_bus_error_copy(error
, e
);
308 /* Treat no PK available as access denied */
309 if (sd_bus_error_has_name(e
, SD_BUS_ERROR_SERVICE_UNKNOWN
))
312 return sd_bus_error_get_errno(e
);
315 r
= sd_bus_message_enter_container(q
->reply
, 'r', "bba{ss}");
317 r
= sd_bus_message_read(q
->reply
, "bb", &authorized
, &challenge
);
329 r
= sd_bus_query_sender_creds(m
, SD_BUS_CREDS_UID
, &creds
);
333 r
= sd_bus_creds_get_uid(creds
, &uid
);
341 sender
= sd_bus_message_get_sender(m
);
345 r
= hashmap_ensure_allocated(registry
, trivial_hash_func
, trivial_compare_func
);
349 r
= sd_bus_message_new_method_call(
351 "org.freedesktop.PolicyKit1",
352 "/org/freedesktop/PolicyKit1/Authority",
353 "org.freedesktop.PolicyKit1.Authority",
354 "CheckAuthorization",
359 r
= sd_bus_message_append(
362 "system-bus-name", 1, "name", "s", sender
,
370 q
= new0(AsyncPolkitQuery
, 1);
374 q
->request
= sd_bus_message_ref(m
);
375 q
->callback
= callback
;
376 q
->userdata
= userdata
;
378 r
= hashmap_put(*registry
, m
, q
);
380 async_polkit_query_free(bus
, q
);
384 q
->registry
= *registry
;
386 r
= sd_bus_call_async(bus
, pk
, async_polkit_callback
, q
, 0, &q
->serial
);
388 async_polkit_query_free(bus
, q
);
398 void bus_verify_polkit_async_registry_free(sd_bus
*bus
, Hashmap
*registry
) {
402 while ((q
= hashmap_steal_first(registry
)))
403 async_polkit_query_free(bus
, q
);
405 hashmap_free(registry
);
409 int bus_check_peercred(sd_bus
*c
) {
416 fd
= sd_bus_get_fd(c
);
420 l
= sizeof(struct ucred
);
421 if (getsockopt(fd
, SOL_SOCKET
, SO_PEERCRED
, &ucred
, &l
) < 0)
424 if (l
!= sizeof(struct ucred
))
427 if (ucred
.uid
!= 0 && ucred
.uid
!= geteuid())
433 int bus_open_system_systemd(sd_bus
**_bus
) {
434 _cleanup_bus_unref_ sd_bus
*bus
= NULL
;
440 return sd_bus_open_system(_bus
);
442 /* If we are root, then let's talk directly to the system
443 * instance, instead of going via the bus */
445 r
= sd_bus_new(&bus
);
449 r
= sd_bus_set_address(bus
, "unix:path=/run/systemd/private");
453 r
= sd_bus_start(bus
);
457 r
= bus_check_peercred(bus
);
467 int bus_open_user_systemd(sd_bus
**_bus
) {
468 _cleanup_bus_unref_ sd_bus
*bus
= NULL
;
469 _cleanup_free_
char *p
= NULL
;
473 /* If we are supposed to talk to the instance, try via
474 * XDG_RUNTIME_DIR first, then fallback to normal bus
479 e
= secure_getenv("XDG_RUNTIME_DIR");
481 if (asprintf(&p
, "unix:path=%s/systemd/private", e
) < 0)
485 r
= sd_bus_new(&bus
);
489 r
= sd_bus_set_address(bus
, p
);
493 r
= sd_bus_start(bus
);
497 r
= bus_check_peercred(bus
);
507 int bus_print_property(const char *name
, sd_bus_message
*property
, bool all
) {
509 const char *contents
;
515 r
= sd_bus_message_peek_type(property
, &type
, &contents
);
521 case SD_BUS_TYPE_STRING
: {
524 r
= sd_bus_message_read_basic(property
, type
, &s
);
528 if (all
|| !isempty(s
))
529 printf("%s=%s\n", name
, s
);
534 case SD_BUS_TYPE_BOOLEAN
: {
537 r
= sd_bus_message_read_basic(property
, type
, &b
);
541 printf("%s=%s\n", name
, yes_no(b
));
546 case SD_BUS_TYPE_UINT64
: {
549 r
= sd_bus_message_read_basic(property
, type
, &u
);
553 /* Yes, heuristics! But we can change this check
554 * should it turn out to not be sufficient */
556 if (endswith(name
, "Timestamp")) {
557 char timestamp
[FORMAT_TIMESTAMP_MAX
], *t
;
559 t
= format_timestamp(timestamp
, sizeof(timestamp
), u
);
561 printf("%s=%s\n", name
, strempty(t
));
563 } else if (strstr(name
, "USec")) {
564 char timespan
[FORMAT_TIMESPAN_MAX
];
566 printf("%s=%s\n", name
, format_timespan(timespan
, sizeof(timespan
), u
, 0));
568 printf("%s=%llu\n", name
, (unsigned long long) u
);
573 case SD_BUS_TYPE_UINT32
: {
576 r
= sd_bus_message_read_basic(property
, type
, &u
);
580 if (strstr(name
, "UMask") || strstr(name
, "Mode"))
581 printf("%s=%04o\n", name
, u
);
583 printf("%s=%u\n", name
, (unsigned) u
);
588 case SD_BUS_TYPE_INT32
: {
591 r
= sd_bus_message_read_basic(property
, type
, &i
);
595 printf("%s=%i\n", name
, (int) i
);
599 case SD_BUS_TYPE_DOUBLE
: {
602 r
= sd_bus_message_read_basic(property
, type
, &d
);
606 printf("%s=%g\n", name
, d
);
610 case SD_BUS_TYPE_ARRAY
:
611 if (streq(contents
, "s")) {
615 r
= sd_bus_message_enter_container(property
, SD_BUS_TYPE_ARRAY
, contents
);
619 while((r
= sd_bus_message_read_basic(property
, SD_BUS_TYPE_STRING
, &str
)) > 0) {
623 printf("%s%s", first
? "" : " ", str
);
635 r
= sd_bus_message_exit_container(property
);
641 } else if (streq(contents
, "y")) {
645 r
= sd_bus_message_read_array(property
, SD_BUS_TYPE_BYTE
, (const void**) &u
, &n
);
654 for (i
= 0; i
< n
; i
++)
655 printf("%02x", u
[i
]);
662 } else if (streq(contents
, "u")) {
666 r
= sd_bus_message_read_array(property
, SD_BUS_TYPE_UINT32
, (const void**) &u
, &n
);
675 for (i
= 0; i
< n
; i
++)
676 printf("%08x", u
[i
]);
690 int bus_print_all_properties(sd_bus
*bus
, const char *dest
, const char *path
, char **filter
, bool all
) {
691 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
692 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
698 r
= sd_bus_call_method(bus
,
701 "org.freedesktop.DBus.Properties",
709 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
713 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
715 const char *contents
;
717 r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &name
);
721 if (!filter
|| strv_find(filter
, name
)) {
722 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
726 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
730 r
= bus_print_property(name
, reply
, all
);
735 printf("%s=[unprintable]\n", name
);
736 /* skip what we didn't read */
737 r
= sd_bus_message_skip(reply
, contents
);
742 r
= sd_bus_message_exit_container(reply
);
746 r
= sd_bus_message_skip(reply
, "v");
751 r
= sd_bus_message_exit_container(reply
);
758 r
= sd_bus_message_exit_container(reply
);
765 int bus_map_id128(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
766 sd_id128_t
*p
= userdata
;
771 r
= sd_bus_message_read_array(m
, SD_BUS_TYPE_BYTE
, &v
, &n
);
778 memcpy((*p
).bytes
, v
, n
);
785 static int map_basic(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
789 r
= sd_bus_message_peek_type(m
, &type
, NULL
);
794 case SD_BUS_TYPE_STRING
: {
799 r
= sd_bus_message_read_basic(m
, type
, &s
);
817 case SD_BUS_TYPE_ARRAY
: {
818 _cleanup_strv_free_
char **l
= NULL
;
819 char ***p
= userdata
;
821 r
= bus_message_read_strv_extend(m
, &l
);
832 case SD_BUS_TYPE_BOOLEAN
: {
836 r
= sd_bus_message_read_basic(m
, type
, &b
);
845 case SD_BUS_TYPE_UINT32
: {
847 uint32_t *p
= userdata
;
849 r
= sd_bus_message_read_basic(m
, type
, &u
);
858 case SD_BUS_TYPE_UINT64
: {
860 uint64_t *p
= userdata
;
862 r
= sd_bus_message_read_basic(m
, type
, &t
);
878 int bus_map_all_properties(sd_bus
*bus
,
879 const char *destination
,
881 const struct bus_properties_map
*map
,
883 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
884 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
892 r
= sd_bus_call_method( bus
,
895 "org.freedesktop.DBus.Properties",
903 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
907 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
908 const struct bus_properties_map
*prop
;
910 const char *contents
;
914 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &member
);
918 for (i
= 0, prop
= NULL
; map
[i
].member
; i
++)
919 if (streq(map
[i
].member
, member
)) {
925 r
= sd_bus_message_peek_type(m
, NULL
, &contents
);
929 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
933 v
= (uint8_t *)userdata
+ prop
->offset
;
935 r
= prop
->set(bus
, member
, m
, &error
, v
);
937 r
= map_basic(bus
, member
, m
, &error
, v
);
939 r
= sd_bus_message_exit_container(m
);
943 r
= sd_bus_message_skip(m
, "v");
948 r
= sd_bus_message_exit_container(m
);
956 int bus_open_transport(BusTransport transport
, const char *host
, bool user
, sd_bus
**bus
) {
959 assert(transport
>= 0);
960 assert(transport
< _BUS_TRANSPORT_MAX
);
963 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
964 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -ENOTSUP
);
968 case BUS_TRANSPORT_LOCAL
:
970 r
= sd_bus_default_user(bus
);
972 r
= sd_bus_default_system(bus
);
976 case BUS_TRANSPORT_REMOTE
:
977 r
= sd_bus_open_system_remote(host
, bus
);
980 case BUS_TRANSPORT_CONTAINER
:
981 r
= sd_bus_open_system_container(host
, bus
);
985 assert_not_reached("Hmm, unknown transport type.");
991 int bus_open_transport_systemd(BusTransport transport
, const char *host
, bool user
, sd_bus
**bus
) {
994 assert(transport
>= 0);
995 assert(transport
< _BUS_TRANSPORT_MAX
);
998 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
999 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -ENOTSUP
);
1001 switch (transport
) {
1003 case BUS_TRANSPORT_LOCAL
:
1005 r
= bus_open_user_systemd(bus
);
1007 r
= bus_open_system_systemd(bus
);
1011 case BUS_TRANSPORT_REMOTE
:
1012 r
= sd_bus_open_system_remote(host
, bus
);
1015 case BUS_TRANSPORT_CONTAINER
:
1016 r
= sd_bus_open_system_container(host
, bus
);
1020 assert_not_reached("Hmm, unknown transport type.");
1026 int bus_property_get_tristate(
1029 const char *interface
,
1030 const char *property
,
1031 sd_bus_message
*reply
,
1033 sd_bus_error
*error
) {
1035 int *tristate
= userdata
;
1037 return sd_bus_message_append(reply
, "b", *tristate
> 0);
1040 int bus_property_get_bool(
1043 const char *interface
,
1044 const char *property
,
1045 sd_bus_message
*reply
,
1047 sd_bus_error
*error
) {
1049 int b
= *(bool*) userdata
;
1051 return sd_bus_message_append_basic(reply
, 'b', &b
);
1054 #if __SIZEOF_SIZE_T__ != 8
1055 int bus_property_get_size(
1058 const char *interface
,
1059 const char *property
,
1060 sd_bus_message
*reply
,
1062 sd_bus_error
*error
) {
1064 uint64_t sz
= *(size_t*) userdata
;
1066 return sd_bus_message_append_basic(reply
, 't', &sz
);
1070 #if __SIZEOF_LONG__ != 8
1071 int bus_property_get_long(
1074 const char *interface
,
1075 const char *property
,
1076 sd_bus_message
*reply
,
1078 sd_bus_error
*error
) {
1080 int64_t l
= *(long*) userdata
;
1082 return sd_bus_message_append_basic(reply
, 'x', &l
);
1085 int bus_property_get_ulong(
1088 const char *interface
,
1089 const char *property
,
1090 sd_bus_message
*reply
,
1092 sd_bus_error
*error
) {
1094 uint64_t ul
= *(unsigned long*) userdata
;
1096 return sd_bus_message_append_basic(reply
, 't', &ul
);
1100 int bus_log_parse_error(int r
) {
1101 log_error("Failed to parse message: %s", strerror(-r
));
1105 int bus_log_create_error(int r
) {
1106 log_error("Failed to create message: %s", strerror(-r
));
1110 int bus_parse_unit_info(sd_bus_message
*message
, UnitInfo
*u
) {
1114 return sd_bus_message_read(
1129 int bus_maybe_reply_error(sd_bus_message
*m
, int r
, sd_bus_error
*error
) {
1133 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
1134 sd_bus_reply_method_errno(m
, r
, error
);
1136 } else if (sd_bus_error_is_set(error
)) {
1137 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
1138 sd_bus_reply_method_error(m
, error
);
1142 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1143 bus_message_type_to_string(m
->header
->type
),
1146 strna(m
->interface
),
1148 strna(m
->root_container
.signature
),
1149 bus_error_message(error
, r
));