2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include "bus-internal.h"
21 #include "bus-message.h"
22 #include "bus-signature.h"
25 #include "string-util.h"
27 _public_ int sd_bus_emit_signal(
30 const char *interface,
32 const char *types, ...) {
34 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
37 assert_return(bus, -EINVAL);
38 assert_return(!bus_pid_changed(bus), -ECHILD);
40 if (!BUS_IS_OPEN(bus->state))
43 r = sd_bus_message_new_signal(bus, &m, path, interface, member);
47 if (!isempty(types)) {
51 r = sd_bus_message_appendv(m, types, ap);
57 return sd_bus_send(bus, m, NULL);
60 _public_ int sd_bus_call_method_async(
63 const char *destination,
65 const char *interface,
67 sd_bus_message_handler_t callback,
69 const char *types, ...) {
71 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
74 assert_return(bus, -EINVAL);
75 assert_return(!bus_pid_changed(bus), -ECHILD);
77 if (!BUS_IS_OPEN(bus->state))
80 r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member);
84 if (!isempty(types)) {
88 r = sd_bus_message_appendv(m, types, ap);
94 return sd_bus_call_async(bus, slot, m, callback, userdata, 0);
97 _public_ int sd_bus_call_method(
99 const char *destination,
101 const char *interface,
104 sd_bus_message **reply,
105 const char *types, ...) {
107 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
110 bus_assert_return(bus, -EINVAL, error);
111 bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
113 if (!BUS_IS_OPEN(bus->state)) {
118 r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member);
122 if (!isempty(types)) {
126 r = sd_bus_message_appendv(m, types, ap);
132 return sd_bus_call(bus, m, 0, error, reply);
135 return sd_bus_error_set_errno(error, r);
138 _public_ int sd_bus_reply_method_return(
139 sd_bus_message *call,
140 const char *types, ...) {
142 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
145 assert_return(call, -EINVAL);
146 assert_return(call->sealed, -EPERM);
147 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
148 assert_return(call->bus, -EINVAL);
149 assert_return(!bus_pid_changed(call->bus), -ECHILD);
151 if (!BUS_IS_OPEN(call->bus->state))
154 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
157 r = sd_bus_message_new_method_return(call, &m);
161 if (!isempty(types)) {
165 r = sd_bus_message_appendv(m, types, ap);
171 return sd_bus_send(call->bus, m, NULL);
174 _public_ int sd_bus_reply_method_error(
175 sd_bus_message *call,
176 const sd_bus_error *e) {
178 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
181 assert_return(call, -EINVAL);
182 assert_return(call->sealed, -EPERM);
183 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
184 assert_return(sd_bus_error_is_set(e), -EINVAL);
185 assert_return(call->bus, -EINVAL);
186 assert_return(!bus_pid_changed(call->bus), -ECHILD);
188 if (!BUS_IS_OPEN(call->bus->state))
191 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
194 r = sd_bus_message_new_method_error(call, &m, e);
198 return sd_bus_send(call->bus, m, NULL);
201 _public_ int sd_bus_reply_method_errorf(
202 sd_bus_message *call,
207 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
210 assert_return(call, -EINVAL);
211 assert_return(call->sealed, -EPERM);
212 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
213 assert_return(call->bus, -EINVAL);
214 assert_return(!bus_pid_changed(call->bus), -ECHILD);
216 if (!BUS_IS_OPEN(call->bus->state))
219 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
222 va_start(ap, format);
223 bus_error_setfv(&error, name, format, ap);
226 return sd_bus_reply_method_error(call, &error);
229 _public_ int sd_bus_reply_method_errno(
230 sd_bus_message *call,
232 const sd_bus_error *p) {
234 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
236 assert_return(call, -EINVAL);
237 assert_return(call->sealed, -EPERM);
238 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
239 assert_return(call->bus, -EINVAL);
240 assert_return(!bus_pid_changed(call->bus), -ECHILD);
242 if (!BUS_IS_OPEN(call->bus->state))
245 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
248 if (sd_bus_error_is_set(p))
249 return sd_bus_reply_method_error(call, p);
251 sd_bus_error_set_errno(&berror, error);
253 return sd_bus_reply_method_error(call, &berror);
256 _public_ int sd_bus_reply_method_errnof(
257 sd_bus_message *call,
262 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
265 assert_return(call, -EINVAL);
266 assert_return(call->sealed, -EPERM);
267 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
268 assert_return(call->bus, -EINVAL);
269 assert_return(!bus_pid_changed(call->bus), -ECHILD);
271 if (!BUS_IS_OPEN(call->bus->state))
274 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
277 va_start(ap, format);
278 sd_bus_error_set_errnofv(&berror, error, format, ap);
281 return sd_bus_reply_method_error(call, &berror);
284 _public_ int sd_bus_get_property(
286 const char *destination,
288 const char *interface,
291 sd_bus_message **reply,
294 sd_bus_message *rep = NULL;
297 bus_assert_return(bus, -EINVAL, error);
298 bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
299 bus_assert_return(member_name_is_valid(member), -EINVAL, error);
300 bus_assert_return(reply, -EINVAL, error);
301 bus_assert_return(signature_is_single(type, false), -EINVAL, error);
302 bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
304 if (!BUS_IS_OPEN(bus->state)) {
309 r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member);
313 r = sd_bus_message_enter_container(rep, 'v', type);
315 sd_bus_message_unref(rep);
323 return sd_bus_error_set_errno(error, r);
326 _public_ int sd_bus_get_property_trivial(
328 const char *destination,
330 const char *interface,
333 char type, void *ptr) {
335 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
338 bus_assert_return(bus, -EINVAL, error);
339 bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
340 bus_assert_return(member_name_is_valid(member), -EINVAL, error);
341 bus_assert_return(bus_type_is_trivial(type), -EINVAL, error);
342 bus_assert_return(ptr, -EINVAL, error);
343 bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
345 if (!BUS_IS_OPEN(bus->state)) {
350 r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
354 r = sd_bus_message_enter_container(reply, 'v', CHAR_TO_STR(type));
358 r = sd_bus_message_read_basic(reply, type, ptr);
365 return sd_bus_error_set_errno(error, r);
368 _public_ int sd_bus_get_property_string(
370 const char *destination,
372 const char *interface,
377 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
382 bus_assert_return(bus, -EINVAL, error);
383 bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
384 bus_assert_return(member_name_is_valid(member), -EINVAL, error);
385 bus_assert_return(ret, -EINVAL, error);
386 bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
388 if (!BUS_IS_OPEN(bus->state)) {
393 r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
397 r = sd_bus_message_enter_container(reply, 'v', "s");
401 r = sd_bus_message_read_basic(reply, 's', &s);
415 return sd_bus_error_set_errno(error, r);
418 _public_ int sd_bus_get_property_strv(
420 const char *destination,
422 const char *interface,
427 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
430 bus_assert_return(bus, -EINVAL, error);
431 bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
432 bus_assert_return(member_name_is_valid(member), -EINVAL, error);
433 bus_assert_return(ret, -EINVAL, error);
434 bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
436 if (!BUS_IS_OPEN(bus->state)) {
441 r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
445 r = sd_bus_message_enter_container(reply, 'v', NULL);
449 r = sd_bus_message_read_strv(reply, ret);
456 return sd_bus_error_set_errno(error, r);
459 _public_ int sd_bus_set_property(
461 const char *destination,
463 const char *interface,
466 const char *type, ...) {
468 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
472 bus_assert_return(bus, -EINVAL, error);
473 bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
474 bus_assert_return(member_name_is_valid(member), -EINVAL, error);
475 bus_assert_return(signature_is_single(type, false), -EINVAL, error);
476 bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
478 if (!BUS_IS_OPEN(bus->state)) {
483 r = sd_bus_message_new_method_call(bus, &m, destination, path, "org.freedesktop.DBus.Properties", "Set");
487 r = sd_bus_message_append(m, "ss", strempty(interface), member);
491 r = sd_bus_message_open_container(m, 'v', type);
496 r = sd_bus_message_appendv(m, type, ap);
501 r = sd_bus_message_close_container(m);
505 return sd_bus_call(bus, m, 0, error, NULL);
508 return sd_bus_error_set_errno(error, r);
511 _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds) {
514 assert_return(call, -EINVAL);
515 assert_return(call->sealed, -EPERM);
516 assert_return(call->bus, -EINVAL);
517 assert_return(!bus_pid_changed(call->bus), -ECHILD);
519 if (!BUS_IS_OPEN(call->bus->state))
522 c = sd_bus_message_get_creds(call);
524 /* All data we need? */
525 if (c && (mask & ~c->mask) == 0) {
526 *creds = sd_bus_creds_ref(c);
530 /* No data passed? Or not enough data passed to retrieve the missing bits? */
531 if (!c || !(c->mask & SD_BUS_CREDS_PID)) {
532 /* We couldn't read anything from the call, let's try
533 * to get it from the sender or peer. */
536 /* There's a sender, but the creds are
537 * missing. This means we are talking via
538 * dbus1, or are getting a message that was
539 * sent to us via kdbus, but was converted
540 * from a dbus1 message by the bus-proxy and
541 * thus also lacks the creds. */
542 return sd_bus_get_name_creds(call->bus, call->sender, mask, creds);
544 /* There's no sender, hence we are on a dbus1
545 * direct connection. For direct connections
546 * the credentials of the AF_UNIX peer matter,
547 * which may be queried via
548 * sd_bus_get_owner_creds(). */
549 return sd_bus_get_owner_creds(call->bus, mask, creds);
552 return bus_creds_extend_by_pid(c, mask, creds);
555 _public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {
556 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
558 bool know_caps = false;
561 assert_return(call, -EINVAL);
562 assert_return(call->sealed, -EPERM);
563 assert_return(call->bus, -EINVAL);
564 assert_return(!bus_pid_changed(call->bus), -ECHILD);
566 if (!BUS_IS_OPEN(call->bus->state))
569 if (capability >= 0) {
571 r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds);
575 /* We cannot use augmented caps for authorization,
576 * since then data is acquired raceful from
577 * /proc. This can never actually happen, but let's
578 * better be safe than sorry, and do an extra check
580 assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EFFECTIVE_CAPS) == 0, -EPERM);
582 /* Note that not even on kdbus we might have the caps
583 * field, due to faked identities, or namespace
584 * translation issues. */
585 r = sd_bus_creds_has_effective_cap(creds, capability);
591 r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID, &creds);
596 /* Now, check the UID, but only if the capability check wasn't
599 if (our_uid != 0 || !know_caps || capability < 0) {
602 /* We cannot use augmented uid/euid for authorization,
603 * since then data is acquired raceful from
604 * /proc. This can never actually happen, but let's
605 * better be safe than sorry, and do an extra check
607 assert_return((sd_bus_creds_get_augmented_mask(creds) & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID)) == 0, -EPERM);
609 /* Try to use the EUID, if we have it. */
610 r = sd_bus_creds_get_euid(creds, &sender_uid);
612 r = sd_bus_creds_get_uid(creds, &sender_uid);
615 /* Sender has same UID as us, then let's grant access */
616 if (sender_uid == our_uid)
619 /* Sender is root, we are not root. */
620 if (our_uid != 0 && sender_uid == 0)