1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Daniel Mack
8 Copyright 2014 Kay Sievers
10 systemd is free software; you can redistribute it and/or modify it
11 under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
15 systemd is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public License
21 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/socket.h>
26 #include <sys/types.h>
37 #include "socket-util.h"
38 #include "sd-daemon.h"
40 #include "bus-internal.h"
41 #include "bus-message.h"
46 #include "capability.h"
47 #include "bus-policy.h"
49 static char *arg_address = NULL;
50 static char *arg_command_line_buffer = NULL;
51 static bool arg_drop_privileges = false;
52 static char **arg_configuration = NULL;
54 static int help(void) {
56 printf("%s [OPTIONS...]\n\n"
57 "Connect STDIO or a socket to a given bus address.\n\n"
58 " -h --help Show this help\n"
59 " --version Show package version\n"
60 " --drop-privileges Drop privileges\n"
61 " --configuration=PATH Configuration file or directory\n"
62 " --machine=MACHINE Connect to specified machine\n"
63 " --address=ADDRESS Connect to the bus specified by ADDRESS\n"
64 " (default: " DEFAULT_SYSTEM_BUS_PATH ")\n",
65 program_invocation_short_name);
70 static int parse_argv(int argc, char *argv[]) {
80 static const struct option options[] = {
81 { "help", no_argument, NULL, 'h' },
82 { "version", no_argument, NULL, ARG_VERSION },
83 { "address", required_argument, NULL, ARG_ADDRESS },
84 { "drop-privileges", no_argument, NULL, ARG_DROP_PRIVILEGES },
85 { "configuration", required_argument, NULL, ARG_CONFIGURATION },
86 { "machine", required_argument, NULL, ARG_MACHINE },
95 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
104 puts(PACKAGE_STRING);
105 puts(SYSTEMD_FEATURES);
120 case ARG_DROP_PRIVILEGES:
121 arg_drop_privileges = true;
124 case ARG_CONFIGURATION:
125 r = strv_extend(&arg_configuration, optarg);
131 _cleanup_free_ char *e = NULL;
134 e = bus_address_escape(optarg);
139 a = strjoin("x-container-kernel:machine=", e, ";x-container-unix:machine=", e, NULL);
141 a = strjoin("x-container-unix:machine=", e, NULL);
156 assert_not_reached("Unhandled option");
159 /* If the first command line argument is only "x" characters
160 * we'll write who we are talking to into it, so that "ps" is
162 arg_command_line_buffer = argv[optind];
163 if (argc > optind + 1 || (arg_command_line_buffer && !in_charset(arg_command_line_buffer, "x"))) {
164 log_error("Too many arguments");
169 arg_address = strdup(DEFAULT_SYSTEM_BUS_PATH);
177 static int rename_service(sd_bus *a, sd_bus *b) {
178 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
179 _cleanup_free_ char *p = NULL, *name = NULL;
189 r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM, &creds);
193 r = sd_bus_creds_get_uid(creds, &uid);
197 r = sd_bus_creds_get_pid(creds, &pid);
201 r = sd_bus_creds_get_cmdline(creds, &cmdline);
205 r = sd_bus_creds_get_comm(creds, &comm);
209 name = uid_to_name(uid);
213 p = strv_join(cmdline, " ");
217 /* The status string gets the full command line ... */
219 "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)",
223 /* ... and the argv line only the short comm */
224 if (arg_command_line_buffer) {
227 m = strlen(arg_command_line_buffer);
228 w = snprintf(arg_command_line_buffer, m,
229 "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]",
234 memzero(arg_command_line_buffer + w, m - w);
237 log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s",
245 static int synthesize_name_acquired(sd_bus *a, sd_bus *b, sd_bus_message *m) {
246 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
247 const char *name, *old_owner, *new_owner;
254 /* If we get NameOwnerChanged for our own name, we need to
255 * synthesize NameLost/NameAcquired, since socket clients need
256 * that, even though it is obsoleted on kdbus */
261 if (!sd_bus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged") ||
262 !streq_ptr(m->path, "/org/freedesktop/DBus") ||
263 !streq_ptr(m->sender, "org.freedesktop.DBus"))
266 r = sd_bus_message_read(m, "sss", &name, &old_owner, &new_owner);
270 r = sd_bus_message_rewind(m, true);
274 if (streq(old_owner, a->unique_name)) {
276 r = sd_bus_message_new_signal(
279 "/org/freedesktop/DBus",
280 "org.freedesktop.DBus",
283 } else if (streq(new_owner, a->unique_name)) {
285 r = sd_bus_message_new_signal(
288 "/org/freedesktop/DBus",
289 "org.freedesktop.DBus",
297 r = sd_bus_message_append(n, "s", name);
301 r = bus_message_append_sender(n, "org.freedesktop.DBus");
305 r = bus_seal_synthetic_message(b, n);
309 return sd_bus_send(b, n, NULL);
312 static int synthetic_driver_send(sd_bus *b, sd_bus_message *m) {
318 r = bus_message_append_sender(m, "org.freedesktop.DBus");
322 r = bus_seal_synthetic_message(b, m);
326 return sd_bus_send(b, m, NULL);
329 static int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) {
330 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
335 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
338 r = sd_bus_message_new_method_error(call, &m, e);
342 return synthetic_driver_send(call->bus, m);
345 static int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) {
347 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
351 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
354 if (sd_bus_error_is_set(p))
355 return synthetic_reply_method_error(call, p);
357 sd_bus_error_set_errno(&berror, error);
359 return synthetic_reply_method_error(call, &berror);
362 static int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) {
363 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
368 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
371 r = sd_bus_message_new_method_return(call, &m);
375 if (!isempty(types)) {
379 r = bus_message_append_ap(m, types, ap);
385 return synthetic_driver_send(call->bus, m);
388 static int synthetic_reply_return_strv(sd_bus_message *call, char **l) {
389 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
394 r = sd_bus_message_new_method_return(call, &m);
396 return synthetic_reply_method_errno(call, r, NULL);
398 r = sd_bus_message_append_strv(m, l);
400 return synthetic_reply_method_errno(call, r, NULL);
402 return synthetic_driver_send(call->bus, m);
405 static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
406 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
413 r = sd_bus_get_name_creds(bus, name, mask, &c);
414 if (r == -ESRCH || r == -ENXIO)
415 return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
419 if ((c->mask & mask) != mask)
428 static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
436 r = sd_bus_message_read(m, "s", &name);
440 return get_creds_by_name(bus, name, mask, _creds, error);
443 static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred, Set *owned_names) {
453 if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
456 /* The "Hello()" call is is handled in process_hello() */
458 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
460 if (!sd_bus_message_has_signature(m, ""))
461 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
463 return synthetic_reply_method_return(m, "s",
464 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
465 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
467 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
468 " <method name=\"Introspect\">\n"
469 " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
472 " <interface name=\"org.freedesktop.DBus\">\n"
473 " <method name=\"AddMatch\">\n"
474 " <arg type=\"s\" direction=\"in\"/>\n"
476 " <method name=\"RemoveMatch\">\n"
477 " <arg type=\"s\" direction=\"in\"/>\n"
479 " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
480 " <arg type=\"s\" direction=\"in\"/>\n"
481 " <arg type=\"ay\" direction=\"out\"/>\n"
483 " <method name=\"GetConnectionUnixProcessID\">\n"
484 " <arg type=\"s\" direction=\"in\"/>\n"
485 " <arg type=\"u\" direction=\"out\"/>\n"
487 " <method name=\"GetConnectionUnixUser\">\n"
488 " <arg type=\"s\" direction=\"in\"/>\n"
489 " <arg type=\"u\" direction=\"out\"/>\n"
491 " <method name=\"GetId\">\n"
492 " <arg type=\"s\" direction=\"out\"/>\n"
494 " <method name=\"GetNameOwner\">\n"
495 " <arg type=\"s\" direction=\"in\"/>\n"
496 " <arg type=\"s\" direction=\"out\"/>\n"
498 " <method name=\"Hello\">\n"
499 " <arg type=\"s\" direction=\"out\"/>\n"
501 " <method name=\"ListActivatableNames\">\n"
502 " <arg type=\"as\" direction=\"out\"/>\n"
504 " <method name=\"ListNames\">\n"
505 " <arg type=\"as\" direction=\"out\"/>\n"
507 " <method name=\"ListQueuedOwners\">\n"
508 " <arg type=\"s\" direction=\"in\"/>\n"
509 " <arg type=\"as\" direction=\"out\"/>\n"
511 " <method name=\"NameHasOwner\">\n"
512 " <arg type=\"s\" direction=\"in\"/>\n"
513 " <arg type=\"b\" direction=\"out\"/>\n"
515 " <method name=\"ReleaseName\">\n"
516 " <arg type=\"s\" direction=\"in\"/>\n"
517 " <arg type=\"u\" direction=\"out\"/>\n"
519 " <method name=\"ReloadConfig\">\n"
521 " <method name=\"RequestName\">\n"
522 " <arg type=\"s\" direction=\"in\"/>\n"
523 " <arg type=\"u\" direction=\"in\"/>\n"
524 " <arg type=\"u\" direction=\"out\"/>\n"
526 " <method name=\"StartServiceByName\">\n"
527 " <arg type=\"s\" direction=\"in\"/>\n"
528 " <arg type=\"u\" direction=\"in\"/>\n"
529 " <arg type=\"u\" direction=\"out\"/>\n"
531 " <method name=\"UpdateActivationEnvironment\">\n"
532 " <arg type=\"a{ss}\" direction=\"in\"/>\n"
534 " <signal name=\"NameAcquired\">\n"
535 " <arg type=\"s\"/>\n"
537 " <signal name=\"NameLost\">\n"
538 " <arg type=\"s\"/>\n"
540 " <signal name=\"NameOwnerChanged\">\n"
541 " <arg type=\"s\"/>\n"
542 " <arg type=\"s\"/>\n"
543 " <arg type=\"s\"/>\n"
548 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
551 if (!sd_bus_message_has_signature(m, "s"))
552 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
554 r = sd_bus_message_read(m, "s", &match);
556 return synthetic_reply_method_errno(m, r, NULL);
558 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
560 return synthetic_reply_method_errno(m, r, NULL);
562 return synthetic_reply_method_return(m, NULL);
564 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
567 if (!sd_bus_message_has_signature(m, "s"))
568 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
570 r = sd_bus_message_read(m, "s", &match);
572 return synthetic_reply_method_errno(m, r, NULL);
574 r = bus_remove_match_by_string(a, match, NULL, NULL);
576 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
578 return synthetic_reply_method_errno(m, r, NULL);
580 return synthetic_reply_method_return(m, NULL);
582 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
583 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
584 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
586 if (!sd_bus_message_has_signature(m, "s"))
587 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
589 r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
591 return synthetic_reply_method_errno(m, r, &error);
593 return synthetic_reply_method_return(m, "y", creds->label, strlen(creds->label));
595 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
596 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
597 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
599 if (!sd_bus_message_has_signature(m, "s"))
600 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
602 r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error);
604 return synthetic_reply_method_errno(m, r, &error);
606 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
608 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
609 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
610 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
612 if (!sd_bus_message_has_signature(m, "s"))
613 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
615 r = get_creds_by_message(a, m, SD_BUS_CREDS_UID, &creds, &error);
617 return synthetic_reply_method_errno(m, r, &error);
619 return synthetic_reply_method_return(m, "u", (uint32_t) creds->uid);
621 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
622 sd_id128_t server_id;
623 char buf[SD_ID128_STRING_MAX];
625 if (!sd_bus_message_has_signature(m, ""))
626 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
628 r = sd_bus_get_owner_id(a, &server_id);
630 return synthetic_reply_method_errno(m, r, NULL);
632 return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
634 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
636 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
637 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
639 if (!sd_bus_message_has_signature(m, "s"))
640 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
642 r = sd_bus_message_read(m, "s", &name);
644 return synthetic_reply_method_errno(m, r, NULL);
646 if (streq(name, "org.freedesktop.DBus"))
647 return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
649 r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
651 return synthetic_reply_method_errno(m, r, &error);
653 return synthetic_reply_method_return(m, "s", creds->unique_name);
655 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
656 _cleanup_strv_free_ char **names = NULL;
658 if (!sd_bus_message_has_signature(m, ""))
659 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
661 r = sd_bus_list_names(a, NULL, &names);
663 return synthetic_reply_method_errno(m, r, NULL);
665 /* Let's sort the names list to make it stable */
668 return synthetic_reply_return_strv(m, names);
670 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
671 _cleanup_strv_free_ char **names = NULL;
673 if (!sd_bus_message_has_signature(m, ""))
674 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
676 r = sd_bus_list_names(a, &names, NULL);
678 return synthetic_reply_method_errno(m, r, NULL);
680 r = strv_extend(&names, "org.freedesktop.DBus");
682 return synthetic_reply_method_errno(m, r, NULL);
684 /* Let's sort the names list to make it stable */
687 return synthetic_reply_return_strv(m, names);
689 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
690 struct kdbus_cmd_name_list cmd = {};
691 struct kdbus_name_list *name_list;
692 struct kdbus_cmd_free cmd_free;
693 struct kdbus_name_info *name;
694 _cleanup_strv_free_ char **owners = NULL;
695 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
699 if (!sd_bus_message_has_signature(m, "s"))
700 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
702 r = sd_bus_message_read(m, "s", &arg0);
704 return synthetic_reply_method_errno(m, r, NULL);
706 r = sd_bus_get_name_creds(a, arg0, 0, NULL);
707 if (r == -ESRCH || r == -ENXIO) {
708 sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0);
709 return synthetic_reply_method_errno(m, r, &error);
712 return synthetic_reply_method_errno(m, r, NULL);
714 cmd.flags = KDBUS_NAME_LIST_QUEUED;
715 r = ioctl(a->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
717 return synthetic_reply_method_errno(m, -errno, NULL);
719 name_list = (struct kdbus_name_list *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
721 KDBUS_ITEM_FOREACH(name, name_list, names) {
722 const char *entry_name = NULL;
723 struct kdbus_item *item;
726 KDBUS_ITEM_FOREACH(item, name, items)
727 if (item->type == KDBUS_ITEM_OWNED_NAME)
728 entry_name = item->name.name;
730 if (!streq_ptr(entry_name, arg0))
733 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
738 r = strv_consume(&owners, n);
746 cmd_free.offset = cmd.offset;
748 r = ioctl(a->input_fd, KDBUS_CMD_FREE, &cmd_free);
750 return synthetic_reply_method_errno(m, r, NULL);
753 return synthetic_reply_method_errno(m, err, NULL);
755 return synthetic_reply_return_strv(m, owners);
757 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
760 if (!sd_bus_message_has_signature(m, "s"))
761 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
763 r = sd_bus_message_read(m, "s", &name);
765 return synthetic_reply_method_errno(m, r, NULL);
767 if (streq(name, "org.freedesktop.DBus"))
768 return synthetic_reply_method_return(m, "b", true);
770 r = sd_bus_get_name_creds(a, name, 0, NULL);
771 if (r < 0 && r != -ESRCH && r != -ENXIO)
772 return synthetic_reply_method_errno(m, r, NULL);
774 return synthetic_reply_method_return(m, "b", r >= 0);
776 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
779 if (!sd_bus_message_has_signature(m, "s"))
780 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
782 r = sd_bus_message_read(m, "s", &name);
784 return synthetic_reply_method_errno(m, r, NULL);
786 r = sd_bus_release_name(a, name);
789 return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
790 if (r == -EADDRINUSE)
791 return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
793 return synthetic_reply_method_errno(m, r, NULL);
796 set_remove(owned_names, (char*) name);
798 return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
800 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
801 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
803 if (!sd_bus_message_has_signature(m, ""))
804 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
806 r = sd_bus_error_setf(&error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
808 return synthetic_reply_method_errno(m, r, &error);
810 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
812 uint32_t flags, param;
815 if (!sd_bus_message_has_signature(m, "su"))
816 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
818 r = sd_bus_message_read(m, "su", &name, &flags);
820 return synthetic_reply_method_errno(m, r, NULL);
822 if (policy && !policy_check_own(policy, ucred->uid, ucred->gid, name))
823 return synthetic_reply_method_errno(m, -EPERM, NULL);
825 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
826 return synthetic_reply_method_errno(m, -EINVAL, NULL);
829 if (flags & BUS_NAME_ALLOW_REPLACEMENT)
830 param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
831 if (flags & BUS_NAME_REPLACE_EXISTING)
832 param |= SD_BUS_NAME_REPLACE_EXISTING;
833 if (!(flags & BUS_NAME_DO_NOT_QUEUE))
834 param |= SD_BUS_NAME_QUEUE;
836 r = set_put_strdup(owned_names, name);
838 return synthetic_reply_method_errno(m, r, NULL);
840 r = sd_bus_request_name(a, name, param);
843 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
845 set_remove(owned_names, (char*) name);
848 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
849 return synthetic_reply_method_errno(m, r, NULL);
855 return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
857 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
859 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
860 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
864 if (!sd_bus_message_has_signature(m, "su"))
865 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
867 r = sd_bus_message_read(m, "su", &name, &flags);
869 return synthetic_reply_method_errno(m, r, NULL);
872 return synthetic_reply_method_errno(m, -EINVAL, NULL);
874 r = sd_bus_get_name_creds(a, name, 0, NULL);
875 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
876 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
878 return synthetic_reply_method_errno(m, r, NULL);
880 r = sd_bus_message_new_method_call(
885 "org.freedesktop.DBus.Peer",
888 return synthetic_reply_method_errno(m, r, NULL);
890 r = sd_bus_send(a, msg, NULL);
892 return synthetic_reply_method_errno(m, r, NULL);
894 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
896 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
897 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
898 _cleanup_strv_free_ char **args = NULL;
900 if (!sd_bus_message_has_signature(m, "a{ss}"))
901 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
903 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
905 return synthetic_reply_method_errno(m, r, NULL);
907 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
908 _cleanup_free_ char *s = NULL;
912 r = sd_bus_message_read(m, "ss", &key, &value);
914 return synthetic_reply_method_errno(m, r, NULL);
916 s = strjoin(key, "=", value, NULL);
918 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
920 r = strv_extend(&args, s);
922 return synthetic_reply_method_errno(m, r, NULL);
924 r = sd_bus_message_exit_container(m);
926 return synthetic_reply_method_errno(m, r, NULL);
929 r = sd_bus_message_exit_container(m);
931 return synthetic_reply_method_errno(m, r, NULL);
934 return synthetic_reply_method_errno(m, -EINVAL, NULL);
936 r = sd_bus_message_new_method_call(
939 "org.freedesktop.systemd1",
940 "/org/freedesktop/systemd1",
941 "org.freedesktop.systemd1.Manager",
944 return synthetic_reply_method_errno(m, r, NULL);
946 r = sd_bus_message_append_strv(msg, args);
948 return synthetic_reply_method_errno(m, r, NULL);
950 r = sd_bus_call(a, msg, 0, NULL, NULL);
952 return synthetic_reply_method_errno(m, r, NULL);
954 return synthetic_reply_method_return(m, NULL);
957 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
959 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
961 return synthetic_reply_method_errno(m, r, &error);
965 static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
975 if (from->is_kernel) {
976 uid_t sender_uid = (uid_t) -1;
977 gid_t sender_gid = (gid_t) -1;
978 char **sender_names = NULL;
979 bool granted = false;
981 /* Driver messages are always OK */
982 if (streq_ptr(m->sender, "org.freedesktop.DBus"))
985 /* The message came from the kernel, and is sent to our legacy client. */
986 r = sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
990 (void) sd_bus_creds_get_uid(&m->creds, &sender_uid);
991 (void) sd_bus_creds_get_gid(&m->creds, &sender_gid);
993 /* First check whether the sender can send the message to our name */
994 if (set_isempty(owned_names)) {
995 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, NULL, m->path, m->interface, m->member))
1001 SET_FOREACH(n, owned_names, i)
1002 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, n, m->path, m->interface, m->member)) {
1009 /* Then check whether us, the recipient can recieve from the sender's name */
1010 if (strv_isempty(sender_names)) {
1011 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1016 STRV_FOREACH(n, sender_names) {
1017 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member))
1023 /* Return an error back to the caller */
1024 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1025 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
1027 /* Return 1, indicating that the message shall not be processed any further */
1031 if (to->is_kernel) {
1032 _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL;
1033 uid_t destination_uid = (uid_t) -1;
1034 gid_t destination_gid = (gid_t) -1;
1035 const char *destination_unique = NULL;
1036 char **destination_names = NULL;
1037 bool granted = false;
1039 /* Driver messages are always OK */
1040 if (streq_ptr(m->destination, "org.freedesktop.DBus"))
1043 /* The message came from the legacy client, and is sent to kdbus. */
1044 if (m->destination) {
1045 r = sd_bus_get_name_creds(to, m->destination,
1046 SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
1047 SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID, &destination_creds);
1051 r = sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
1055 r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
1059 (void) sd_bus_creds_get_uid(destination_creds, &destination_uid);
1060 (void) sd_bus_creds_get_gid(destination_creds, &destination_gid);
1063 /* First check if we, the sender can send to this name */
1064 if (strv_isempty(destination_names)) {
1065 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1070 STRV_FOREACH(n, destination_names) {
1071 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member)) {
1073 /* If we made a receiver decision,
1074 then remember which name's policy
1075 we used, and to which unique ID it
1076 mapped when we made the
1077 decision. Then, let's pass this to
1078 the kernel when sending the
1079 message, so that it refuses the
1080 operation should the name and
1081 unique ID not map to each other
1084 r = free_and_strdup(&m->destination_ptr, *n);
1088 r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
1098 /* Then check if the recipient can receive from our name */
1100 if (set_isempty(owned_names)) {
1101 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, NULL, m->path, m->interface, m->member))
1107 SET_FOREACH(n, owned_names, i)
1108 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, n, m->path, m->interface, m->member))
1113 /* Return an error back to the caller */
1114 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1115 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
1117 /* Return 1, indicating that the message shall not be processed any further */
1124 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
1125 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
1134 /* As reaction to hello we need to respond with two messages:
1135 * the callback reply and the NameAcquired for the unique
1136 * name, since hello is otherwise obsolete on kdbus. */
1139 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1140 streq_ptr(m->destination, "org.freedesktop.DBus");
1147 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1152 log_error("Got duplicate hello, aborting.");
1161 r = sd_bus_message_new_method_return(m, &n);
1163 log_error("Failed to generate HELLO reply: %s", strerror(-r));
1167 r = sd_bus_message_append(n, "s", a->unique_name);
1169 log_error("Failed to append unique name to HELLO reply: %s", strerror(-r));
1173 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1175 log_error("Failed to append sender to HELLO reply: %s", strerror(-r));
1179 r = bus_seal_synthetic_message(b, n);
1181 log_error("Failed to seal HELLO reply: %s", strerror(-r));
1185 r = sd_bus_send(b, n, NULL);
1187 log_error("Failed to send HELLO reply: %s", strerror(-r));
1191 n = sd_bus_message_unref(n);
1192 r = sd_bus_message_new_signal(
1195 "/org/freedesktop/DBus",
1196 "org.freedesktop.DBus",
1199 log_error("Failed to allocate initial NameAcquired message: %s", strerror(-r));
1203 r = sd_bus_message_append(n, "s", a->unique_name);
1205 log_error("Failed to append unique name to NameAcquired message: %s", strerror(-r));
1209 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1211 log_error("Failed to append sender to NameAcquired message: %s", strerror(-r));
1215 r = bus_seal_synthetic_message(b, n);
1217 log_error("Failed to seal NameAcquired message: %s", strerror(-r));
1221 r = sd_bus_send(b, n, NULL);
1223 log_error("Failed to send NameAcquired message: %s", strerror(-r));
1230 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1231 char **well_known = NULL;
1241 /* We will change the sender of messages from the bus driver
1242 * so that they originate from the bus driver. This is a
1243 * speciality originating from dbus1, where the bus driver did
1244 * not have a unique id, but only the well-known name. */
1246 c = sd_bus_message_get_creds(m);
1250 r = sd_bus_creds_get_well_known_names(c, &well_known);
1254 if (strv_contains(well_known, "org.freedesktop.DBus"))
1255 m->sender = "org.freedesktop.DBus";
1260 int main(int argc, char *argv[]) {
1262 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1263 sd_id128_t server_id;
1264 int r, in_fd, out_fd;
1265 bool got_hello = false;
1267 struct ucred ucred = {};
1268 _cleanup_free_ char *peersec = NULL;
1269 Policy policy_buffer = {}, *policy = NULL;
1270 _cleanup_set_free_free_ Set *owned_names = NULL;
1272 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1273 log_parse_environment();
1276 r = parse_argv(argc, argv);
1280 r = sd_listen_fds(0);
1282 in_fd = STDIN_FILENO;
1283 out_fd = STDOUT_FILENO;
1284 } else if (r == 1) {
1285 in_fd = SD_LISTEN_FDS_START;
1286 out_fd = SD_LISTEN_FDS_START;
1288 log_error("Illegal number of file descriptors passed");
1293 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1294 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1297 (void) getpeercred(in_fd, &ucred);
1298 (void) getpeersec(in_fd, &peersec);
1301 if (arg_drop_privileges) {
1302 const char *user = "systemd-bus-proxy";
1306 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1308 log_error("Cannot resolve user name %s: %s", user, strerror(-r));
1312 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1317 owned_names = set_new(&string_hash_ops);
1325 log_error("Failed to allocate bus: %s", strerror(-r));
1329 r = sd_bus_set_description(a, "sd-proxy");
1331 log_error("Failed to set bus name: %s", strerror(-r));
1335 r = sd_bus_set_address(a, arg_address);
1337 log_error("Failed to set address to connect to: %s", strerror(-r));
1341 r = sd_bus_negotiate_fds(a, is_unix);
1343 log_error("Failed to set FD negotiation: %s", strerror(-r));
1347 r = sd_bus_negotiate_creds(a, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1349 log_error("Failed to set credential negotiation: %s", strerror(-r));
1353 if (ucred.pid > 0) {
1354 a->fake_pids.pid = ucred.pid;
1355 a->fake_pids_valid = true;
1357 a->fake_creds.uid = ucred.uid;
1358 a->fake_creds.euid = (uid_t) -1;
1359 a->fake_creds.suid = (uid_t) -1;
1360 a->fake_creds.fsuid = (uid_t) -1;
1361 a->fake_creds.gid = ucred.gid;
1362 a->fake_creds.egid = (gid_t) -1;
1363 a->fake_creds.sgid = (gid_t) -1;
1364 a->fake_creds.fsgid = (gid_t) -1;
1365 a->fake_creds_valid = true;
1369 a->fake_label = peersec;
1373 a->manual_peer_interface = true;
1375 r = sd_bus_start(a);
1377 log_error("Failed to start bus client: %s", strerror(-r));
1381 r = sd_bus_get_owner_id(a, &server_id);
1383 log_error("Failed to get server ID: %s", strerror(-r));
1388 _cleanup_bus_creds_unref_ sd_bus_creds *bus_creds = NULL;
1391 r = sd_bus_get_owner_creds(a, SD_BUS_CREDS_UID, &bus_creds);
1393 log_error("Failed to get bus creds: %s", strerror(-r));
1397 r = sd_bus_creds_get_uid(bus_creds, &bus_uid);
1399 log_error("Failed to get bus owner UID: %s", strerror(-r));
1404 /* We only enforce the old XML policy on
1405 * kernel busses owned by root users. */
1407 r = policy_load(&policy_buffer, arg_configuration);
1409 log_error("Failed to load policy: %s", strerror(-r));
1413 if (!policy_check_hello(&policy_buffer, ucred.uid, ucred.gid)) {
1414 log_error("Policy denied connection");
1419 policy_dump(&policy_buffer);
1420 policy = &policy_buffer;
1426 log_error("Failed to allocate bus: %s", strerror(-r));
1430 r = sd_bus_set_fd(b, in_fd, out_fd);
1432 log_error("Failed to set fds: %s", strerror(-r));
1436 r = sd_bus_set_server(b, 1, server_id);
1438 log_error("Failed to set server mode: %s", strerror(-r));
1442 r = sd_bus_negotiate_fds(b, is_unix);
1444 log_error("Failed to set FD negotiation: %s", strerror(-r));
1448 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1450 log_error("Failed to set credential negotiation: %s", strerror(-r));
1454 r = sd_bus_set_anonymous(b, true);
1456 log_error("Failed to set anonymous authentication: %s", strerror(-r));
1460 b->manual_peer_interface = true;
1462 r = sd_bus_start(b);
1464 log_error("Failed to start bus client: %s", strerror(-r));
1468 r = rename_service(a, b);
1470 log_debug("Failed to rename process: %s", strerror(-r));
1473 _cleanup_free_ char *match = NULL;
1476 r = sd_bus_get_unique_name(a, &unique);
1478 log_error("Failed to get unique name: %s", strerror(-r));
1482 match = strjoin("type='signal',"
1483 "sender='org.freedesktop.DBus',"
1484 "path='/org/freedesktop/DBus',"
1485 "interface='org.freedesktop.DBus',"
1486 "member='NameOwnerChanged',"
1496 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1498 log_error("Failed to add match for NameLost: %s", strerror(-r));
1503 match = strjoin("type='signal',"
1504 "sender='org.freedesktop.DBus',"
1505 "path='/org/freedesktop/DBus',"
1506 "interface='org.freedesktop.DBus',"
1507 "member='NameOwnerChanged',"
1517 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1519 log_error("Failed to add match for NameAcquired: %s", strerror(-r));
1525 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1526 int events_a, events_b, fd;
1527 uint64_t timeout_a, timeout_b, t;
1528 struct timespec _ts, *ts;
1529 struct pollfd *pollfd;
1533 /* Read messages from bus, to pass them on to our client */
1535 r = sd_bus_process(a, &m);
1537 /* treat 'connection reset by peer' as clean exit condition */
1538 if (r == -ECONNRESET)
1541 log_error("Failed to process bus a: %s", strerror(-r));
1547 bool processed = false;
1549 /* We officially got EOF, let's quit */
1550 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1555 k = synthesize_name_acquired(a, b, m);
1558 log_error("Failed to synthesize message: %s", strerror(-r));
1565 k = process_policy(a, b, m, policy, &ucred, owned_names);
1568 log_error("Failed to process policy: %s", strerror(-r));
1577 k = sd_bus_send(b, m, NULL);
1579 if (k == -ECONNRESET)
1583 log_error("Failed to send message to client: %s", strerror(-r));
1596 /* Read messages from our client, to pass them on to the bus */
1597 r = sd_bus_process(b, &m);
1599 /* treat 'connection reset by peer' as clean exit condition */
1600 if (r == -ECONNRESET)
1603 log_error("Failed to process bus b: %s", strerror(-r));
1609 bool processed = false;
1611 /* We officially got EOF, let's quit */
1612 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1617 k = process_hello(a, b, m, &got_hello);
1620 log_error("Failed to process HELLO: %s", strerror(-r));
1628 k = process_driver(a, b, m, policy, &ucred, owned_names);
1631 log_error("Failed to process driver calls: %s", strerror(-r));
1642 k = process_policy(b, a, m, policy, &ucred, owned_names);
1645 log_error("Failed to process policy: %s", strerror(-r));
1654 k = sd_bus_send(a, m, NULL);
1657 /* The name database changed since the policy check, hence let's check again */
1659 else if (k == -ECONNRESET)
1663 log_error("Failed to send message to bus: %s", strerror(-r));
1679 fd = sd_bus_get_fd(a);
1681 log_error("Failed to get fd: %s", strerror(-r));
1685 events_a = sd_bus_get_events(a);
1687 log_error("Failed to get events mask: %s", strerror(-r));
1691 r = sd_bus_get_timeout(a, &timeout_a);
1693 log_error("Failed to get timeout: %s", strerror(-r));
1697 events_b = sd_bus_get_events(b);
1699 log_error("Failed to get events mask: %s", strerror(-r));
1703 r = sd_bus_get_timeout(b, &timeout_b);
1705 log_error("Failed to get timeout: %s", strerror(-r));
1710 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1713 if (t == (uint64_t) -1)
1718 nw = now(CLOCK_MONOTONIC);
1724 ts = timespec_store(&_ts, t);
1727 pollfd = (struct pollfd[3]) {
1728 {.fd = fd, .events = events_a, },
1729 {.fd = in_fd, .events = events_b & POLLIN, },
1730 {.fd = out_fd, .events = events_b & POLLOUT, }
1733 r = ppoll(pollfd, 3, ts, NULL);
1735 log_error("ppoll() failed: %m");
1743 "STATUS=Shutting down.");
1745 policy_free(&policy_buffer);
1746 strv_free(arg_configuration);
1749 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;