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 process_policy(sd_bus *a, sd_bus *b, sd_bus_message *m) {
313 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
323 if (!sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "GetAll"))
326 if (!streq_ptr(m->path, "/org/gnome/DisplayManager/Slave"))
329 r = sd_bus_message_new_method_errorf(m, &n, SD_BUS_ERROR_ACCESS_DENIED, "gdm, you are stupid");
333 r = bus_message_append_sender(n, "org.freedesktop.DBus");
335 log_error("Failed to append sender to gdm reply: %s", strerror(-r));
339 r = bus_seal_synthetic_message(b, n);
341 log_error("Failed to seal gdm reply: %s", strerror(-r));
345 r = sd_bus_send(b, n, NULL);
347 log_error("Failed to send gdm reply: %s", strerror(-r));
354 static int synthetic_driver_send(sd_bus *b, sd_bus_message *m) {
360 r = bus_message_append_sender(m, "org.freedesktop.DBus");
364 r = bus_seal_synthetic_message(b, m);
368 return sd_bus_send(b, m, NULL);
371 static int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) {
372 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
377 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
380 r = sd_bus_message_new_method_error(call, &m, e);
384 return synthetic_driver_send(call->bus, m);
387 static int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) {
389 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
393 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
396 if (sd_bus_error_is_set(p))
397 return synthetic_reply_method_error(call, p);
399 sd_bus_error_set_errno(&berror, error);
401 return synthetic_reply_method_error(call, &berror);
404 static int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) {
405 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
410 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
413 r = sd_bus_message_new_method_return(call, &m);
417 if (!isempty(types)) {
421 r = bus_message_append_ap(m, types, ap);
427 return synthetic_driver_send(call->bus, m);
430 static int synthetic_reply_return_strv(sd_bus_message *call, char **l) {
431 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
436 r = sd_bus_message_new_method_return(call, &m);
438 return synthetic_reply_method_errno(call, r, NULL);
440 r = sd_bus_message_append_strv(m, l);
442 return synthetic_reply_method_errno(call, r, NULL);
444 return synthetic_driver_send(call->bus, m);
447 static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
448 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
455 assert_return(service_name_is_valid(name), -EINVAL);
457 r = sd_bus_get_name_creds(bus, name, mask, &c);
458 if (r == -ESRCH || r == -ENXIO)
459 return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
463 if ((c->mask & mask) != mask)
472 static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
480 r = sd_bus_message_read(m, "s", &name);
484 return get_creds_by_name(bus, name, mask, _creds, error);
487 static int peer_is_privileged(sd_bus *bus, sd_bus_message *m) {
488 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
492 r = get_creds_by_message(bus, m, SD_BUS_CREDS_UID, &creds, NULL);
496 r = sd_bus_creds_get_uid(creds, &uid);
500 r = sd_bus_creds_has_effective_cap(creds, CAP_SYS_ADMIN);
510 static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) {
520 if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
523 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
524 if (0 && !isempty(sd_bus_message_get_signature(m, true))) {
525 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
527 r = sd_bus_error_setf(&error, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters");
529 return synthetic_reply_method_errno(m, r, &error);
532 return synthetic_reply_method_return(m, "s",
533 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
534 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
536 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
537 " <method name=\"Introspect\">\n"
538 " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
541 " <interface name=\"org.freedesktop.DBus\">\n"
542 " <method name=\"AddMatch\">\n"
543 " <arg type=\"s\" direction=\"in\"/>\n"
545 " <method name=\"RemoveMatch\">\n"
546 " <arg type=\"s\" direction=\"in\"/>\n"
548 " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
549 " <arg type=\"s\" direction=\"in\"/>\n"
550 " <arg type=\"ay\" direction=\"out\"/>\n"
552 " <method name=\"GetConnectionUnixProcessID\">\n"
553 " <arg type=\"s\" direction=\"in\"/>\n"
554 " <arg type=\"u\" direction=\"out\"/>\n"
556 " <method name=\"GetConnectionUnixUser\">\n"
557 " <arg type=\"s\" direction=\"in\"/>\n"
558 " <arg type=\"u\" direction=\"out\"/>\n"
560 " <method name=\"GetId\">\n"
561 " <arg type=\"s\" direction=\"out\"/>\n"
563 " <method name=\"GetNameOwner\">\n"
564 " <arg type=\"s\" direction=\"in\"/>\n"
565 " <arg type=\"s\" direction=\"out\"/>\n"
567 " <method name=\"Hello\">\n"
568 " <arg type=\"s\" direction=\"out\"/>\n"
570 " <method name=\"ListActivatableNames\">\n"
571 " <arg type=\"as\" direction=\"out\"/>\n"
573 " <method name=\"ListNames\">\n"
574 " <arg type=\"as\" direction=\"out\"/>\n"
576 " <method name=\"ListQueuedOwners\">\n"
577 " <arg type=\"s\" direction=\"in\"/>\n"
578 " <arg type=\"as\" direction=\"out\"/>\n"
580 " <method name=\"NameHasOwner\">\n"
581 " <arg type=\"s\" direction=\"in\"/>\n"
582 " <arg type=\"b\" direction=\"out\"/>\n"
584 " <method name=\"ReleaseName\">\n"
585 " <arg type=\"s\" direction=\"in\"/>\n"
586 " <arg type=\"u\" direction=\"out\"/>\n"
588 " <method name=\"ReloadConfig\">\n"
590 " <method name=\"RequestName\">\n"
591 " <arg type=\"s\" direction=\"in\"/>\n"
592 " <arg type=\"u\" direction=\"in\"/>\n"
593 " <arg type=\"u\" direction=\"out\"/>\n"
595 " <method name=\"StartServiceByName\">\n"
596 " <arg type=\"s\" direction=\"in\"/>\n"
597 " <arg type=\"u\" direction=\"in\"/>\n"
598 " <arg type=\"u\" direction=\"out\"/>\n"
600 " <method name=\"UpdateActivationEnvironment\">\n"
601 " <arg type=\"a{ss}\" direction=\"in\"/>\n"
603 " <signal name=\"NameAcquired\">\n"
604 " <arg type=\"s\"/>\n"
606 " <signal name=\"NameLost\">\n"
607 " <arg type=\"s\"/>\n"
609 " <signal name=\"NameOwnerChanged\">\n"
610 " <arg type=\"s\"/>\n"
611 " <arg type=\"s\"/>\n"
612 " <arg type=\"s\"/>\n"
617 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
620 r = sd_bus_message_read(m, "s", &match);
622 return synthetic_reply_method_errno(m, r, NULL);
624 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
626 return synthetic_reply_method_errno(m, r, NULL);
628 return synthetic_reply_method_return(m, NULL);
630 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
633 r = sd_bus_message_read(m, "s", &match);
635 return synthetic_reply_method_errno(m, r, NULL);
637 r = bus_remove_match_by_string(a, match, NULL, NULL);
639 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
641 return synthetic_reply_method_errno(m, r, NULL);
643 return synthetic_reply_method_return(m, NULL);
645 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
646 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
647 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
649 r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
651 return synthetic_reply_method_errno(m, r, &error);
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;
657 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
659 r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error);
661 return synthetic_reply_method_errno(m, r, &error);
663 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
665 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
666 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
667 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
669 r = get_creds_by_message(a, m, SD_BUS_CREDS_UID, &creds, &error);
671 return synthetic_reply_method_errno(m, r, &error);
673 return synthetic_reply_method_return(m, "u", (uint32_t) creds->uid);
675 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
676 sd_id128_t server_id;
677 char buf[SD_ID128_STRING_MAX];
679 r = sd_bus_get_server_id(a, &server_id);
681 return synthetic_reply_method_errno(m, r, NULL);
683 return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
685 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
687 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
688 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
690 r = sd_bus_message_read(m, "s", &name);
692 return synthetic_reply_method_errno(m, r, NULL);
694 if (streq(name, "org.freedesktop.DBus"))
695 return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
697 r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
699 return synthetic_reply_method_errno(m, r, &error);
701 return synthetic_reply_method_return(m, "s", creds->unique_name);
703 /* "Hello" is handled in process_hello() */
705 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
706 _cleanup_strv_free_ char **names = NULL;
708 r = sd_bus_list_names(a, NULL, &names);
710 return synthetic_reply_method_errno(m, r, NULL);
712 /* Let's sort the names list to make it stable */
715 return synthetic_reply_return_strv(m, names);
717 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
718 _cleanup_strv_free_ char **names = NULL;
720 r = sd_bus_list_names(a, &names, NULL);
722 return synthetic_reply_method_errno(m, r, NULL);
724 r = strv_extend(&names, "org.freedesktop.DBus");
726 return synthetic_reply_method_errno(m, r, NULL);
728 /* Let's sort the names list to make it stable */
731 return synthetic_reply_return_strv(m, names);
733 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
734 struct kdbus_cmd_name_list cmd = {};
735 struct kdbus_name_list *name_list;
736 struct kdbus_cmd_free cmd_free;
737 struct kdbus_name_info *name;
738 _cleanup_strv_free_ char **owners = NULL;
739 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
743 r = sd_bus_message_read(m, "s", &arg0);
745 return synthetic_reply_method_errno(m, r, NULL);
747 if (!service_name_is_valid(arg0))
748 return synthetic_reply_method_errno(m, -EINVAL, NULL);
750 r = sd_bus_get_name_creds(a, arg0, 0, NULL);
751 if (r == -ESRCH || r == -ENXIO) {
752 sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0);
753 return synthetic_reply_method_errno(m, r, &error);
756 return synthetic_reply_method_errno(m, r, NULL);
758 cmd.flags = KDBUS_NAME_LIST_QUEUED;
759 r = ioctl(a->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
761 return synthetic_reply_method_errno(m, -errno, NULL);
763 name_list = (struct kdbus_name_list *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
765 KDBUS_ITEM_FOREACH(name, name_list, names) {
766 const char *entry_name = NULL;
767 struct kdbus_item *item;
770 KDBUS_ITEM_FOREACH(item, name, items)
771 if (item->type == KDBUS_ITEM_NAME)
772 entry_name = item->str;
774 if (!streq_ptr(entry_name, arg0))
777 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
782 r = strv_consume(&owners, n);
790 cmd_free.offset = cmd.offset;
792 r = ioctl(a->input_fd, KDBUS_CMD_FREE, &cmd_free);
794 return synthetic_reply_method_errno(m, r, NULL);
797 return synthetic_reply_method_errno(m, err, NULL);
799 return synthetic_reply_return_strv(m, owners);
801 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
804 r = sd_bus_message_read(m, "s", &name);
806 return synthetic_reply_method_errno(m, r, NULL);
808 if (!service_name_is_valid(name))
809 return synthetic_reply_method_errno(m, -EINVAL, NULL);
811 if (streq(name, "org.freedesktop.DBus"))
812 return synthetic_reply_method_return(m, "b", true);
814 r = sd_bus_get_name_creds(a, name, 0, NULL);
815 if (r < 0 && r != -ESRCH && r != -ENXIO)
816 return synthetic_reply_method_errno(m, r, NULL);
818 return synthetic_reply_method_return(m, "b", r >= 0);
820 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
823 r = sd_bus_message_read(m, "s", &name);
825 return synthetic_reply_method_errno(m, r, NULL);
827 if (!service_name_is_valid(name))
828 return synthetic_reply_method_errno(m, -EINVAL, NULL);
830 r = sd_bus_release_name(a, name);
833 return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
834 if (r == -EADDRINUSE)
835 return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
837 return synthetic_reply_method_errno(m, r, NULL);
840 return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
842 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
843 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
845 r = sd_bus_error_setf(&error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
847 return synthetic_reply_method_errno(m, r, &error);
849 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
851 uint32_t flags, param;
853 r = sd_bus_message_read(m, "su", &name, &flags);
855 return synthetic_reply_method_errno(m, r, NULL);
857 if (!service_name_is_valid(name))
858 return synthetic_reply_method_errno(m, -EINVAL, NULL);
859 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
860 return synthetic_reply_method_errno(m, -EINVAL, NULL);
863 if (flags & BUS_NAME_ALLOW_REPLACEMENT)
864 param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
865 if (flags & BUS_NAME_REPLACE_EXISTING)
866 param |= SD_BUS_NAME_REPLACE_EXISTING;
867 if (!(flags & BUS_NAME_DO_NOT_QUEUE))
868 param |= SD_BUS_NAME_QUEUE;
870 r = sd_bus_request_name(a, name, param);
873 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
875 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
876 return synthetic_reply_method_errno(m, r, NULL);
880 return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
882 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
884 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
885 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
889 r = sd_bus_message_read(m, "su", &name, &flags);
891 return synthetic_reply_method_errno(m, r, NULL);
893 if (!service_name_is_valid(name))
894 return synthetic_reply_method_errno(m, -EINVAL, NULL);
896 return synthetic_reply_method_errno(m, -EINVAL, NULL);
898 r = sd_bus_get_name_creds(a, name, 0, NULL);
899 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
900 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
902 return synthetic_reply_method_errno(m, r, NULL);
904 r = sd_bus_message_new_method_call(
909 "org.freedesktop.DBus.Peer",
912 return synthetic_reply_method_errno(m, r, NULL);
914 r = sd_bus_send(a, msg, NULL);
916 return synthetic_reply_method_errno(m, r, NULL);
918 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
920 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
921 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
922 _cleanup_strv_free_ char **args = NULL;
924 if (!peer_is_privileged(a, m))
925 return synthetic_reply_method_errno(m, -EPERM, NULL);
927 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
929 return synthetic_reply_method_errno(m, r, NULL);
931 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
932 _cleanup_free_ char *s = NULL;
936 r = sd_bus_message_read(m, "ss", &key, &value);
938 return synthetic_reply_method_errno(m, r, NULL);
940 s = strjoin(key, "=", value, NULL);
942 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
944 r = strv_extend(&args, s);
946 return synthetic_reply_method_errno(m, r, NULL);
948 r = sd_bus_message_exit_container(m);
950 return synthetic_reply_method_errno(m, r, NULL);
953 r = sd_bus_message_exit_container(m);
955 return synthetic_reply_method_errno(m, r, NULL);
958 return synthetic_reply_method_errno(m, -EINVAL, NULL);
960 r = sd_bus_message_new_method_call(
963 "org.freedesktop.systemd1",
964 "/org/freedesktop/systemd1",
965 "org.freedesktop.systemd1.Manager",
968 return synthetic_reply_method_errno(m, r, NULL);
970 r = sd_bus_message_append_strv(msg, args);
972 return synthetic_reply_method_errno(m, r, NULL);
974 r = sd_bus_call(a, msg, 0, NULL, NULL);
976 return synthetic_reply_method_errno(m, r, NULL);
978 return synthetic_reply_method_return(m, NULL);
981 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
983 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
985 return synthetic_reply_method_errno(m, r, &error);
989 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
990 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
999 /* As reaction to hello we need to respond with two messages:
1000 * the callback reply and the NameAcquired for the unique
1001 * name, since hello is otherwise obsolete on kdbus. */
1004 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1005 streq_ptr(m->destination, "org.freedesktop.DBus");
1012 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1017 log_error("Got duplicate hello, aborting.");
1026 r = sd_bus_message_new_method_return(m, &n);
1028 log_error("Failed to generate HELLO reply: %s", strerror(-r));
1032 r = sd_bus_message_append(n, "s", a->unique_name);
1034 log_error("Failed to append unique name to HELLO reply: %s", strerror(-r));
1038 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1040 log_error("Failed to append sender to HELLO reply: %s", strerror(-r));
1044 r = bus_seal_synthetic_message(b, n);
1046 log_error("Failed to seal HELLO reply: %s", strerror(-r));
1050 r = sd_bus_send(b, n, NULL);
1052 log_error("Failed to send HELLO reply: %s", strerror(-r));
1056 n = sd_bus_message_unref(n);
1057 r = sd_bus_message_new_signal(
1060 "/org/freedesktop/DBus",
1061 "org.freedesktop.DBus",
1064 log_error("Failed to allocate initial NameAcquired message: %s", strerror(-r));
1068 r = sd_bus_message_append(n, "s", a->unique_name);
1070 log_error("Failed to append unique name to NameAcquired message: %s", strerror(-r));
1074 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1076 log_error("Failed to append sender to NameAcquired message: %s", strerror(-r));
1080 r = bus_seal_synthetic_message(b, n);
1082 log_error("Failed to seal NameAcquired message: %s", strerror(-r));
1086 r = sd_bus_send(b, n, NULL);
1088 log_error("Failed to send NameAcquired message: %s", strerror(-r));
1095 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1096 char **well_known = NULL;
1106 /* We will change the sender of messages from the bus driver
1107 * so that they originate from the bus driver. This is a
1108 * speciality originating from dbus1, where the bus driver did
1109 * not have a unique id, but only the well-known name. */
1111 c = sd_bus_message_get_creds(m);
1115 r = sd_bus_creds_get_well_known_names(c, &well_known);
1119 if (strv_contains(well_known, "org.freedesktop.DBus"))
1120 m->sender = "org.freedesktop.DBus";
1125 int main(int argc, char *argv[]) {
1127 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1128 sd_id128_t server_id;
1129 int r, in_fd, out_fd;
1130 bool got_hello = false;
1132 struct ucred ucred = {};
1133 _cleanup_free_ char *peersec = NULL;
1136 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1137 log_parse_environment();
1140 r = parse_argv(argc, argv);
1144 r = policy_load(&policy, arg_configuration);
1146 log_error("Failed to load policy: %s", strerror(-r));
1150 /* policy_dump(&policy); */
1152 r = sd_listen_fds(0);
1154 in_fd = STDIN_FILENO;
1155 out_fd = STDOUT_FILENO;
1156 } else if (r == 1) {
1157 in_fd = SD_LISTEN_FDS_START;
1158 out_fd = SD_LISTEN_FDS_START;
1160 log_error("Illegal number of file descriptors passed");
1165 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1166 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1169 (void) getpeercred(in_fd, &ucred);
1170 (void) getpeersec(in_fd, &peersec);
1173 if (arg_drop_privileges) {
1174 const char *user = "systemd-bus-proxy";
1178 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1180 log_error("Cannot resolve user name %s: %s", user, strerror(-r));
1184 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1191 log_error("Failed to allocate bus: %s", strerror(-r));
1195 r = sd_bus_set_name(a, "sd-proxy");
1197 log_error("Failed to set bus name: %s", strerror(-r));
1201 r = sd_bus_set_address(a, arg_address);
1203 log_error("Failed to set address to connect to: %s", strerror(-r));
1207 r = sd_bus_negotiate_fds(a, is_unix);
1209 log_error("Failed to set FD negotiation: %s", strerror(-r));
1213 if (ucred.pid > 0) {
1214 a->fake_creds.pid = ucred.pid;
1215 a->fake_creds.uid = ucred.uid;
1216 a->fake_creds.gid = ucred.gid;
1217 a->fake_creds_valid = true;
1221 a->fake_label = peersec;
1225 a->manual_peer_interface = true;
1227 r = sd_bus_start(a);
1229 log_error("Failed to start bus client: %s", strerror(-r));
1233 r = sd_bus_get_server_id(a, &server_id);
1235 log_error("Failed to get server ID: %s", strerror(-r));
1241 log_error("Failed to allocate bus: %s", strerror(-r));
1245 r = sd_bus_set_fd(b, in_fd, out_fd);
1247 log_error("Failed to set fds: %s", strerror(-r));
1251 r = sd_bus_set_server(b, 1, server_id);
1253 log_error("Failed to set server mode: %s", strerror(-r));
1257 r = sd_bus_negotiate_fds(b, is_unix);
1259 log_error("Failed to set FD negotiation: %s", strerror(-r));
1263 r = sd_bus_set_anonymous(b, true);
1265 log_error("Failed to set anonymous authentication: %s", strerror(-r));
1269 b->manual_peer_interface = true;
1271 r = sd_bus_start(b);
1273 log_error("Failed to start bus client: %s", strerror(-r));
1277 r = rename_service(a, b);
1279 log_debug("Failed to rename process: %s", strerror(-r));
1282 _cleanup_free_ char *match = NULL;
1285 r = sd_bus_get_unique_name(a, &unique);
1287 log_error("Failed to get unique name: %s", strerror(-r));
1291 match = strjoin("type='signal',"
1292 "sender='org.freedesktop.DBus',"
1293 "path='/org/freedesktop/DBus',"
1294 "interface='org.freedesktop.DBus',"
1295 "member='NameOwnerChanged',"
1305 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1307 log_error("Failed to add match for NameLost: %s", strerror(-r));
1312 match = strjoin("type='signal',"
1313 "sender='org.freedesktop.DBus',"
1314 "path='/org/freedesktop/DBus',"
1315 "interface='org.freedesktop.DBus',"
1316 "member='NameOwnerChanged',"
1326 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1328 log_error("Failed to add match for NameAcquired: %s", strerror(-r));
1334 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1335 int events_a, events_b, fd;
1336 uint64_t timeout_a, timeout_b, t;
1337 struct timespec _ts, *ts;
1338 struct pollfd *pollfd;
1342 r = sd_bus_process(a, &m);
1344 /* treat 'connection reset by peer' as clean exit condition */
1345 if (r == -ECONNRESET)
1348 log_error("Failed to process bus a: %s", strerror(-r));
1354 /* We officially got EOF, let's quit */
1355 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1360 k = synthesize_name_acquired(a, b, m);
1363 log_error("Failed to synthesize message: %s", strerror(-r));
1369 k = sd_bus_send(b, m, NULL);
1371 if (k == -ECONNRESET)
1375 log_error("Failed to send message: %s", strerror(-r));
1386 r = sd_bus_process(b, &m);
1388 /* treat 'connection reset by peer' as clean exit condition */
1389 if (r == -ECONNRESET)
1392 log_error("Failed to process bus b: %s", strerror(-r));
1398 /* We officially got EOF, let's quit */
1399 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1404 k = process_hello(a, b, m, &got_hello);
1407 log_error("Failed to process HELLO: %s", strerror(-r));
1414 k = process_policy(a, b, m);
1417 log_error("Failed to process policy: %s", strerror(-r));
1421 k = process_driver(a, b, m);
1424 log_error("Failed to process driver calls: %s", strerror(-r));
1431 k = sd_bus_send(a, m, NULL);
1433 if (k == -ECONNRESET)
1437 log_error("Failed to send message: %s", strerror(-r));
1449 fd = sd_bus_get_fd(a);
1451 log_error("Failed to get fd: %s", strerror(-r));
1455 events_a = sd_bus_get_events(a);
1457 log_error("Failed to get events mask: %s", strerror(-r));
1461 r = sd_bus_get_timeout(a, &timeout_a);
1463 log_error("Failed to get timeout: %s", strerror(-r));
1467 events_b = sd_bus_get_events(b);
1469 log_error("Failed to get events mask: %s", strerror(-r));
1473 r = sd_bus_get_timeout(b, &timeout_b);
1475 log_error("Failed to get timeout: %s", strerror(-r));
1480 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1483 if (t == (uint64_t) -1)
1488 nw = now(CLOCK_MONOTONIC);
1494 ts = timespec_store(&_ts, t);
1497 pollfd = (struct pollfd[3]) {
1498 {.fd = fd, .events = events_a, },
1499 {.fd = in_fd, .events = events_b & POLLIN, },
1500 {.fd = out_fd, .events = events_b & POLLOUT, }
1503 r = ppoll(pollfd, 3, ts, NULL);
1505 log_error("ppoll() failed: %m");
1513 "STATUS=Shutting down.");
1515 policy_free(&policy);
1516 strv_free(arg_configuration);
1519 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;