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"
43 #include "bus-internal.h"
47 #include "capability.h"
48 #include "bus-policy.h"
50 static char *arg_address = NULL;
51 static char *arg_command_line_buffer = NULL;
52 static bool arg_drop_privileges = false;
53 static char **arg_configuration = NULL;
55 static int help(void) {
57 printf("%s [OPTIONS...]\n\n"
58 "Connect STDIO or a socket to a given bus address.\n\n"
59 " -h --help Show this help\n"
60 " --version Show package version\n"
61 " --drop-privileges Drop privileges\n"
62 " --configuration=PATH Configuration file or directory\n"
63 " --machine=MACHINE Connect to specified machine\n"
64 " --address=ADDRESS Connect to the bus specified by ADDRESS\n"
65 " (default: " DEFAULT_SYSTEM_BUS_PATH ")\n",
66 program_invocation_short_name);
71 static int parse_argv(int argc, char *argv[]) {
81 static const struct option options[] = {
82 { "help", no_argument, NULL, 'h' },
83 { "version", no_argument, NULL, ARG_VERSION },
84 { "address", required_argument, NULL, ARG_ADDRESS },
85 { "drop-privileges", no_argument, NULL, ARG_DROP_PRIVILEGES },
86 { "configuration", required_argument, NULL, ARG_CONFIGURATION },
87 { "machine", required_argument, NULL, ARG_MACHINE },
96 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
105 puts(PACKAGE_STRING);
106 puts(SYSTEMD_FEATURES);
121 case ARG_DROP_PRIVILEGES:
122 arg_drop_privileges = true;
125 case ARG_CONFIGURATION:
126 r = strv_extend(&arg_configuration, optarg);
132 _cleanup_free_ char *e = NULL;
135 e = bus_address_escape(optarg);
140 a = strjoin("x-container-kernel:machine=", e, ";x-container-unix:machine=", e, NULL);
142 a = strjoin("x-container-unix:machine=", e, NULL);
157 assert_not_reached("Unhandled option");
160 /* If the first command line argument is only "x" characters
161 * we'll write who we are talking to into it, so that "ps" is
163 arg_command_line_buffer = argv[optind];
164 if (argc > optind + 1 || (arg_command_line_buffer && !in_charset(arg_command_line_buffer, "x"))) {
165 log_error("Too many arguments");
170 arg_address = strdup(DEFAULT_SYSTEM_BUS_PATH);
178 static int rename_service(sd_bus *a, sd_bus *b) {
179 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
180 _cleanup_free_ char *p = NULL, *name = NULL;
190 r = sd_bus_get_peer_creds(b, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM, &creds);
194 r = sd_bus_creds_get_uid(creds, &uid);
198 r = sd_bus_creds_get_pid(creds, &pid);
202 r = sd_bus_creds_get_cmdline(creds, &cmdline);
206 r = sd_bus_creds_get_comm(creds, &comm);
210 name = uid_to_name(uid);
214 p = strv_join(cmdline, " ");
218 /* The status string gets the full command line ... */
220 "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)",
224 /* ... and the argv line only the short comm */
225 if (arg_command_line_buffer) {
228 m = strlen(arg_command_line_buffer);
229 w = snprintf(arg_command_line_buffer, m,
230 "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]",
235 memzero(arg_command_line_buffer + w, m - w);
238 log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s",
246 static int synthesize_name_acquired(sd_bus *a, sd_bus *b, sd_bus_message *m) {
247 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
248 const char *name, *old_owner, *new_owner;
255 /* If we get NameOwnerChanged for our own name, we need to
256 * synthesize NameLost/NameAcquired, since socket clients need
257 * that, even though it is obsoleted on kdbus */
262 if (!sd_bus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged") ||
263 !streq_ptr(m->path, "/org/freedesktop/DBus") ||
264 !streq_ptr(m->sender, "org.freedesktop.DBus"))
267 r = sd_bus_message_read(m, "sss", &name, &old_owner, &new_owner);
271 r = sd_bus_message_rewind(m, true);
275 if (streq(old_owner, a->unique_name)) {
277 r = sd_bus_message_new_signal(
280 "/org/freedesktop/DBus",
281 "org.freedesktop.DBus",
284 } else if (streq(new_owner, a->unique_name)) {
286 r = sd_bus_message_new_signal(
289 "/org/freedesktop/DBus",
290 "org.freedesktop.DBus",
298 r = sd_bus_message_append(n, "s", name);
302 r = bus_message_append_sender(n, "org.freedesktop.DBus");
306 r = bus_seal_synthetic_message(b, n);
310 return sd_bus_send(b, n, NULL);
313 static int process_policy(sd_bus *a, sd_bus *b, sd_bus_message *m) {
314 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
324 if (!sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "GetAll"))
327 if (!streq_ptr(m->path, "/org/gnome/DisplayManager/Slave"))
330 r = sd_bus_message_new_method_errorf(m, &n, SD_BUS_ERROR_ACCESS_DENIED, "gdm, you are stupid");
334 r = bus_message_append_sender(n, "org.freedesktop.DBus");
336 log_error("Failed to append sender to gdm reply: %s", strerror(-r));
340 r = bus_seal_synthetic_message(b, n);
342 log_error("Failed to seal gdm reply: %s", strerror(-r));
346 r = sd_bus_send(b, n, NULL);
348 log_error("Failed to send gdm reply: %s", strerror(-r));
355 static int synthetic_driver_send(sd_bus *b, sd_bus_message *m) {
361 r = bus_message_append_sender(m, "org.freedesktop.DBus");
365 r = bus_seal_synthetic_message(b, m);
369 return sd_bus_send(b, m, NULL);
372 static int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) {
373 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
378 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
381 r = sd_bus_message_new_method_error(call, &m, e);
385 return synthetic_driver_send(call->bus, m);
388 static int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) {
390 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
394 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
397 if (sd_bus_error_is_set(p))
398 return synthetic_reply_method_error(call, p);
400 sd_bus_error_set_errno(&berror, error);
402 return synthetic_reply_method_error(call, &berror);
405 static int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) {
406 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
411 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
414 r = sd_bus_message_new_method_return(call, &m);
418 if (!isempty(types)) {
422 r = bus_message_append_ap(m, types, ap);
428 return synthetic_driver_send(call->bus, m);
431 static int synthetic_reply_return_strv(sd_bus_message *call, char **l) {
432 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
437 r = sd_bus_message_new_method_return(call, &m);
439 return synthetic_reply_method_errno(call, r, NULL);
441 r = sd_bus_message_append_strv(m, l);
443 return synthetic_reply_method_errno(call, r, NULL);
445 return synthetic_driver_send(call->bus, m);
448 static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
449 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
456 assert_return(service_name_is_valid(name), -EINVAL);
458 r = sd_bus_get_owner(bus, name, mask, &c);
459 if (r == -ESRCH || r == -ENXIO)
460 return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
464 if ((c->mask & mask) != mask)
473 static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
481 r = sd_bus_message_read(m, "s", &name);
485 return get_creds_by_name(bus, name, mask, _creds, error);
488 static int peer_is_privileged(sd_bus *bus, sd_bus_message *m) {
489 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
493 r = get_creds_by_message(bus, m, SD_BUS_CREDS_UID, &creds, NULL);
497 r = sd_bus_creds_get_uid(creds, &uid);
501 r = sd_bus_creds_has_effective_cap(creds, CAP_SYS_ADMIN);
511 static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) {
521 if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
524 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
525 if (0 && !isempty(sd_bus_message_get_signature(m, true))) {
526 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
528 r = sd_bus_error_setf(&error, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters");
530 return synthetic_reply_method_errno(m, r, &error);
533 return synthetic_reply_method_return(m, "s",
534 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
535 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
537 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
538 " <method name=\"Introspect\">\n"
539 " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
542 " <interface name=\"org.freedesktop.DBus\">\n"
543 " <method name=\"AddMatch\">\n"
544 " <arg type=\"s\" direction=\"in\"/>\n"
546 " <method name=\"RemoveMatch\">\n"
547 " <arg type=\"s\" direction=\"in\"/>\n"
549 " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
550 " <arg type=\"s\" direction=\"in\"/>\n"
551 " <arg type=\"ay\" direction=\"out\"/>\n"
553 " <method name=\"GetConnectionUnixProcessID\">\n"
554 " <arg type=\"s\" direction=\"in\"/>\n"
555 " <arg type=\"u\" direction=\"out\"/>\n"
557 " <method name=\"GetConnectionUnixUser\">\n"
558 " <arg type=\"s\" direction=\"in\"/>\n"
559 " <arg type=\"u\" direction=\"out\"/>\n"
561 " <method name=\"GetId\">\n"
562 " <arg type=\"s\" direction=\"out\"/>\n"
564 " <method name=\"GetNameOwner\">\n"
565 " <arg type=\"s\" direction=\"in\"/>\n"
566 " <arg type=\"s\" direction=\"out\"/>\n"
568 " <method name=\"Hello\">\n"
569 " <arg type=\"s\" direction=\"out\"/>\n"
571 " <method name=\"ListActivatableNames\">\n"
572 " <arg type=\"as\" direction=\"out\"/>\n"
574 " <method name=\"ListNames\">\n"
575 " <arg type=\"as\" direction=\"out\"/>\n"
577 " <method name=\"ListQueuedOwners\">\n"
578 " <arg type=\"s\" direction=\"in\"/>\n"
579 " <arg type=\"as\" direction=\"out\"/>\n"
581 " <method name=\"NameHasOwner\">\n"
582 " <arg type=\"s\" direction=\"in\"/>\n"
583 " <arg type=\"b\" direction=\"out\"/>\n"
585 " <method name=\"ReleaseName\">\n"
586 " <arg type=\"s\" direction=\"in\"/>\n"
587 " <arg type=\"u\" direction=\"out\"/>\n"
589 " <method name=\"ReloadConfig\">\n"
591 " <method name=\"RequestName\">\n"
592 " <arg type=\"s\" direction=\"in\"/>\n"
593 " <arg type=\"u\" direction=\"in\"/>\n"
594 " <arg type=\"u\" direction=\"out\"/>\n"
596 " <method name=\"StartServiceByName\">\n"
597 " <arg type=\"s\" direction=\"in\"/>\n"
598 " <arg type=\"u\" direction=\"in\"/>\n"
599 " <arg type=\"u\" direction=\"out\"/>\n"
601 " <method name=\"UpdateActivationEnvironment\">\n"
602 " <arg type=\"a{ss}\" direction=\"in\"/>\n"
604 " <signal name=\"NameAcquired\">\n"
605 " <arg type=\"s\"/>\n"
607 " <signal name=\"NameLost\">\n"
608 " <arg type=\"s\"/>\n"
610 " <signal name=\"NameOwnerChanged\">\n"
611 " <arg type=\"s\"/>\n"
612 " <arg type=\"s\"/>\n"
613 " <arg type=\"s\"/>\n"
618 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
621 r = sd_bus_message_read(m, "s", &match);
623 return synthetic_reply_method_errno(m, r, NULL);
625 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
627 return synthetic_reply_method_errno(m, r, NULL);
629 return synthetic_reply_method_return(m, NULL);
631 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
634 r = sd_bus_message_read(m, "s", &match);
636 return synthetic_reply_method_errno(m, r, NULL);
638 r = bus_remove_match_by_string(a, match, NULL, NULL);
640 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
642 return synthetic_reply_method_errno(m, r, NULL);
644 return synthetic_reply_method_return(m, NULL);
646 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
647 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
649 r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, NULL);
651 return synthetic_reply_method_errno(m, r, NULL);
653 return synthetic_reply_method_return(m, "y", creds->label, strlen(creds->label));
655 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
656 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
658 r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, NULL);
660 return synthetic_reply_method_errno(m, r, NULL);
662 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
664 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
665 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
667 r = get_creds_by_message(a, m, SD_BUS_CREDS_UID, &creds, NULL);
669 return synthetic_reply_method_errno(m, r, NULL);
671 return synthetic_reply_method_return(m, "u", (uint32_t) creds->uid);
673 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
674 sd_id128_t server_id;
675 char buf[SD_ID128_STRING_MAX];
677 r = sd_bus_get_server_id(a, &server_id);
679 return synthetic_reply_method_errno(m, r, NULL);
681 return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
683 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
685 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
686 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
688 r = sd_bus_message_read(m, "s", &name);
690 return synthetic_reply_method_errno(m, r, NULL);
692 if (streq(name, "org.freedesktop.DBus"))
693 return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
695 r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
697 return synthetic_reply_method_errno(m, r, &error);
699 return synthetic_reply_method_return(m, "s", creds->unique_name);
701 /* "Hello" is handled in process_hello() */
703 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
704 _cleanup_strv_free_ char **names = NULL;
706 r = sd_bus_list_names(a, NULL, &names);
708 return synthetic_reply_method_errno(m, r, NULL);
710 /* Let's sort the names list to make it stable */
713 return synthetic_reply_return_strv(m, names);
715 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
716 _cleanup_strv_free_ char **names = NULL;
718 r = sd_bus_list_names(a, &names, NULL);
720 return synthetic_reply_method_errno(m, r, NULL);
722 r = strv_extend(&names, "org.freedesktop.DBus");
724 return synthetic_reply_method_errno(m, r, NULL);
726 /* Let's sort the names list to make it stable */
729 return synthetic_reply_return_strv(m, names);
731 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
732 struct kdbus_cmd_name_list cmd = {};
733 struct kdbus_name_list *name_list;
734 struct kdbus_cmd_name *name;
735 _cleanup_strv_free_ char **owners = NULL;
739 r = sd_bus_message_read(m, "s", &arg0);
741 return synthetic_reply_method_errno(m, r, NULL);
743 if (!service_name_is_valid(arg0))
744 return synthetic_reply_method_errno(m, -EINVAL, NULL);
746 cmd.flags = KDBUS_NAME_LIST_QUEUED;
747 r = ioctl(a->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
749 return synthetic_reply_method_errno(m, -errno, NULL);
751 name_list = (struct kdbus_name_list *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
753 KDBUS_ITEM_FOREACH(name, name_list, names) {
754 const char *entry_name = NULL;
755 struct kdbus_item *item;
758 KDBUS_ITEM_FOREACH(item, name, items)
759 if (item->type == KDBUS_ITEM_NAME)
760 entry_name = item->str;
762 if (!streq_ptr(entry_name, arg0))
765 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
770 r = strv_consume(&owners, n);
777 r = ioctl(a->input_fd, KDBUS_CMD_FREE, &cmd.offset);
779 return synthetic_reply_method_errno(m, r, NULL);
782 return synthetic_reply_method_errno(m, err, NULL);
784 return synthetic_reply_return_strv(m, owners);
786 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
789 r = sd_bus_message_read(m, "s", &name);
791 return synthetic_reply_method_errno(m, r, NULL);
793 if (!service_name_is_valid(name))
794 return synthetic_reply_method_errno(m, -EINVAL, NULL);
796 if (streq(name, "org.freedesktop.DBus"))
797 return synthetic_reply_method_return(m, "b", true);
799 r = sd_bus_get_owner(a, name, 0, NULL);
800 if (r < 0 && r != -ESRCH && r != -ENXIO)
801 return synthetic_reply_method_errno(m, r, NULL);
803 return synthetic_reply_method_return(m, "b", r >= 0);
805 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
808 r = sd_bus_message_read(m, "s", &name);
810 return synthetic_reply_method_errno(m, r, NULL);
812 if (!service_name_is_valid(name))
813 return synthetic_reply_method_errno(m, -EINVAL, NULL);
815 r = sd_bus_release_name(a, name);
818 return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
819 if (r == -EADDRINUSE)
820 return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
822 return synthetic_reply_method_errno(m, r, NULL);
825 return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
827 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
828 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
830 r = sd_bus_error_setf(&error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
832 return synthetic_reply_method_errno(m, r, &error);
834 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
838 r = sd_bus_message_read(m, "su", &name, &flags);
840 return synthetic_reply_method_errno(m, r, NULL);
842 if (!service_name_is_valid(name))
843 return synthetic_reply_method_errno(m, -EINVAL, NULL);
844 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
845 return synthetic_reply_method_errno(m, -EINVAL, NULL);
847 r = sd_bus_request_name(a, name, flags);
850 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
852 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
853 return synthetic_reply_method_errno(m, r, NULL);
857 return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
859 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
861 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
862 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
866 r = sd_bus_message_read(m, "su", &name, &flags);
868 return synthetic_reply_method_errno(m, r, NULL);
870 if (!service_name_is_valid(name))
871 return synthetic_reply_method_errno(m, -EINVAL, NULL);
873 return synthetic_reply_method_errno(m, -EINVAL, NULL);
875 r = sd_bus_get_owner(a, name, 0, NULL);
876 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
877 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
879 return synthetic_reply_method_errno(m, r, NULL);
881 r = sd_bus_message_new_method_call(
886 "org.freedesktop.DBus.Peer",
889 return synthetic_reply_method_errno(m, r, NULL);
891 r = sd_bus_send(a, msg, NULL);
893 return synthetic_reply_method_errno(m, r, NULL);
895 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
897 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
898 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
899 _cleanup_strv_free_ char **args = NULL;
901 if (!peer_is_privileged(a, m))
902 return synthetic_reply_method_errno(m, -EPERM, NULL);
904 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
906 return synthetic_reply_method_errno(m, r, NULL);
908 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
909 _cleanup_free_ char *s = NULL;
913 r = sd_bus_message_read(m, "ss", &key, &value);
915 return synthetic_reply_method_errno(m, r, NULL);
917 s = strjoin(key, "=", value, NULL);
919 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
921 r = strv_extend(&args, s);
923 return synthetic_reply_method_errno(m, r, NULL);
925 r = sd_bus_message_exit_container(m);
927 return synthetic_reply_method_errno(m, r, NULL);
930 r = sd_bus_message_exit_container(m);
932 return synthetic_reply_method_errno(m, r, NULL);
935 return synthetic_reply_method_errno(m, -EINVAL, NULL);
937 r = sd_bus_message_new_method_call(
940 "org.freedesktop.systemd1",
941 "/org/freedesktop/systemd1",
942 "org.freedesktop.systemd1.Manager",
945 return synthetic_reply_method_errno(m, r, NULL);
947 r = sd_bus_message_append_strv(msg, args);
949 return synthetic_reply_method_errno(m, r, NULL);
951 r = sd_bus_call(a, msg, 0, NULL, NULL);
953 return synthetic_reply_method_errno(m, r, NULL);
955 return synthetic_reply_method_return(m, NULL);
958 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
960 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
962 return synthetic_reply_method_errno(m, r, &error);
966 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
967 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
976 /* As reaction to hello we need to respond with two messages:
977 * the callback reply and the NameAcquired for the unique
978 * name, since hello is otherwise obsolete on kdbus. */
981 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
982 streq_ptr(m->destination, "org.freedesktop.DBus");
989 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
994 log_error("Got duplicate hello, aborting.");
1003 r = sd_bus_message_new_method_return(m, &n);
1005 log_error("Failed to generate HELLO reply: %s", strerror(-r));
1009 r = sd_bus_message_append(n, "s", a->unique_name);
1011 log_error("Failed to append unique name to HELLO reply: %s", strerror(-r));
1015 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1017 log_error("Failed to append sender to HELLO reply: %s", strerror(-r));
1021 r = bus_seal_synthetic_message(b, n);
1023 log_error("Failed to seal HELLO reply: %s", strerror(-r));
1027 r = sd_bus_send(b, n, NULL);
1029 log_error("Failed to send HELLO reply: %s", strerror(-r));
1033 n = sd_bus_message_unref(n);
1034 r = sd_bus_message_new_signal(
1037 "/org/freedesktop/DBus",
1038 "org.freedesktop.DBus",
1041 log_error("Failed to allocate initial NameAcquired message: %s", strerror(-r));
1045 r = sd_bus_message_append(n, "s", a->unique_name);
1047 log_error("Failed to append unique name to NameAcquired message: %s", strerror(-r));
1051 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1053 log_error("Failed to append sender to NameAcquired message: %s", strerror(-r));
1057 r = bus_seal_synthetic_message(b, n);
1059 log_error("Failed to seal NameAcquired message: %s", strerror(-r));
1063 r = sd_bus_send(b, n, NULL);
1065 log_error("Failed to send NameAcquired message: %s", strerror(-r));
1072 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1073 char **well_known = NULL;
1083 /* We will change the sender of messages from the bus driver
1084 * so that they originate from the bus driver. This is a
1085 * speciality originating from dbus1, where the bus driver did
1086 * not have a unique id, but only the well-known name. */
1088 c = sd_bus_message_get_creds(m);
1092 r = sd_bus_creds_get_well_known_names(c, &well_known);
1096 if (strv_contains(well_known, "org.freedesktop.DBus"))
1097 m->sender = "org.freedesktop.DBus";
1102 int main(int argc, char *argv[]) {
1104 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1105 sd_id128_t server_id;
1106 int r, in_fd, out_fd;
1107 bool got_hello = false;
1109 struct ucred ucred = {};
1110 _cleanup_free_ char *peersec = NULL;
1113 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1114 log_parse_environment();
1117 r = parse_argv(argc, argv);
1121 r = policy_load(&policy, arg_configuration);
1123 log_error("Failed to load policy: %s", strerror(-r));
1127 /* policy_dump(&policy); */
1129 r = sd_listen_fds(0);
1131 in_fd = STDIN_FILENO;
1132 out_fd = STDOUT_FILENO;
1133 } else if (r == 1) {
1134 in_fd = SD_LISTEN_FDS_START;
1135 out_fd = SD_LISTEN_FDS_START;
1137 log_error("Illegal number of file descriptors passed");
1142 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1143 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1146 getpeercred(in_fd, &ucred);
1147 getpeersec(in_fd, &peersec);
1150 if (arg_drop_privileges) {
1151 const char *user = "systemd-bus-proxy";
1155 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1157 log_error("Cannot resolve user name %s: %s", user, strerror(-r));
1161 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1168 log_error("Failed to allocate bus: %s", strerror(-r));
1172 r = sd_bus_set_name(a, "sd-proxy");
1174 log_error("Failed to set bus name: %s", strerror(-r));
1178 r = sd_bus_set_address(a, arg_address);
1180 log_error("Failed to set address to connect to: %s", strerror(-r));
1184 r = sd_bus_negotiate_fds(a, is_unix);
1186 log_error("Failed to set FD negotiation: %s", strerror(-r));
1190 if (ucred.pid > 0) {
1191 a->fake_creds.pid = ucred.pid;
1192 a->fake_creds.uid = ucred.uid;
1193 a->fake_creds.gid = ucred.gid;
1194 a->fake_creds_valid = true;
1198 a->fake_label = peersec;
1202 a->manual_peer_interface = true;
1204 r = sd_bus_start(a);
1206 log_error("Failed to start bus client: %s", strerror(-r));
1210 r = sd_bus_get_server_id(a, &server_id);
1212 log_error("Failed to get server ID: %s", strerror(-r));
1218 log_error("Failed to allocate bus: %s", strerror(-r));
1222 r = sd_bus_set_fd(b, in_fd, out_fd);
1224 log_error("Failed to set fds: %s", strerror(-r));
1228 r = sd_bus_set_server(b, 1, server_id);
1230 log_error("Failed to set server mode: %s", strerror(-r));
1234 r = sd_bus_negotiate_fds(b, is_unix);
1236 log_error("Failed to set FD negotiation: %s", strerror(-r));
1240 r = sd_bus_set_anonymous(b, true);
1242 log_error("Failed to set anonymous authentication: %s", strerror(-r));
1246 b->manual_peer_interface = true;
1248 r = sd_bus_start(b);
1250 log_error("Failed to start bus client: %s", strerror(-r));
1254 r = rename_service(a, b);
1256 log_debug("Failed to rename process: %s", strerror(-r));
1259 _cleanup_free_ char *match = NULL;
1262 r = sd_bus_get_unique_name(a, &unique);
1264 log_error("Failed to get unique name: %s", strerror(-r));
1268 match = strjoin("type='signal',"
1269 "sender='org.freedesktop.DBus',"
1270 "path='/org/freedesktop/DBus',"
1271 "interface='org.freedesktop.DBus',"
1272 "member='NameOwnerChanged',"
1282 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1284 log_error("Failed to add match for NameLost: %s", strerror(-r));
1289 match = strjoin("type='signal',"
1290 "sender='org.freedesktop.DBus',"
1291 "path='/org/freedesktop/DBus',"
1292 "interface='org.freedesktop.DBus',"
1293 "member='NameOwnerChanged',"
1303 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1305 log_error("Failed to add match for NameAcquired: %s", strerror(-r));
1311 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1312 int events_a, events_b, fd;
1313 uint64_t timeout_a, timeout_b, t;
1314 struct timespec _ts, *ts;
1315 struct pollfd *pollfd;
1319 r = sd_bus_process(a, &m);
1321 /* treat 'connection reset by peer' as clean exit condition */
1322 if (r == -ECONNRESET)
1325 log_error("Failed to process bus a: %s", strerror(-r));
1331 /* We officially got EOF, let's quit */
1332 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1337 k = synthesize_name_acquired(a, b, m);
1340 log_error("Failed to synthesize message: %s", strerror(-r));
1346 k = sd_bus_send(b, m, NULL);
1348 if (k == -ECONNRESET)
1352 log_error("Failed to send message: %s", strerror(-r));
1363 r = sd_bus_process(b, &m);
1365 /* treat 'connection reset by peer' as clean exit condition */
1366 if (r == -ECONNRESET)
1369 log_error("Failed to process bus b: %s", strerror(-r));
1375 /* We officially got EOF, let's quit */
1376 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1381 k = process_hello(a, b, m, &got_hello);
1384 log_error("Failed to process HELLO: %s", strerror(-r));
1391 k = process_policy(a, b, m);
1394 log_error("Failed to process policy: %s", strerror(-r));
1398 k = process_driver(a, b, m);
1401 log_error("Failed to process driver calls: %s", strerror(-r));
1408 k = sd_bus_send(a, m, NULL);
1410 if (k == -ECONNRESET)
1414 log_error("Failed to send message: %s", strerror(-r));
1426 fd = sd_bus_get_fd(a);
1428 log_error("Failed to get fd: %s", strerror(-r));
1432 events_a = sd_bus_get_events(a);
1434 log_error("Failed to get events mask: %s", strerror(-r));
1438 r = sd_bus_get_timeout(a, &timeout_a);
1440 log_error("Failed to get timeout: %s", strerror(-r));
1444 events_b = sd_bus_get_events(b);
1446 log_error("Failed to get events mask: %s", strerror(-r));
1450 r = sd_bus_get_timeout(b, &timeout_b);
1452 log_error("Failed to get timeout: %s", strerror(-r));
1457 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1460 if (t == (uint64_t) -1)
1465 nw = now(CLOCK_MONOTONIC);
1471 ts = timespec_store(&_ts, t);
1474 pollfd = (struct pollfd[3]) {
1475 {.fd = fd, .events = events_a, },
1476 {.fd = in_fd, .events = events_b & POLLIN, },
1477 {.fd = out_fd, .events = events_b & POLLOUT, }
1480 r = ppoll(pollfd, 3, ts, NULL);
1482 log_error("ppoll() failed: %m");
1490 "STATUS=Shutting down.");
1492 policy_free(&policy);
1493 strv_free(arg_configuration);
1496 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;