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;
376 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
379 r = sd_bus_message_new_method_error(call, &m, e);
383 return synthetic_driver_send(call->bus, m);
386 static int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) {
388 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
390 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
393 if (sd_bus_error_is_set(p))
394 return synthetic_reply_method_error(call, p);
396 sd_bus_error_set_errno(&berror, error);
398 return synthetic_reply_method_error(call, &berror);
401 static int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) {
402 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
405 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
408 r = sd_bus_message_new_method_return(call, &m);
412 if (!isempty(types)) {
416 r = bus_message_append_ap(m, types, ap);
422 return synthetic_driver_send(call->bus, m);
425 static int synthetic_reply_return_strv(sd_bus_message *call, char **l) {
426 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
429 r = sd_bus_message_new_method_return(call, &m);
431 return synthetic_reply_method_errno(call, r, NULL);
433 r = sd_bus_message_append_strv(m, l);
435 return synthetic_reply_method_errno(call, r, NULL);
437 return synthetic_driver_send(call->bus, m);
440 static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
441 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
448 assert_return(service_name_is_valid(name), -EINVAL);
450 r = sd_bus_get_owner(bus, name, mask, &c);
451 if (r == -ESRCH || r == -ENXIO)
452 return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
456 if ((c->mask & mask) != mask)
465 static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
473 r = sd_bus_message_read(m, "s", &name);
477 return get_creds_by_name(bus, name, mask, _creds, error);
480 static int peer_is_privileged(sd_bus *bus, sd_bus_message *m) {
481 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
485 r = get_creds_by_message(bus, m, SD_BUS_CREDS_UID, &creds, NULL);
489 r = sd_bus_creds_get_uid(creds, &uid);
493 r = sd_bus_creds_has_effective_cap(creds, CAP_SYS_ADMIN);
503 static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) {
513 if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
516 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
517 if (0 && !isempty(sd_bus_message_get_signature(m, true))) {
518 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
520 r = sd_bus_error_setf(&error, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters");
522 return synthetic_reply_method_errno(m, r, &error);
525 return synthetic_reply_method_return(m, "s",
526 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
527 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
529 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
530 " <method name=\"Introspect\">\n"
531 " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
534 " <interface name=\"org.freedesktop.DBus\">\n"
535 " <method name=\"AddMatch\">\n"
536 " <arg type=\"s\" direction=\"in\"/>\n"
538 " <method name=\"RemoveMatch\">\n"
539 " <arg type=\"s\" direction=\"in\"/>\n"
541 " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
542 " <arg type=\"s\" direction=\"in\"/>\n"
543 " <arg type=\"ay\" direction=\"out\"/>\n"
545 " <method name=\"GetConnectionUnixProcessID\">\n"
546 " <arg type=\"s\" direction=\"in\"/>\n"
547 " <arg type=\"u\" direction=\"out\"/>\n"
549 " <method name=\"GetConnectionUnixUser\">\n"
550 " <arg type=\"s\" direction=\"in\"/>\n"
551 " <arg type=\"u\" direction=\"out\"/>\n"
553 " <method name=\"GetId\">\n"
554 " <arg type=\"s\" direction=\"out\"/>\n"
556 " <method name=\"GetNameOwner\">\n"
557 " <arg type=\"s\" direction=\"in\"/>\n"
558 " <arg type=\"s\" direction=\"out\"/>\n"
560 " <method name=\"Hello\">\n"
561 " <arg type=\"s\" direction=\"out\"/>\n"
563 " <method name=\"ListActivatableNames\">\n"
564 " <arg type=\"as\" direction=\"out\"/>\n"
566 " <method name=\"ListNames\">\n"
567 " <arg type=\"as\" direction=\"out\"/>\n"
569 " <method name=\"ListQueuedOwners\">\n"
570 " <arg type=\"s\" direction=\"in\"/>\n"
571 " <arg type=\"as\" direction=\"out\"/>\n"
573 " <method name=\"NameHasOwner\">\n"
574 " <arg type=\"s\" direction=\"in\"/>\n"
575 " <arg type=\"b\" direction=\"out\"/>\n"
577 " <method name=\"ReleaseName\">\n"
578 " <arg type=\"s\" direction=\"in\"/>\n"
579 " <arg type=\"u\" direction=\"out\"/>\n"
581 " <method name=\"ReloadConfig\">\n"
583 " <method name=\"RequestName\">\n"
584 " <arg type=\"s\" direction=\"in\"/>\n"
585 " <arg type=\"u\" direction=\"in\"/>\n"
586 " <arg type=\"u\" direction=\"out\"/>\n"
588 " <method name=\"StartServiceByName\">\n"
589 " <arg type=\"s\" direction=\"in\"/>\n"
590 " <arg type=\"u\" direction=\"in\"/>\n"
591 " <arg type=\"u\" direction=\"out\"/>\n"
593 " <method name=\"UpdateActivationEnvironment\">\n"
594 " <arg type=\"a{ss}\" direction=\"in\"/>\n"
596 " <signal name=\"NameAcquired\">\n"
597 " <arg type=\"s\"/>\n"
599 " <signal name=\"NameLost\">\n"
600 " <arg type=\"s\"/>\n"
602 " <signal name=\"NameOwnerChanged\">\n"
603 " <arg type=\"s\"/>\n"
604 " <arg type=\"s\"/>\n"
605 " <arg type=\"s\"/>\n"
610 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
613 r = sd_bus_message_read(m, "s", &match);
615 return synthetic_reply_method_errno(m, r, NULL);
617 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
619 return synthetic_reply_method_errno(m, r, NULL);
621 return synthetic_reply_method_return(m, NULL);
623 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
626 r = sd_bus_message_read(m, "s", &match);
628 return synthetic_reply_method_errno(m, r, NULL);
630 r = bus_remove_match_by_string(a, match, NULL, NULL);
632 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
634 return synthetic_reply_method_errno(m, r, NULL);
636 return synthetic_reply_method_return(m, NULL);
638 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
639 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
641 r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, NULL);
643 return synthetic_reply_method_errno(m, r, NULL);
645 return synthetic_reply_method_return(m, "y", creds->label, strlen(creds->label));
647 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
648 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
650 r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, NULL);
652 return synthetic_reply_method_errno(m, r, NULL);
654 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
656 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
657 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
659 r = get_creds_by_message(a, m, SD_BUS_CREDS_UID, &creds, NULL);
661 return synthetic_reply_method_errno(m, r, NULL);
663 return synthetic_reply_method_return(m, "u", (uint32_t) creds->uid);
665 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
666 sd_id128_t server_id;
667 char buf[SD_ID128_STRING_MAX];
669 r = sd_bus_get_server_id(a, &server_id);
671 return synthetic_reply_method_errno(m, r, NULL);
673 return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
675 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
677 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
678 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
680 r = sd_bus_message_read(m, "s", &name);
682 return synthetic_reply_method_errno(m, r, NULL);
684 if (streq(name, "org.freedesktop.DBus"))
685 return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
687 r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
689 return synthetic_reply_method_errno(m, r, &error);
691 return synthetic_reply_method_return(m, "s", creds->unique_name);
693 /* "Hello" is handled in process_hello() */
695 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
696 _cleanup_strv_free_ char **names = NULL;
698 r = sd_bus_list_names(a, NULL, &names);
700 return synthetic_reply_method_errno(m, r, NULL);
702 /* Let's sort the names list to make it stable */
705 return synthetic_reply_return_strv(m, names);
707 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
708 _cleanup_strv_free_ char **names = NULL;
710 r = sd_bus_list_names(a, &names, NULL);
712 return synthetic_reply_method_errno(m, r, NULL);
714 r = strv_extend(&names, "org.freedesktop.DBus");
716 return synthetic_reply_method_errno(m, r, NULL);
718 /* Let's sort the names list to make it stable */
721 return synthetic_reply_return_strv(m, names);
723 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
724 struct kdbus_cmd_name_list cmd = {};
725 struct kdbus_name_list *name_list;
726 struct kdbus_cmd_name *name;
727 _cleanup_strv_free_ char **owners = NULL;
731 r = sd_bus_message_read(m, "s", &arg0);
733 return synthetic_reply_method_errno(m, r, NULL);
735 if (!service_name_is_valid(arg0))
736 return synthetic_reply_method_errno(m, -EINVAL, NULL);
738 cmd.flags = KDBUS_NAME_LIST_QUEUED;
739 r = ioctl(a->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
741 return synthetic_reply_method_errno(m, -errno, NULL);
743 name_list = (struct kdbus_name_list *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
745 KDBUS_ITEM_FOREACH(name, name_list, names) {
746 const char *entry_name = NULL;
747 struct kdbus_item *item;
750 KDBUS_ITEM_FOREACH(item, name, items)
751 if (item->type == KDBUS_ITEM_NAME)
752 entry_name = item->str;
754 if (!streq_ptr(entry_name, arg0))
757 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
762 r = strv_consume(&owners, n);
769 r = ioctl(a->input_fd, KDBUS_CMD_FREE, &cmd.offset);
771 return synthetic_reply_method_errno(m, r, NULL);
774 return synthetic_reply_method_errno(m, err, NULL);
776 return synthetic_reply_return_strv(m, owners);
778 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
781 r = sd_bus_message_read(m, "s", &name);
783 return synthetic_reply_method_errno(m, r, NULL);
785 if (!service_name_is_valid(name))
786 return synthetic_reply_method_errno(m, -EINVAL, NULL);
788 if (streq(name, "org.freedesktop.DBus"))
789 return synthetic_reply_method_return(m, "b", true);
791 r = sd_bus_get_owner(a, name, 0, NULL);
792 if (r < 0 && r != -ESRCH && r != -ENXIO)
793 return synthetic_reply_method_errno(m, r, NULL);
795 return synthetic_reply_method_return(m, "b", r >= 0);
797 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
800 r = sd_bus_message_read(m, "s", &name);
802 return synthetic_reply_method_errno(m, r, NULL);
804 if (!service_name_is_valid(name))
805 return synthetic_reply_method_errno(m, -EINVAL, NULL);
807 r = sd_bus_release_name(a, name);
810 return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
811 if (r == -EADDRINUSE)
812 return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
814 return synthetic_reply_method_errno(m, r, NULL);
817 return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
819 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
820 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
822 r = sd_bus_error_setf(&error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
824 return synthetic_reply_method_errno(m, r, &error);
826 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
830 r = sd_bus_message_read(m, "su", &name, &flags);
832 return synthetic_reply_method_errno(m, r, NULL);
834 if (!service_name_is_valid(name))
835 return synthetic_reply_method_errno(m, -EINVAL, NULL);
836 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
837 return synthetic_reply_method_errno(m, -EINVAL, NULL);
839 r = sd_bus_request_name(a, name, flags);
842 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
844 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
845 return synthetic_reply_method_errno(m, r, NULL);
849 return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
851 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
853 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
854 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
858 r = sd_bus_message_read(m, "su", &name, &flags);
860 return synthetic_reply_method_errno(m, r, NULL);
862 if (!service_name_is_valid(name))
863 return synthetic_reply_method_errno(m, -EINVAL, NULL);
865 return synthetic_reply_method_errno(m, -EINVAL, NULL);
867 r = sd_bus_get_owner(a, name, 0, NULL);
868 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
869 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
871 return synthetic_reply_method_errno(m, r, NULL);
873 r = sd_bus_message_new_method_call(
878 "org.freedesktop.DBus.Peer",
881 return synthetic_reply_method_errno(m, r, NULL);
883 r = sd_bus_send(a, msg, NULL);
885 return synthetic_reply_method_errno(m, r, NULL);
887 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
889 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
890 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
891 _cleanup_strv_free_ char **args = NULL;
893 if (!peer_is_privileged(a, m))
894 return synthetic_reply_method_errno(m, -EPERM, NULL);
896 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
898 return synthetic_reply_method_errno(m, r, NULL);
900 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
901 _cleanup_free_ char *s = NULL;
905 r = sd_bus_message_read(m, "ss", &key, &value);
907 return synthetic_reply_method_errno(m, r, NULL);
909 s = strjoin(key, "=", value, NULL);
911 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
913 r = strv_extend(&args, s);
915 return synthetic_reply_method_errno(m, r, NULL);
917 r = sd_bus_message_exit_container(m);
919 return synthetic_reply_method_errno(m, r, NULL);
922 r = sd_bus_message_exit_container(m);
924 return synthetic_reply_method_errno(m, r, NULL);
927 return synthetic_reply_method_errno(m, -EINVAL, NULL);
929 r = sd_bus_message_new_method_call(
932 "org.freedesktop.systemd1",
933 "/org/freedesktop/systemd1",
934 "org.freedesktop.systemd1.Manager",
937 return synthetic_reply_method_errno(m, r, NULL);
939 r = sd_bus_message_append_strv(msg, args);
941 return synthetic_reply_method_errno(m, r, NULL);
943 r = sd_bus_call(a, msg, 0, NULL, NULL);
945 return synthetic_reply_method_errno(m, r, NULL);
947 return synthetic_reply_method_return(m, NULL);
950 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
952 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
954 return synthetic_reply_method_errno(m, r, &error);
958 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
959 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
968 /* As reaction to hello we need to respond with two messages:
969 * the callback reply and the NameAcquired for the unique
970 * name, since hello is otherwise obsolete on kdbus. */
973 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
974 streq_ptr(m->destination, "org.freedesktop.DBus");
981 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
986 log_error("Got duplicate hello, aborting.");
995 r = sd_bus_message_new_method_return(m, &n);
997 log_error("Failed to generate HELLO reply: %s", strerror(-r));
1001 r = sd_bus_message_append(n, "s", a->unique_name);
1003 log_error("Failed to append unique name to HELLO reply: %s", strerror(-r));
1007 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1009 log_error("Failed to append sender to HELLO reply: %s", strerror(-r));
1013 r = bus_seal_synthetic_message(b, n);
1015 log_error("Failed to seal HELLO reply: %s", strerror(-r));
1019 r = sd_bus_send(b, n, NULL);
1021 log_error("Failed to send HELLO reply: %s", strerror(-r));
1025 n = sd_bus_message_unref(n);
1026 r = sd_bus_message_new_signal(
1029 "/org/freedesktop/DBus",
1030 "org.freedesktop.DBus",
1033 log_error("Failed to allocate initial NameAcquired message: %s", strerror(-r));
1037 r = sd_bus_message_append(n, "s", a->unique_name);
1039 log_error("Failed to append unique name to NameAcquired message: %s", strerror(-r));
1043 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1045 log_error("Failed to append sender to NameAcquired message: %s", strerror(-r));
1049 r = bus_seal_synthetic_message(b, n);
1051 log_error("Failed to seal NameAcquired message: %s", strerror(-r));
1055 r = sd_bus_send(b, n, NULL);
1057 log_error("Failed to send NameAcquired message: %s", strerror(-r));
1064 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1065 char **well_known = NULL;
1075 /* We will change the sender of messages from the bus driver
1076 * so that they originate from the bus driver. This is a
1077 * speciality originating from dbus1, where the bus driver did
1078 * not have a unique id, but only the well-known name. */
1080 c = sd_bus_message_get_creds(m);
1084 r = sd_bus_creds_get_well_known_names(c, &well_known);
1088 if (strv_contains(well_known, "org.freedesktop.DBus"))
1089 m->sender = "org.freedesktop.DBus";
1094 int main(int argc, char *argv[]) {
1096 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1097 sd_id128_t server_id;
1098 int r, in_fd, out_fd;
1099 bool got_hello = false;
1101 struct ucred ucred = {};
1102 _cleanup_free_ char *peersec = NULL;
1105 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1106 log_parse_environment();
1109 r = parse_argv(argc, argv);
1113 r = policy_load(&policy, arg_configuration);
1115 log_error("Failed to load policy: %s", strerror(-r));
1119 /* policy_dump(&policy); */
1121 r = sd_listen_fds(0);
1123 in_fd = STDIN_FILENO;
1124 out_fd = STDOUT_FILENO;
1125 } else if (r == 1) {
1126 in_fd = SD_LISTEN_FDS_START;
1127 out_fd = SD_LISTEN_FDS_START;
1129 log_error("Illegal number of file descriptors passed");
1134 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1135 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1138 getpeercred(in_fd, &ucred);
1139 getpeersec(in_fd, &peersec);
1142 if (arg_drop_privileges) {
1143 const char *user = "systemd-bus-proxy";
1147 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1149 log_error("Cannot resolve user name %s: %s", user, strerror(-r));
1153 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1160 log_error("Failed to allocate bus: %s", strerror(-r));
1164 r = sd_bus_set_name(a, "sd-proxy");
1166 log_error("Failed to set bus name: %s", strerror(-r));
1170 r = sd_bus_set_address(a, arg_address);
1172 log_error("Failed to set address to connect to: %s", strerror(-r));
1176 r = sd_bus_negotiate_fds(a, is_unix);
1178 log_error("Failed to set FD negotiation: %s", strerror(-r));
1182 if (ucred.pid > 0) {
1183 a->fake_creds.pid = ucred.pid;
1184 a->fake_creds.uid = ucred.uid;
1185 a->fake_creds.gid = ucred.gid;
1186 a->fake_creds_valid = true;
1190 a->fake_label = peersec;
1194 a->manual_peer_interface = true;
1196 r = sd_bus_start(a);
1198 log_error("Failed to start bus client: %s", strerror(-r));
1202 r = sd_bus_get_server_id(a, &server_id);
1204 log_error("Failed to get server ID: %s", strerror(-r));
1210 log_error("Failed to allocate bus: %s", strerror(-r));
1214 r = sd_bus_set_fd(b, in_fd, out_fd);
1216 log_error("Failed to set fds: %s", strerror(-r));
1220 r = sd_bus_set_server(b, 1, server_id);
1222 log_error("Failed to set server mode: %s", strerror(-r));
1226 r = sd_bus_negotiate_fds(b, is_unix);
1228 log_error("Failed to set FD negotiation: %s", strerror(-r));
1232 r = sd_bus_set_anonymous(b, true);
1234 log_error("Failed to set anonymous authentication: %s", strerror(-r));
1238 b->manual_peer_interface = true;
1240 r = sd_bus_start(b);
1242 log_error("Failed to start bus client: %s", strerror(-r));
1246 r = rename_service(a, b);
1248 log_debug("Failed to rename process: %s", strerror(-r));
1251 _cleanup_free_ char *match = NULL;
1254 r = sd_bus_get_unique_name(a, &unique);
1256 log_error("Failed to get unique name: %s", strerror(-r));
1260 match = strjoin("type='signal',"
1261 "sender='org.freedesktop.DBus',"
1262 "path='/org/freedesktop/DBus',"
1263 "interface='org.freedesktop.DBus',"
1264 "member='NameOwnerChanged',"
1274 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1276 log_error("Failed to add match for NameLost: %s", strerror(-r));
1281 match = strjoin("type='signal',"
1282 "sender='org.freedesktop.DBus',"
1283 "path='/org/freedesktop/DBus',"
1284 "interface='org.freedesktop.DBus',"
1285 "member='NameOwnerChanged',"
1295 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1297 log_error("Failed to add match for NameAcquired: %s", strerror(-r));
1303 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1304 int events_a, events_b, fd;
1305 uint64_t timeout_a, timeout_b, t;
1306 struct timespec _ts, *ts;
1307 struct pollfd *pollfd;
1311 r = sd_bus_process(a, &m);
1313 /* treat 'connection reset by peer' as clean exit condition */
1314 if (r == -ECONNRESET)
1317 log_error("Failed to process bus a: %s", strerror(-r));
1323 /* We officially got EOF, let's quit */
1324 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1329 k = synthesize_name_acquired(a, b, m);
1332 log_error("Failed to synthesize message: %s", strerror(-r));
1338 k = sd_bus_send(b, m, NULL);
1340 if (k == -ECONNRESET)
1344 log_error("Failed to send message: %s", strerror(-r));
1355 r = sd_bus_process(b, &m);
1357 /* treat 'connection reset by peer' as clean exit condition */
1358 if (r == -ECONNRESET)
1361 log_error("Failed to process bus b: %s", strerror(-r));
1367 /* We officially got EOF, let's quit */
1368 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1373 k = process_hello(a, b, m, &got_hello);
1376 log_error("Failed to process HELLO: %s", strerror(-r));
1383 k = process_policy(a, b, m);
1386 log_error("Failed to process policy: %s", strerror(-r));
1390 k = process_driver(a, b, m);
1393 log_error("Failed to process driver calls: %s", strerror(-r));
1400 k = sd_bus_send(a, m, NULL);
1402 if (k == -ECONNRESET)
1406 log_error("Failed to send message: %s", strerror(-r));
1418 fd = sd_bus_get_fd(a);
1420 log_error("Failed to get fd: %s", strerror(-r));
1424 events_a = sd_bus_get_events(a);
1426 log_error("Failed to get events mask: %s", strerror(-r));
1430 r = sd_bus_get_timeout(a, &timeout_a);
1432 log_error("Failed to get timeout: %s", strerror(-r));
1436 events_b = sd_bus_get_events(b);
1438 log_error("Failed to get events mask: %s", strerror(-r));
1442 r = sd_bus_get_timeout(b, &timeout_b);
1444 log_error("Failed to get timeout: %s", strerror(-r));
1449 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1452 if (t == (uint64_t) -1)
1457 nw = now(CLOCK_MONOTONIC);
1463 ts = timespec_store(&_ts, t);
1466 pollfd = (struct pollfd[3]) {
1467 {.fd = fd, .events = events_a, },
1468 {.fd = in_fd, .events = events_b & POLLIN, },
1469 {.fd = out_fd, .events = events_b & POLLOUT, }
1472 r = ppoll(pollfd, 3, ts, NULL);
1474 log_error("ppoll() failed: %m");
1482 "STATUS=Shutting down.");
1484 policy_free(&policy);
1485 strv_free(arg_configuration);
1488 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;