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_peer_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_owner(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")) {
647 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
648 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
650 r = sd_bus_message_read(m, "s", &name);
654 r = get_creds_by_name(a, name, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, NULL);
655 if (r == -ESRCH || r == -ENXIO) {
656 sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get security context of name '%s': no such name.", name);
657 return synthetic_reply_method_errno(m, r, &error);
660 return synthetic_reply_method_errno(m, r, NULL);
662 return synthetic_reply_method_return(m, "y", creds->label, strlen(creds->label));
664 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
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 = sd_bus_message_read(m, "s", &name);
673 r = get_creds_by_name(a, name, SD_BUS_CREDS_PID, &creds, NULL);
674 if (r == -ESRCH || r == -ENXIO) {
675 sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get PID of name '%s': no such name.", name);
676 return synthetic_reply_method_errno(m, r, &error);
679 return synthetic_reply_method_errno(m, r, NULL);
681 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
683 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
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);
692 r = get_creds_by_name(a, name, SD_BUS_CREDS_UID, &creds, NULL);
693 if (r == -ESRCH || r == -ENXIO) {
694 sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get UID of name '%s': no such name.", name);
695 return synthetic_reply_method_errno(m, r, &error);
698 return synthetic_reply_method_errno(m, r, NULL);
700 return synthetic_reply_method_return(m, "u", (uint32_t) creds->uid);
702 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
703 sd_id128_t server_id;
704 char buf[SD_ID128_STRING_MAX];
706 r = sd_bus_get_server_id(a, &server_id);
708 return synthetic_reply_method_errno(m, r, NULL);
710 return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
712 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
714 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
715 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
717 r = sd_bus_message_read(m, "s", &name);
719 return synthetic_reply_method_errno(m, r, NULL);
721 if (streq(name, "org.freedesktop.DBus"))
722 return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
724 r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
726 return synthetic_reply_method_errno(m, r, &error);
728 return synthetic_reply_method_return(m, "s", creds->unique_name);
730 /* "Hello" is handled in process_hello() */
732 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
733 _cleanup_strv_free_ char **names = NULL;
735 r = sd_bus_list_names(a, NULL, &names);
737 return synthetic_reply_method_errno(m, r, NULL);
739 /* Let's sort the names list to make it stable */
742 return synthetic_reply_return_strv(m, names);
744 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
745 _cleanup_strv_free_ char **names = NULL;
747 r = sd_bus_list_names(a, &names, NULL);
749 return synthetic_reply_method_errno(m, r, NULL);
751 r = strv_extend(&names, "org.freedesktop.DBus");
753 return synthetic_reply_method_errno(m, r, NULL);
755 /* Let's sort the names list to make it stable */
758 return synthetic_reply_return_strv(m, names);
760 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
761 struct kdbus_cmd_name_list cmd = {};
762 struct kdbus_name_list *name_list;
763 struct kdbus_cmd_free cmd_free;
764 struct kdbus_cmd_name *name;
765 _cleanup_strv_free_ char **owners = NULL;
766 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
770 r = sd_bus_message_read(m, "s", &arg0);
772 return synthetic_reply_method_errno(m, r, NULL);
774 if (!service_name_is_valid(arg0))
775 return synthetic_reply_method_errno(m, -EINVAL, NULL);
777 r = sd_bus_get_owner(a, arg0, 0, NULL);
778 if (r == -ESRCH || r == -ENXIO) {
779 sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0);
780 return synthetic_reply_method_errno(m, r, &error);
783 return synthetic_reply_method_errno(m, r, NULL);
785 cmd.flags = KDBUS_NAME_LIST_QUEUED;
786 r = ioctl(a->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
788 return synthetic_reply_method_errno(m, -errno, NULL);
790 name_list = (struct kdbus_name_list *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
792 KDBUS_ITEM_FOREACH(name, name_list, names) {
793 const char *entry_name = NULL;
794 struct kdbus_item *item;
797 KDBUS_ITEM_FOREACH(item, name, items)
798 if (item->type == KDBUS_ITEM_NAME)
799 entry_name = item->str;
801 if (!streq_ptr(entry_name, arg0))
804 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
809 r = strv_consume(&owners, n);
817 cmd_free.offset = cmd.offset;
819 r = ioctl(a->input_fd, KDBUS_CMD_FREE, &cmd_free);
821 return synthetic_reply_method_errno(m, r, NULL);
824 return synthetic_reply_method_errno(m, err, NULL);
826 return synthetic_reply_return_strv(m, owners);
828 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
831 r = sd_bus_message_read(m, "s", &name);
833 return synthetic_reply_method_errno(m, r, NULL);
835 if (!service_name_is_valid(name))
836 return synthetic_reply_method_errno(m, -EINVAL, NULL);
838 if (streq(name, "org.freedesktop.DBus"))
839 return synthetic_reply_method_return(m, "b", true);
841 r = sd_bus_get_owner(a, name, 0, NULL);
842 if (r < 0 && r != -ESRCH && r != -ENXIO)
843 return synthetic_reply_method_errno(m, r, NULL);
845 return synthetic_reply_method_return(m, "b", r >= 0);
847 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
850 r = sd_bus_message_read(m, "s", &name);
852 return synthetic_reply_method_errno(m, r, NULL);
854 if (!service_name_is_valid(name))
855 return synthetic_reply_method_errno(m, -EINVAL, NULL);
857 r = sd_bus_release_name(a, name);
860 return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
861 if (r == -EADDRINUSE)
862 return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
864 return synthetic_reply_method_errno(m, r, NULL);
867 return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
869 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
870 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
872 r = sd_bus_error_setf(&error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
874 return synthetic_reply_method_errno(m, r, &error);
876 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
878 uint32_t flags, param;
880 r = sd_bus_message_read(m, "su", &name, &flags);
882 return synthetic_reply_method_errno(m, r, NULL);
884 if (!service_name_is_valid(name))
885 return synthetic_reply_method_errno(m, -EINVAL, NULL);
886 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
887 return synthetic_reply_method_errno(m, -EINVAL, NULL);
890 if (flags & BUS_NAME_ALLOW_REPLACEMENT)
891 param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
892 if (flags & BUS_NAME_REPLACE_EXISTING)
893 param |= SD_BUS_NAME_REPLACE_EXISTING;
894 if (!(flags & BUS_NAME_DO_NOT_QUEUE))
895 param |= SD_BUS_NAME_QUEUE;
897 r = sd_bus_request_name(a, name, param);
900 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
902 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
903 return synthetic_reply_method_errno(m, r, NULL);
907 return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
909 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
911 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
912 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
916 r = sd_bus_message_read(m, "su", &name, &flags);
918 return synthetic_reply_method_errno(m, r, NULL);
920 if (!service_name_is_valid(name))
921 return synthetic_reply_method_errno(m, -EINVAL, NULL);
923 return synthetic_reply_method_errno(m, -EINVAL, NULL);
925 r = sd_bus_get_owner(a, name, 0, NULL);
926 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
927 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
929 return synthetic_reply_method_errno(m, r, NULL);
931 r = sd_bus_message_new_method_call(
936 "org.freedesktop.DBus.Peer",
939 return synthetic_reply_method_errno(m, r, NULL);
941 r = sd_bus_send(a, msg, NULL);
943 return synthetic_reply_method_errno(m, r, NULL);
945 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
947 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
948 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
949 _cleanup_strv_free_ char **args = NULL;
951 if (!peer_is_privileged(a, m))
952 return synthetic_reply_method_errno(m, -EPERM, NULL);
954 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
956 return synthetic_reply_method_errno(m, r, NULL);
958 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
959 _cleanup_free_ char *s = NULL;
963 r = sd_bus_message_read(m, "ss", &key, &value);
965 return synthetic_reply_method_errno(m, r, NULL);
967 s = strjoin(key, "=", value, NULL);
969 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
971 r = strv_extend(&args, s);
973 return synthetic_reply_method_errno(m, r, NULL);
975 r = sd_bus_message_exit_container(m);
977 return synthetic_reply_method_errno(m, r, NULL);
980 r = sd_bus_message_exit_container(m);
982 return synthetic_reply_method_errno(m, r, NULL);
985 return synthetic_reply_method_errno(m, -EINVAL, NULL);
987 r = sd_bus_message_new_method_call(
990 "org.freedesktop.systemd1",
991 "/org/freedesktop/systemd1",
992 "org.freedesktop.systemd1.Manager",
995 return synthetic_reply_method_errno(m, r, NULL);
997 r = sd_bus_message_append_strv(msg, args);
999 return synthetic_reply_method_errno(m, r, NULL);
1001 r = sd_bus_call(a, msg, 0, NULL, NULL);
1003 return synthetic_reply_method_errno(m, r, NULL);
1005 return synthetic_reply_method_return(m, NULL);
1008 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1010 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
1012 return synthetic_reply_method_errno(m, r, &error);
1016 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
1017 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
1026 /* As reaction to hello we need to respond with two messages:
1027 * the callback reply and the NameAcquired for the unique
1028 * name, since hello is otherwise obsolete on kdbus. */
1031 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1032 streq_ptr(m->destination, "org.freedesktop.DBus");
1039 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1044 log_error("Got duplicate hello, aborting.");
1053 r = sd_bus_message_new_method_return(m, &n);
1055 log_error("Failed to generate HELLO reply: %s", strerror(-r));
1059 r = sd_bus_message_append(n, "s", a->unique_name);
1061 log_error("Failed to append unique name to HELLO reply: %s", strerror(-r));
1065 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1067 log_error("Failed to append sender to HELLO reply: %s", strerror(-r));
1071 r = bus_seal_synthetic_message(b, n);
1073 log_error("Failed to seal HELLO reply: %s", strerror(-r));
1077 r = sd_bus_send(b, n, NULL);
1079 log_error("Failed to send HELLO reply: %s", strerror(-r));
1083 n = sd_bus_message_unref(n);
1084 r = sd_bus_message_new_signal(
1087 "/org/freedesktop/DBus",
1088 "org.freedesktop.DBus",
1091 log_error("Failed to allocate initial NameAcquired message: %s", strerror(-r));
1095 r = sd_bus_message_append(n, "s", a->unique_name);
1097 log_error("Failed to append unique name to NameAcquired message: %s", strerror(-r));
1101 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1103 log_error("Failed to append sender to NameAcquired message: %s", strerror(-r));
1107 r = bus_seal_synthetic_message(b, n);
1109 log_error("Failed to seal NameAcquired message: %s", strerror(-r));
1113 r = sd_bus_send(b, n, NULL);
1115 log_error("Failed to send NameAcquired message: %s", strerror(-r));
1122 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1123 char **well_known = NULL;
1133 /* We will change the sender of messages from the bus driver
1134 * so that they originate from the bus driver. This is a
1135 * speciality originating from dbus1, where the bus driver did
1136 * not have a unique id, but only the well-known name. */
1138 c = sd_bus_message_get_creds(m);
1142 r = sd_bus_creds_get_well_known_names(c, &well_known);
1146 if (strv_contains(well_known, "org.freedesktop.DBus"))
1147 m->sender = "org.freedesktop.DBus";
1152 int main(int argc, char *argv[]) {
1154 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1155 sd_id128_t server_id;
1156 int r, in_fd, out_fd;
1157 bool got_hello = false;
1159 struct ucred ucred = {};
1160 _cleanup_free_ char *peersec = NULL;
1163 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1164 log_parse_environment();
1167 r = parse_argv(argc, argv);
1171 r = policy_load(&policy, arg_configuration);
1173 log_error("Failed to load policy: %s", strerror(-r));
1177 /* policy_dump(&policy); */
1179 r = sd_listen_fds(0);
1181 in_fd = STDIN_FILENO;
1182 out_fd = STDOUT_FILENO;
1183 } else if (r == 1) {
1184 in_fd = SD_LISTEN_FDS_START;
1185 out_fd = SD_LISTEN_FDS_START;
1187 log_error("Illegal number of file descriptors passed");
1192 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1193 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1196 r = getpeercred(in_fd, &ucred);
1198 log_error("Failed to get peer creds: %s", strerror(-r));
1202 (void) getpeersec(in_fd, &peersec);
1205 if (arg_drop_privileges) {
1206 const char *user = "systemd-bus-proxy";
1210 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1212 log_error("Cannot resolve user name %s: %s", user, strerror(-r));
1216 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1223 log_error("Failed to allocate bus: %s", strerror(-r));
1227 r = sd_bus_set_name(a, "sd-proxy");
1229 log_error("Failed to set bus name: %s", strerror(-r));
1233 r = sd_bus_set_address(a, arg_address);
1235 log_error("Failed to set address to connect to: %s", strerror(-r));
1239 r = sd_bus_negotiate_fds(a, is_unix);
1241 log_error("Failed to set FD negotiation: %s", strerror(-r));
1245 if (ucred.pid > 0) {
1246 a->fake_creds.pid = ucred.pid;
1247 a->fake_creds.uid = ucred.uid;
1248 a->fake_creds.gid = ucred.gid;
1249 a->fake_creds_valid = true;
1253 a->fake_label = peersec;
1257 a->manual_peer_interface = true;
1259 r = sd_bus_start(a);
1261 log_error("Failed to start bus client: %s", strerror(-r));
1265 r = sd_bus_get_server_id(a, &server_id);
1267 log_error("Failed to get server ID: %s", strerror(-r));
1273 log_error("Failed to allocate bus: %s", strerror(-r));
1277 r = sd_bus_set_fd(b, in_fd, out_fd);
1279 log_error("Failed to set fds: %s", strerror(-r));
1283 r = sd_bus_set_server(b, 1, server_id);
1285 log_error("Failed to set server mode: %s", strerror(-r));
1289 r = sd_bus_negotiate_fds(b, is_unix);
1291 log_error("Failed to set FD negotiation: %s", strerror(-r));
1295 r = sd_bus_set_anonymous(b, true);
1297 log_error("Failed to set anonymous authentication: %s", strerror(-r));
1301 b->manual_peer_interface = true;
1303 r = sd_bus_start(b);
1305 log_error("Failed to start bus client: %s", strerror(-r));
1309 r = rename_service(a, b);
1311 log_debug("Failed to rename process: %s", strerror(-r));
1314 _cleanup_free_ char *match = NULL;
1317 r = sd_bus_get_unique_name(a, &unique);
1319 log_error("Failed to get unique name: %s", strerror(-r));
1323 match = strjoin("type='signal',"
1324 "sender='org.freedesktop.DBus',"
1325 "path='/org/freedesktop/DBus',"
1326 "interface='org.freedesktop.DBus',"
1327 "member='NameOwnerChanged',"
1337 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1339 log_error("Failed to add match for NameLost: %s", strerror(-r));
1344 match = strjoin("type='signal',"
1345 "sender='org.freedesktop.DBus',"
1346 "path='/org/freedesktop/DBus',"
1347 "interface='org.freedesktop.DBus',"
1348 "member='NameOwnerChanged',"
1358 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1360 log_error("Failed to add match for NameAcquired: %s", strerror(-r));
1366 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1367 int events_a, events_b, fd;
1368 uint64_t timeout_a, timeout_b, t;
1369 struct timespec _ts, *ts;
1370 struct pollfd *pollfd;
1374 r = sd_bus_process(a, &m);
1376 /* treat 'connection reset by peer' as clean exit condition */
1377 if (r == -ECONNRESET)
1380 log_error("Failed to process bus a: %s", strerror(-r));
1386 /* We officially got EOF, let's quit */
1387 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1392 k = synthesize_name_acquired(a, b, m);
1395 log_error("Failed to synthesize message: %s", strerror(-r));
1401 k = sd_bus_send(b, m, NULL);
1403 if (k == -ECONNRESET)
1407 log_error("Failed to send message: %s", strerror(-r));
1418 r = sd_bus_process(b, &m);
1420 /* treat 'connection reset by peer' as clean exit condition */
1421 if (r == -ECONNRESET)
1424 log_error("Failed to process bus b: %s", strerror(-r));
1430 /* We officially got EOF, let's quit */
1431 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1436 k = process_hello(a, b, m, &got_hello);
1439 log_error("Failed to process HELLO: %s", strerror(-r));
1446 k = process_policy(a, b, m);
1449 log_error("Failed to process policy: %s", strerror(-r));
1453 k = process_driver(a, b, m);
1456 log_error("Failed to process driver calls: %s", strerror(-r));
1463 k = sd_bus_send(a, m, NULL);
1465 if (k == -ECONNRESET)
1469 log_error("Failed to send message: %s", strerror(-r));
1481 fd = sd_bus_get_fd(a);
1483 log_error("Failed to get fd: %s", strerror(-r));
1487 events_a = sd_bus_get_events(a);
1489 log_error("Failed to get events mask: %s", strerror(-r));
1493 r = sd_bus_get_timeout(a, &timeout_a);
1495 log_error("Failed to get timeout: %s", strerror(-r));
1499 events_b = sd_bus_get_events(b);
1501 log_error("Failed to get events mask: %s", strerror(-r));
1505 r = sd_bus_get_timeout(b, &timeout_b);
1507 log_error("Failed to get timeout: %s", strerror(-r));
1512 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1515 if (t == (uint64_t) -1)
1520 nw = now(CLOCK_MONOTONIC);
1526 ts = timespec_store(&_ts, t);
1529 pollfd = (struct pollfd[3]) {
1530 {.fd = fd, .events = events_a, },
1531 {.fd = in_fd, .events = events_b & POLLIN, },
1532 {.fd = out_fd, .events = events_b & POLLOUT, }
1535 r = ppoll(pollfd, 3, ts, NULL);
1537 log_error("ppoll() failed: %m");
1545 "STATUS=Shutting down.");
1547 policy_free(&policy);
1548 strv_free(arg_configuration);
1551 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;