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 return sd_bus_open_user(_bus
);
483 if (asprintf(&p
, "unix:path=%s/systemd/private", e
) < 0)
486 r
= sd_bus_new(&bus
);
490 r
= sd_bus_set_address(bus
, p
);
494 r
= sd_bus_start(bus
);
498 r
= bus_check_peercred(bus
);
508 int bus_print_property(const char *name
, sd_bus_message
*property
, bool all
) {
510 const char *contents
;
516 r
= sd_bus_message_peek_type(property
, &type
, &contents
);
522 case SD_BUS_TYPE_STRING
: {
525 r
= sd_bus_message_read_basic(property
, type
, &s
);
529 if (all
|| !isempty(s
))
530 printf("%s=%s\n", name
, s
);
535 case SD_BUS_TYPE_BOOLEAN
: {
538 r
= sd_bus_message_read_basic(property
, type
, &b
);
542 printf("%s=%s\n", name
, yes_no(b
));
547 case SD_BUS_TYPE_UINT64
: {
550 r
= sd_bus_message_read_basic(property
, type
, &u
);
554 /* Yes, heuristics! But we can change this check
555 * should it turn out to not be sufficient */
557 if (endswith(name
, "Timestamp")) {
558 char timestamp
[FORMAT_TIMESTAMP_MAX
], *t
;
560 t
= format_timestamp(timestamp
, sizeof(timestamp
), u
);
562 printf("%s=%s\n", name
, strempty(t
));
564 } else if (strstr(name
, "USec")) {
565 char timespan
[FORMAT_TIMESPAN_MAX
];
567 printf("%s=%s\n", name
, format_timespan(timespan
, sizeof(timespan
), u
, 0));
569 printf("%s=%llu\n", name
, (unsigned long long) u
);
574 case SD_BUS_TYPE_UINT32
: {
577 r
= sd_bus_message_read_basic(property
, type
, &u
);
581 if (strstr(name
, "UMask") || strstr(name
, "Mode"))
582 printf("%s=%04o\n", name
, u
);
584 printf("%s=%u\n", name
, (unsigned) u
);
589 case SD_BUS_TYPE_INT32
: {
592 r
= sd_bus_message_read_basic(property
, type
, &i
);
596 printf("%s=%i\n", name
, (int) i
);
600 case SD_BUS_TYPE_DOUBLE
: {
603 r
= sd_bus_message_read_basic(property
, type
, &d
);
607 printf("%s=%g\n", name
, d
);
611 case SD_BUS_TYPE_ARRAY
:
612 if (streq(contents
, "s")) {
616 r
= sd_bus_message_enter_container(property
, SD_BUS_TYPE_ARRAY
, contents
);
620 while((r
= sd_bus_message_read_basic(property
, SD_BUS_TYPE_STRING
, &str
)) > 0) {
624 printf("%s%s", first
? "" : " ", str
);
636 r
= sd_bus_message_exit_container(property
);
642 } else if (streq(contents
, "y")) {
646 r
= sd_bus_message_read_array(property
, SD_BUS_TYPE_BYTE
, (const void**) &u
, &n
);
655 for (i
= 0; i
< n
; i
++)
656 printf("%02x", u
[i
]);
663 } else if (streq(contents
, "u")) {
667 r
= sd_bus_message_read_array(property
, SD_BUS_TYPE_UINT32
, (const void**) &u
, &n
);
676 for (i
= 0; i
< n
; i
++)
677 printf("%08x", u
[i
]);
691 int bus_print_all_properties(sd_bus
*bus
, const char *dest
, const char *path
, char **filter
, bool all
) {
692 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
693 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
699 r
= sd_bus_call_method(bus
,
702 "org.freedesktop.DBus.Properties",
710 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
714 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
716 const char *contents
;
718 r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &name
);
722 if (!filter
|| strv_find(filter
, name
)) {
723 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
727 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
731 r
= bus_print_property(name
, reply
, all
);
736 printf("%s=[unprintable]\n", name
);
737 /* skip what we didn't read */
738 r
= sd_bus_message_skip(reply
, contents
);
743 r
= sd_bus_message_exit_container(reply
);
747 r
= sd_bus_message_skip(reply
, "v");
752 r
= sd_bus_message_exit_container(reply
);
759 r
= sd_bus_message_exit_container(reply
);
766 int bus_map_id128(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
767 sd_id128_t
*p
= userdata
;
772 r
= sd_bus_message_read_array(m
, SD_BUS_TYPE_BYTE
, &v
, &n
);
779 memcpy((*p
).bytes
, v
, n
);
786 static int map_basic(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
790 r
= sd_bus_message_peek_type(m
, &type
, NULL
);
795 case SD_BUS_TYPE_STRING
: {
800 r
= sd_bus_message_read_basic(m
, type
, &s
);
818 case SD_BUS_TYPE_ARRAY
: {
819 _cleanup_strv_free_
char **l
= NULL
;
820 char ***p
= userdata
;
822 r
= bus_message_read_strv_extend(m
, &l
);
833 case SD_BUS_TYPE_BOOLEAN
: {
837 r
= sd_bus_message_read_basic(m
, type
, &b
);
846 case SD_BUS_TYPE_UINT32
: {
848 uint32_t *p
= userdata
;
850 r
= sd_bus_message_read_basic(m
, type
, &u
);
859 case SD_BUS_TYPE_UINT64
: {
861 uint64_t *p
= userdata
;
863 r
= sd_bus_message_read_basic(m
, type
, &t
);
879 int bus_map_all_properties(sd_bus
*bus
,
880 const char *destination
,
882 const struct bus_properties_map
*map
,
884 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
;
885 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
893 r
= sd_bus_call_method( bus
,
896 "org.freedesktop.DBus.Properties",
904 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
908 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
909 const struct bus_properties_map
*prop
;
911 const char *contents
;
915 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &member
);
919 for (i
= 0, prop
= NULL
; map
[i
].member
; i
++)
920 if (streq(map
[i
].member
, member
)) {
926 r
= sd_bus_message_peek_type(m
, NULL
, &contents
);
930 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, contents
);
934 v
= (uint8_t *)userdata
+ prop
->offset
;
936 r
= prop
->set(bus
, member
, m
, &error
, v
);
938 r
= map_basic(bus
, member
, m
, &error
, v
);
940 r
= sd_bus_message_exit_container(m
);
944 r
= sd_bus_message_skip(m
, "v");
949 r
= sd_bus_message_exit_container(m
);
957 int bus_open_transport(BusTransport transport
, const char *host
, bool user
, sd_bus
**bus
) {
960 assert(transport
>= 0);
961 assert(transport
< _BUS_TRANSPORT_MAX
);
964 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
965 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -ENOTSUP
);
969 case BUS_TRANSPORT_LOCAL
:
971 r
= sd_bus_default_user(bus
);
973 r
= sd_bus_default_system(bus
);
977 case BUS_TRANSPORT_REMOTE
:
978 r
= sd_bus_open_system_remote(host
, bus
);
981 case BUS_TRANSPORT_CONTAINER
:
982 r
= sd_bus_open_system_container(host
, bus
);
986 assert_not_reached("Hmm, unknown transport type.");
992 int bus_open_transport_systemd(BusTransport transport
, const char *host
, bool user
, sd_bus
**bus
) {
995 assert(transport
>= 0);
996 assert(transport
< _BUS_TRANSPORT_MAX
);
999 assert_return((transport
== BUS_TRANSPORT_LOCAL
) == !host
, -EINVAL
);
1000 assert_return(transport
== BUS_TRANSPORT_LOCAL
|| !user
, -ENOTSUP
);
1002 switch (transport
) {
1004 case BUS_TRANSPORT_LOCAL
:
1006 r
= bus_open_user_systemd(bus
);
1008 r
= bus_open_system_systemd(bus
);
1012 case BUS_TRANSPORT_REMOTE
:
1013 r
= sd_bus_open_system_remote(host
, bus
);
1016 case BUS_TRANSPORT_CONTAINER
:
1017 r
= sd_bus_open_system_container(host
, bus
);
1021 assert_not_reached("Hmm, unknown transport type.");
1027 int bus_property_get_tristate(
1030 const char *interface
,
1031 const char *property
,
1032 sd_bus_message
*reply
,
1034 sd_bus_error
*error
) {
1036 int *tristate
= userdata
;
1038 return sd_bus_message_append(reply
, "b", *tristate
> 0);
1041 int bus_property_get_bool(
1044 const char *interface
,
1045 const char *property
,
1046 sd_bus_message
*reply
,
1048 sd_bus_error
*error
) {
1050 int b
= *(bool*) userdata
;
1052 return sd_bus_message_append_basic(reply
, 'b', &b
);
1055 #if __SIZEOF_SIZE_T__ != 8
1056 int bus_property_get_size(
1059 const char *interface
,
1060 const char *property
,
1061 sd_bus_message
*reply
,
1063 sd_bus_error
*error
) {
1065 uint64_t sz
= *(size_t*) userdata
;
1067 return sd_bus_message_append_basic(reply
, 't', &sz
);
1071 #if __SIZEOF_LONG__ != 8
1072 int bus_property_get_long(
1075 const char *interface
,
1076 const char *property
,
1077 sd_bus_message
*reply
,
1079 sd_bus_error
*error
) {
1081 int64_t l
= *(long*) userdata
;
1083 return sd_bus_message_append_basic(reply
, 'x', &l
);
1086 int bus_property_get_ulong(
1089 const char *interface
,
1090 const char *property
,
1091 sd_bus_message
*reply
,
1093 sd_bus_error
*error
) {
1095 uint64_t ul
= *(unsigned long*) userdata
;
1097 return sd_bus_message_append_basic(reply
, 't', &ul
);
1101 int bus_log_parse_error(int r
) {
1102 log_error("Failed to parse message: %s", strerror(-r
));
1106 int bus_log_create_error(int r
) {
1107 log_error("Failed to create message: %s", strerror(-r
));
1111 int bus_parse_unit_info(sd_bus_message
*message
, UnitInfo
*u
) {
1115 return sd_bus_message_read(
1130 int bus_maybe_reply_error(sd_bus_message
*m
, int r
, sd_bus_error
*error
) {
1134 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
1135 sd_bus_reply_method_errno(m
, r
, error
);
1137 } else if (sd_bus_error_is_set(error
)) {
1138 if (m
->header
->type
== SD_BUS_MESSAGE_METHOD_CALL
)
1139 sd_bus_reply_method_error(m
, error
);
1143 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1144 bus_message_type_to_string(m
->header
->type
),
1147 strna(m
->interface
),
1149 strna(m
->root_container
.signature
),
1150 bus_error_message(error
, r
));