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 Hashmap *names_hash = NULL;
56 static int help(void) {
58 printf("%s [OPTIONS...]\n\n"
59 "Connect STDIO or a socket to a given bus address.\n\n"
60 " -h --help Show this help\n"
61 " --version Show package version\n"
62 " --drop-privileges Drop privileges\n"
63 " --configuration=PATH Configuration file or directory\n"
64 " --machine=MACHINE Connect to specified machine\n"
65 " --address=ADDRESS Connect to the bus specified by ADDRESS\n"
66 " (default: " DEFAULT_SYSTEM_BUS_PATH ")\n",
67 program_invocation_short_name);
72 static int parse_argv(int argc, char *argv[]) {
82 static const struct option options[] = {
83 { "help", no_argument, NULL, 'h' },
84 { "version", no_argument, NULL, ARG_VERSION },
85 { "address", required_argument, NULL, ARG_ADDRESS },
86 { "drop-privileges", no_argument, NULL, ARG_DROP_PRIVILEGES },
87 { "configuration", required_argument, NULL, ARG_CONFIGURATION },
88 { "machine", required_argument, NULL, ARG_MACHINE },
97 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
106 puts(PACKAGE_STRING);
107 puts(SYSTEMD_FEATURES);
122 case ARG_DROP_PRIVILEGES:
123 arg_drop_privileges = true;
126 case ARG_CONFIGURATION:
127 r = strv_extend(&arg_configuration, optarg);
133 _cleanup_free_ char *e = NULL;
136 e = bus_address_escape(optarg);
141 a = strjoin("x-container-kernel:machine=", e, ";x-container-unix:machine=", e, NULL);
143 a = strjoin("x-container-unix:machine=", e, NULL);
158 assert_not_reached("Unhandled option");
161 /* If the first command line argument is only "x" characters
162 * we'll write who we are talking to into it, so that "ps" is
164 arg_command_line_buffer = argv[optind];
165 if (argc > optind + 1 || (arg_command_line_buffer && !in_charset(arg_command_line_buffer, "x"))) {
166 log_error("Too many arguments");
171 arg_address = strdup(DEFAULT_SYSTEM_BUS_PATH);
179 static int rename_service(sd_bus *a, sd_bus *b) {
180 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
181 _cleanup_free_ char *p = NULL, *name = NULL;
191 r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM, &creds);
195 r = sd_bus_creds_get_uid(creds, &uid);
199 r = sd_bus_creds_get_pid(creds, &pid);
203 r = sd_bus_creds_get_cmdline(creds, &cmdline);
207 r = sd_bus_creds_get_comm(creds, &comm);
211 name = uid_to_name(uid);
215 p = strv_join(cmdline, " ");
219 /* The status string gets the full command line ... */
221 "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)",
225 /* ... and the argv line only the short comm */
226 if (arg_command_line_buffer) {
229 m = strlen(arg_command_line_buffer);
230 w = snprintf(arg_command_line_buffer, m,
231 "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]",
236 memzero(arg_command_line_buffer + w, m - w);
239 log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s",
247 static int synthesize_name_acquired(sd_bus *a, sd_bus *b, sd_bus_message *m) {
248 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
249 const char *name, *old_owner, *new_owner;
256 /* If we get NameOwnerChanged for our own name, we need to
257 * synthesize NameLost/NameAcquired, since socket clients need
258 * that, even though it is obsoleted on kdbus */
263 if (!sd_bus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged") ||
264 !streq_ptr(m->path, "/org/freedesktop/DBus") ||
265 !streq_ptr(m->sender, "org.freedesktop.DBus"))
268 r = sd_bus_message_read(m, "sss", &name, &old_owner, &new_owner);
272 r = sd_bus_message_rewind(m, true);
276 if (streq(old_owner, a->unique_name)) {
278 r = sd_bus_message_new_signal(
281 "/org/freedesktop/DBus",
282 "org.freedesktop.DBus",
285 } else if (streq(new_owner, a->unique_name)) {
287 r = sd_bus_message_new_signal(
290 "/org/freedesktop/DBus",
291 "org.freedesktop.DBus",
299 r = sd_bus_message_append(n, "s", name);
303 r = bus_message_append_sender(n, "org.freedesktop.DBus");
307 r = bus_seal_synthetic_message(b, n);
311 return sd_bus_send(b, n, NULL);
314 static int synthetic_driver_send(sd_bus *b, sd_bus_message *m) {
320 r = bus_message_append_sender(m, "org.freedesktop.DBus");
324 r = bus_seal_synthetic_message(b, m);
328 return sd_bus_send(b, m, NULL);
331 static int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) {
332 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
337 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
340 r = sd_bus_message_new_method_error(call, &m, e);
344 return synthetic_driver_send(call->bus, m);
347 static int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) {
349 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
353 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
356 if (sd_bus_error_is_set(p))
357 return synthetic_reply_method_error(call, p);
359 sd_bus_error_set_errno(&berror, error);
361 return synthetic_reply_method_error(call, &berror);
364 static int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) {
365 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
370 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
373 r = sd_bus_message_new_method_return(call, &m);
377 if (!isempty(types)) {
381 r = bus_message_append_ap(m, types, ap);
387 return synthetic_driver_send(call->bus, m);
390 static int synthetic_reply_return_strv(sd_bus_message *call, char **l) {
391 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
396 r = sd_bus_message_new_method_return(call, &m);
398 return synthetic_reply_method_errno(call, r, NULL);
400 r = sd_bus_message_append_strv(m, l);
402 return synthetic_reply_method_errno(call, r, NULL);
404 return synthetic_driver_send(call->bus, m);
407 static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
408 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
415 assert_return(service_name_is_valid(name), -EINVAL);
417 r = sd_bus_get_name_creds(bus, name, mask, &c);
418 if (r == -ESRCH || r == -ENXIO)
419 return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
423 if ((c->mask & mask) != mask)
432 static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
440 r = sd_bus_message_read(m, "s", &name);
444 return get_creds_by_name(bus, name, mask, _creds, error);
447 static int peer_is_privileged(sd_bus *bus, sd_bus_message *m) {
448 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
452 r = get_creds_by_message(bus, m, SD_BUS_CREDS_UID, &creds, NULL);
456 r = sd_bus_creds_get_uid(creds, &uid);
460 r = sd_bus_creds_has_effective_cap(creds, CAP_SYS_ADMIN);
470 static int process_policy(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred) {
483 /* The message came from the kernel, and is sent to our legacy client. */
484 r = sd_bus_creds_get_well_known_names(&m->creds, &names_strv);
489 if (!policy_check_recv(policy, ucred, names_hash, m->header->type, m->path, m->interface, m->member))
492 if (!policy_check_send(policy, ucred, names_strv, m->header->type, m->path, m->interface, m->member))
505 static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred) {
515 if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
518 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
519 if (0 && !isempty(sd_bus_message_get_signature(m, true))) {
520 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
522 r = sd_bus_error_setf(&error, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters");
524 return synthetic_reply_method_errno(m, r, &error);
527 return synthetic_reply_method_return(m, "s",
528 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
529 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
531 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
532 " <method name=\"Introspect\">\n"
533 " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
536 " <interface name=\"org.freedesktop.DBus\">\n"
537 " <method name=\"AddMatch\">\n"
538 " <arg type=\"s\" direction=\"in\"/>\n"
540 " <method name=\"RemoveMatch\">\n"
541 " <arg type=\"s\" direction=\"in\"/>\n"
543 " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
544 " <arg type=\"s\" direction=\"in\"/>\n"
545 " <arg type=\"ay\" direction=\"out\"/>\n"
547 " <method name=\"GetConnectionUnixProcessID\">\n"
548 " <arg type=\"s\" direction=\"in\"/>\n"
549 " <arg type=\"u\" direction=\"out\"/>\n"
551 " <method name=\"GetConnectionUnixUser\">\n"
552 " <arg type=\"s\" direction=\"in\"/>\n"
553 " <arg type=\"u\" direction=\"out\"/>\n"
555 " <method name=\"GetId\">\n"
556 " <arg type=\"s\" direction=\"out\"/>\n"
558 " <method name=\"GetNameOwner\">\n"
559 " <arg type=\"s\" direction=\"in\"/>\n"
560 " <arg type=\"s\" direction=\"out\"/>\n"
562 " <method name=\"Hello\">\n"
563 " <arg type=\"s\" direction=\"out\"/>\n"
565 " <method name=\"ListActivatableNames\">\n"
566 " <arg type=\"as\" direction=\"out\"/>\n"
568 " <method name=\"ListNames\">\n"
569 " <arg type=\"as\" direction=\"out\"/>\n"
571 " <method name=\"ListQueuedOwners\">\n"
572 " <arg type=\"s\" direction=\"in\"/>\n"
573 " <arg type=\"as\" direction=\"out\"/>\n"
575 " <method name=\"NameHasOwner\">\n"
576 " <arg type=\"s\" direction=\"in\"/>\n"
577 " <arg type=\"b\" direction=\"out\"/>\n"
579 " <method name=\"ReleaseName\">\n"
580 " <arg type=\"s\" direction=\"in\"/>\n"
581 " <arg type=\"u\" direction=\"out\"/>\n"
583 " <method name=\"ReloadConfig\">\n"
585 " <method name=\"RequestName\">\n"
586 " <arg type=\"s\" direction=\"in\"/>\n"
587 " <arg type=\"u\" direction=\"in\"/>\n"
588 " <arg type=\"u\" direction=\"out\"/>\n"
590 " <method name=\"StartServiceByName\">\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=\"UpdateActivationEnvironment\">\n"
596 " <arg type=\"a{ss}\" direction=\"in\"/>\n"
598 " <signal name=\"NameAcquired\">\n"
599 " <arg type=\"s\"/>\n"
601 " <signal name=\"NameLost\">\n"
602 " <arg type=\"s\"/>\n"
604 " <signal name=\"NameOwnerChanged\">\n"
605 " <arg type=\"s\"/>\n"
606 " <arg type=\"s\"/>\n"
607 " <arg type=\"s\"/>\n"
612 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
615 r = sd_bus_message_read(m, "s", &match);
617 return synthetic_reply_method_errno(m, r, NULL);
619 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
621 return synthetic_reply_method_errno(m, r, NULL);
623 return synthetic_reply_method_return(m, NULL);
625 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
628 r = sd_bus_message_read(m, "s", &match);
630 return synthetic_reply_method_errno(m, r, NULL);
632 r = bus_remove_match_by_string(a, match, NULL, NULL);
634 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
636 return synthetic_reply_method_errno(m, r, NULL);
638 return synthetic_reply_method_return(m, NULL);
640 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
641 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
642 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
644 r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
646 return synthetic_reply_method_errno(m, r, &error);
648 return synthetic_reply_method_return(m, "y", creds->label, strlen(creds->label));
650 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
651 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
652 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
654 r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error);
656 return synthetic_reply_method_errno(m, r, &error);
658 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
660 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
661 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
662 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
664 r = get_creds_by_message(a, m, SD_BUS_CREDS_UID, &creds, &error);
666 return synthetic_reply_method_errno(m, r, &error);
668 return synthetic_reply_method_return(m, "u", (uint32_t) creds->uid);
670 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
671 sd_id128_t server_id;
672 char buf[SD_ID128_STRING_MAX];
674 r = sd_bus_get_owner_id(a, &server_id);
676 return synthetic_reply_method_errno(m, r, NULL);
678 return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
680 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
682 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
683 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
685 r = sd_bus_message_read(m, "s", &name);
687 return synthetic_reply_method_errno(m, r, NULL);
689 if (streq(name, "org.freedesktop.DBus"))
690 return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
692 r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
694 return synthetic_reply_method_errno(m, r, &error);
696 return synthetic_reply_method_return(m, "s", creds->unique_name);
698 /* "Hello" is handled in process_hello() */
700 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
701 _cleanup_strv_free_ char **names = NULL;
703 r = sd_bus_list_names(a, NULL, &names);
705 return synthetic_reply_method_errno(m, r, NULL);
707 /* Let's sort the names list to make it stable */
710 return synthetic_reply_return_strv(m, names);
712 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
713 _cleanup_strv_free_ char **names = NULL;
715 r = sd_bus_list_names(a, &names, NULL);
717 return synthetic_reply_method_errno(m, r, NULL);
719 r = strv_extend(&names, "org.freedesktop.DBus");
721 return synthetic_reply_method_errno(m, r, NULL);
723 /* Let's sort the names list to make it stable */
726 return synthetic_reply_return_strv(m, names);
728 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
729 struct kdbus_cmd_name_list cmd = {};
730 struct kdbus_name_list *name_list;
731 struct kdbus_cmd_free cmd_free;
732 struct kdbus_name_info *name;
733 _cleanup_strv_free_ char **owners = NULL;
734 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
738 r = sd_bus_message_read(m, "s", &arg0);
740 return synthetic_reply_method_errno(m, r, NULL);
742 if (!service_name_is_valid(arg0))
743 return synthetic_reply_method_errno(m, -EINVAL, NULL);
745 r = sd_bus_get_name_creds(a, arg0, 0, NULL);
746 if (r == -ESRCH || r == -ENXIO) {
747 sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0);
748 return synthetic_reply_method_errno(m, r, &error);
751 return synthetic_reply_method_errno(m, r, NULL);
753 cmd.flags = KDBUS_NAME_LIST_QUEUED;
754 r = ioctl(a->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
756 return synthetic_reply_method_errno(m, -errno, NULL);
758 name_list = (struct kdbus_name_list *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
760 KDBUS_ITEM_FOREACH(name, name_list, names) {
761 const char *entry_name = NULL;
762 struct kdbus_item *item;
765 KDBUS_ITEM_FOREACH(item, name, items)
766 if (item->type == KDBUS_ITEM_OWNED_NAME)
767 entry_name = item->name.name;
769 if (!streq_ptr(entry_name, arg0))
772 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
777 r = strv_consume(&owners, n);
785 cmd_free.offset = cmd.offset;
787 r = ioctl(a->input_fd, KDBUS_CMD_FREE, &cmd_free);
789 return synthetic_reply_method_errno(m, r, NULL);
792 return synthetic_reply_method_errno(m, err, NULL);
794 return synthetic_reply_return_strv(m, owners);
796 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
799 r = sd_bus_message_read(m, "s", &name);
801 return synthetic_reply_method_errno(m, r, NULL);
803 if (!service_name_is_valid(name))
804 return synthetic_reply_method_errno(m, -EINVAL, NULL);
806 if (streq(name, "org.freedesktop.DBus"))
807 return synthetic_reply_method_return(m, "b", true);
809 r = sd_bus_get_name_creds(a, name, 0, NULL);
810 if (r < 0 && r != -ESRCH && r != -ENXIO)
811 return synthetic_reply_method_errno(m, r, NULL);
813 return synthetic_reply_method_return(m, "b", r >= 0);
815 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
818 r = sd_bus_message_read(m, "s", &name);
820 return synthetic_reply_method_errno(m, r, NULL);
822 if (!service_name_is_valid(name))
823 return synthetic_reply_method_errno(m, -EINVAL, NULL);
825 r = sd_bus_release_name(a, name);
828 return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
829 if (r == -EADDRINUSE)
830 return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
832 return synthetic_reply_method_errno(m, r, NULL);
835 hashmap_remove(names_hash, name);
837 return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
839 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
840 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
842 r = sd_bus_error_setf(&error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
844 return synthetic_reply_method_errno(m, r, &error);
846 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
848 uint32_t flags, param;
851 r = sd_bus_message_read(m, "su", &name, &flags);
853 return synthetic_reply_method_errno(m, r, NULL);
855 if (policy && !policy_check_own(policy, ucred, name))
856 return synthetic_reply_method_errno(m, -EPERM, NULL);
858 if (!service_name_is_valid(name))
859 return synthetic_reply_method_errno(m, -EINVAL, NULL);
860 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
861 return synthetic_reply_method_errno(m, -EINVAL, NULL);
864 if (flags & BUS_NAME_ALLOW_REPLACEMENT)
865 param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
866 if (flags & BUS_NAME_REPLACE_EXISTING)
867 param |= SD_BUS_NAME_REPLACE_EXISTING;
868 if (!(flags & BUS_NAME_DO_NOT_QUEUE))
869 param |= SD_BUS_NAME_QUEUE;
871 r = sd_bus_request_name(a, name, param);
874 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
876 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
877 return synthetic_reply_method_errno(m, r, NULL);
882 r = hashmap_put(names_hash, name, NULL);
884 return synthetic_reply_method_errno(m, r, NULL);
887 return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
889 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
891 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
892 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
896 r = sd_bus_message_read(m, "su", &name, &flags);
898 return synthetic_reply_method_errno(m, r, NULL);
900 if (!service_name_is_valid(name))
901 return synthetic_reply_method_errno(m, -EINVAL, NULL);
903 return synthetic_reply_method_errno(m, -EINVAL, NULL);
905 r = sd_bus_get_name_creds(a, name, 0, NULL);
906 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
907 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
909 return synthetic_reply_method_errno(m, r, NULL);
911 r = sd_bus_message_new_method_call(
916 "org.freedesktop.DBus.Peer",
919 return synthetic_reply_method_errno(m, r, NULL);
921 r = sd_bus_send(a, msg, NULL);
923 return synthetic_reply_method_errno(m, r, NULL);
925 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
927 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
928 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
929 _cleanup_strv_free_ char **args = NULL;
931 if (!peer_is_privileged(a, m))
932 return synthetic_reply_method_errno(m, -EPERM, NULL);
934 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
936 return synthetic_reply_method_errno(m, r, NULL);
938 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
939 _cleanup_free_ char *s = NULL;
943 r = sd_bus_message_read(m, "ss", &key, &value);
945 return synthetic_reply_method_errno(m, r, NULL);
947 s = strjoin(key, "=", value, NULL);
949 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
951 r = strv_extend(&args, s);
953 return synthetic_reply_method_errno(m, r, NULL);
955 r = sd_bus_message_exit_container(m);
957 return synthetic_reply_method_errno(m, r, NULL);
960 r = sd_bus_message_exit_container(m);
962 return synthetic_reply_method_errno(m, r, NULL);
965 return synthetic_reply_method_errno(m, -EINVAL, NULL);
967 r = sd_bus_message_new_method_call(
970 "org.freedesktop.systemd1",
971 "/org/freedesktop/systemd1",
972 "org.freedesktop.systemd1.Manager",
975 return synthetic_reply_method_errno(m, r, NULL);
977 r = sd_bus_message_append_strv(msg, args);
979 return synthetic_reply_method_errno(m, r, NULL);
981 r = sd_bus_call(a, msg, 0, NULL, NULL);
983 return synthetic_reply_method_errno(m, r, NULL);
985 return synthetic_reply_method_return(m, NULL);
988 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
990 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
992 return synthetic_reply_method_errno(m, r, &error);
996 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred, bool *got_hello) {
997 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
1006 /* As reaction to hello we need to respond with two messages:
1007 * the callback reply and the NameAcquired for the unique
1008 * name, since hello is otherwise obsolete on kdbus. */
1011 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1012 streq_ptr(m->destination, "org.freedesktop.DBus");
1019 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1024 log_error("Got duplicate hello, aborting.");
1028 if (policy && !policy_check_hello(policy, ucred)) {
1029 log_error("Policy denied HELLO");
1038 r = sd_bus_message_new_method_return(m, &n);
1040 log_error("Failed to generate HELLO reply: %s", strerror(-r));
1044 r = sd_bus_message_append(n, "s", a->unique_name);
1046 log_error("Failed to append unique name to HELLO reply: %s", strerror(-r));
1050 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1052 log_error("Failed to append sender to HELLO reply: %s", strerror(-r));
1056 r = bus_seal_synthetic_message(b, n);
1058 log_error("Failed to seal HELLO reply: %s", strerror(-r));
1062 r = sd_bus_send(b, n, NULL);
1064 log_error("Failed to send HELLO reply: %s", strerror(-r));
1068 n = sd_bus_message_unref(n);
1069 r = sd_bus_message_new_signal(
1072 "/org/freedesktop/DBus",
1073 "org.freedesktop.DBus",
1076 log_error("Failed to allocate initial NameAcquired message: %s", strerror(-r));
1080 r = sd_bus_message_append(n, "s", a->unique_name);
1082 log_error("Failed to append unique name to NameAcquired message: %s", strerror(-r));
1086 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1088 log_error("Failed to append sender to NameAcquired message: %s", strerror(-r));
1092 r = bus_seal_synthetic_message(b, n);
1094 log_error("Failed to seal NameAcquired message: %s", strerror(-r));
1098 r = sd_bus_send(b, n, NULL);
1100 log_error("Failed to send NameAcquired message: %s", strerror(-r));
1107 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1108 char **well_known = NULL;
1118 /* We will change the sender of messages from the bus driver
1119 * so that they originate from the bus driver. This is a
1120 * speciality originating from dbus1, where the bus driver did
1121 * not have a unique id, but only the well-known name. */
1123 c = sd_bus_message_get_creds(m);
1127 r = sd_bus_creds_get_well_known_names(c, &well_known);
1131 if (strv_contains(well_known, "org.freedesktop.DBus"))
1132 m->sender = "org.freedesktop.DBus";
1137 int main(int argc, char *argv[]) {
1139 _cleanup_bus_creds_unref_ sd_bus_creds *bus_creds = NULL;
1140 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1141 sd_id128_t server_id;
1142 int r, in_fd, out_fd;
1143 bool got_hello = false;
1145 struct ucred ucred = {};
1146 _cleanup_free_ char *peersec = NULL;
1149 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1150 log_parse_environment();
1153 r = parse_argv(argc, argv);
1157 r = policy_load(&policy, arg_configuration);
1159 log_error("Failed to load policy: %s", strerror(-r));
1163 /* policy_dump(&policy); */
1165 r = sd_listen_fds(0);
1167 in_fd = STDIN_FILENO;
1168 out_fd = STDOUT_FILENO;
1169 } else if (r == 1) {
1170 in_fd = SD_LISTEN_FDS_START;
1171 out_fd = SD_LISTEN_FDS_START;
1173 log_error("Illegal number of file descriptors passed");
1178 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1179 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1182 (void) getpeercred(in_fd, &ucred);
1183 (void) getpeersec(in_fd, &peersec);
1186 if (arg_drop_privileges) {
1187 const char *user = "systemd-bus-proxy";
1191 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1193 log_error("Cannot resolve user name %s: %s", user, strerror(-r));
1197 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1202 names_hash = hashmap_new(&string_hash_ops);
1210 log_error("Failed to allocate bus: %s", strerror(-r));
1214 r = sd_bus_set_description(a, "sd-proxy");
1216 log_error("Failed to set bus name: %s", strerror(-r));
1220 r = sd_bus_set_address(a, arg_address);
1222 log_error("Failed to set address to connect to: %s", strerror(-r));
1226 r = sd_bus_negotiate_fds(a, is_unix);
1228 log_error("Failed to set FD negotiation: %s", strerror(-r));
1232 if (ucred.pid > 0) {
1233 a->fake_creds.pid = ucred.pid;
1234 a->fake_creds.uid = ucred.uid;
1235 a->fake_creds.gid = ucred.gid;
1236 a->fake_creds_valid = true;
1240 a->fake_label = peersec;
1244 a->manual_peer_interface = true;
1246 r = sd_bus_start(a);
1248 log_error("Failed to start bus client: %s", strerror(-r));
1252 r = sd_bus_get_owner_id(a, &server_id);
1254 log_error("Failed to get server ID: %s", strerror(-r));
1258 r = sd_bus_get_owner_creds(a, SD_BUS_CREDS_UID, &bus_creds);
1260 log_error("Failed to get bus creds: %s", strerror(-r));
1266 log_error("Failed to allocate bus: %s", strerror(-r));
1270 r = sd_bus_set_fd(b, in_fd, out_fd);
1272 log_error("Failed to set fds: %s", strerror(-r));
1276 r = sd_bus_set_server(b, 1, server_id);
1278 log_error("Failed to set server mode: %s", strerror(-r));
1282 r = sd_bus_negotiate_fds(b, is_unix);
1284 log_error("Failed to set FD negotiation: %s", strerror(-r));
1288 r = sd_bus_set_anonymous(b, true);
1290 log_error("Failed to set anonymous authentication: %s", strerror(-r));
1294 b->manual_peer_interface = true;
1296 r = sd_bus_start(b);
1298 log_error("Failed to start bus client: %s", strerror(-r));
1302 r = rename_service(a, b);
1304 log_debug("Failed to rename process: %s", strerror(-r));
1307 _cleanup_free_ char *match = NULL;
1310 r = sd_bus_get_unique_name(a, &unique);
1312 log_error("Failed to get unique name: %s", strerror(-r));
1316 match = strjoin("type='signal',"
1317 "sender='org.freedesktop.DBus',"
1318 "path='/org/freedesktop/DBus',"
1319 "interface='org.freedesktop.DBus',"
1320 "member='NameOwnerChanged',"
1330 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1332 log_error("Failed to add match for NameLost: %s", strerror(-r));
1337 match = strjoin("type='signal',"
1338 "sender='org.freedesktop.DBus',"
1339 "path='/org/freedesktop/DBus',"
1340 "interface='org.freedesktop.DBus',"
1341 "member='NameOwnerChanged',"
1351 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1353 log_error("Failed to add match for NameAcquired: %s", strerror(-r));
1359 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1360 int events_a, events_b, fd;
1361 uint64_t timeout_a, timeout_b, t;
1362 struct timespec _ts, *ts;
1363 struct pollfd *pollfd;
1367 r = sd_bus_process(a, &m);
1369 /* treat 'connection reset by peer' as clean exit condition */
1370 if (r == -ECONNRESET)
1373 log_error("Failed to process bus a: %s", strerror(-r));
1379 /* We officially got EOF, let's quit */
1380 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1385 k = synthesize_name_acquired(a, b, m);
1388 log_error("Failed to synthesize message: %s", strerror(-r));
1394 k = sd_bus_send(b, m, NULL);
1396 if (k == -ECONNRESET)
1400 log_error("Failed to send message: %s", strerror(-r));
1411 r = sd_bus_process(b, &m);
1413 /* treat 'connection reset by peer' as clean exit condition */
1414 if (r == -ECONNRESET)
1417 log_error("Failed to process bus b: %s", strerror(-r));
1426 assert_se(sd_bus_creds_get_uid(bus_creds, &uid) == 0);
1428 if (uid == 0 || uid != ucred.uid)
1431 /* We officially got EOF, let's quit */
1432 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1437 k = process_hello(a, b, m, p, &ucred, &got_hello);
1440 log_error("Failed to process HELLO: %s", strerror(-r));
1447 k = process_driver(a, b, m, p, &ucred);
1450 log_error("Failed to process driver calls: %s", strerror(-r));
1457 k = process_policy(a, b, m, &policy, &ucred);
1460 log_error("Failed to process policy: %s", strerror(-r));
1464 k = sd_bus_send(a, m, NULL);
1466 if (k == -ECONNRESET)
1470 k = process_policy(a, b, m, p, &ucred);
1473 log_error("Failed to send message: %s", strerror(-r));
1485 fd = sd_bus_get_fd(a);
1487 log_error("Failed to get fd: %s", strerror(-r));
1491 events_a = sd_bus_get_events(a);
1493 log_error("Failed to get events mask: %s", strerror(-r));
1497 r = sd_bus_get_timeout(a, &timeout_a);
1499 log_error("Failed to get timeout: %s", strerror(-r));
1503 events_b = sd_bus_get_events(b);
1505 log_error("Failed to get events mask: %s", strerror(-r));
1509 r = sd_bus_get_timeout(b, &timeout_b);
1511 log_error("Failed to get timeout: %s", strerror(-r));
1516 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1519 if (t == (uint64_t) -1)
1524 nw = now(CLOCK_MONOTONIC);
1530 ts = timespec_store(&_ts, t);
1533 pollfd = (struct pollfd[3]) {
1534 {.fd = fd, .events = events_a, },
1535 {.fd = in_fd, .events = events_b & POLLIN, },
1536 {.fd = out_fd, .events = events_b & POLLOUT, }
1539 r = ppoll(pollfd, 3, ts, NULL);
1541 log_error("ppoll() failed: %m");
1549 "STATUS=Shutting down.");
1551 policy_free(&policy);
1552 strv_free(arg_configuration);
1553 hashmap_free(names_hash);
1556 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;