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 r = sd_bus_get_name_creds(bus, name, mask, &c);
416 if (r == -ESRCH || r == -ENXIO)
417 return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
421 if ((c->mask & mask) != mask)
430 static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
438 r = sd_bus_message_read(m, "s", &name);
442 return get_creds_by_name(bus, name, mask, _creds, error);
445 static int process_policy(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred) {
449 bool granted = false;
461 /* The message came from the kernel, and is sent to our legacy client. */
462 r = sd_bus_creds_get_well_known_names(&m->creds, &names_strv);
466 STRV_FOREACH(name, names_strv) {
467 if (policy_check_send(policy, ucred, m->header->type, *name, m->path, m->interface, m->member)) {
468 r = free_and_strdup(&m->destination_ptr, *name);
485 HASHMAP_FOREACH(name, names_hash, i) {
486 if (policy_check_recv(policy, ucred, m->header->type, *name, m->path, m->interface, m->member))
492 sd_bus_creds *bus_creds;
494 /* The message came from the legacy client, and is sent to kdbus. */
495 r = sd_bus_get_name_creds(a, m->destination, SD_BUS_CREDS_WELL_KNOWN_NAMES, &bus_creds);
499 STRV_FOREACH(name, names_strv) {
500 if (policy_check_send(policy, ucred, m->header->type, *name, m->path, m->interface, m->member)) {
501 r = free_and_strdup(&m->destination_ptr, *name);
505 r = bus_kernel_parse_unique_name(m->sender, &m->verify_destination_id);
522 HASHMAP_FOREACH(name, names_hash, i) {
523 if (policy_check_recv(policy, ucred, m->header->type, *name, m->path, m->interface, m->member))
533 static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred) {
543 if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
546 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
547 if (0 && !isempty(sd_bus_message_get_signature(m, true))) {
548 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
550 r = sd_bus_error_setf(&error, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters");
552 return synthetic_reply_method_errno(m, r, &error);
555 return synthetic_reply_method_return(m, "s",
556 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
557 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
559 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
560 " <method name=\"Introspect\">\n"
561 " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
564 " <interface name=\"org.freedesktop.DBus\">\n"
565 " <method name=\"AddMatch\">\n"
566 " <arg type=\"s\" direction=\"in\"/>\n"
568 " <method name=\"RemoveMatch\">\n"
569 " <arg type=\"s\" direction=\"in\"/>\n"
571 " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
572 " <arg type=\"s\" direction=\"in\"/>\n"
573 " <arg type=\"ay\" direction=\"out\"/>\n"
575 " <method name=\"GetConnectionUnixProcessID\">\n"
576 " <arg type=\"s\" direction=\"in\"/>\n"
577 " <arg type=\"u\" direction=\"out\"/>\n"
579 " <method name=\"GetConnectionUnixUser\">\n"
580 " <arg type=\"s\" direction=\"in\"/>\n"
581 " <arg type=\"u\" direction=\"out\"/>\n"
583 " <method name=\"GetId\">\n"
584 " <arg type=\"s\" direction=\"out\"/>\n"
586 " <method name=\"GetNameOwner\">\n"
587 " <arg type=\"s\" direction=\"in\"/>\n"
588 " <arg type=\"s\" direction=\"out\"/>\n"
590 " <method name=\"Hello\">\n"
591 " <arg type=\"s\" direction=\"out\"/>\n"
593 " <method name=\"ListActivatableNames\">\n"
594 " <arg type=\"as\" direction=\"out\"/>\n"
596 " <method name=\"ListNames\">\n"
597 " <arg type=\"as\" direction=\"out\"/>\n"
599 " <method name=\"ListQueuedOwners\">\n"
600 " <arg type=\"s\" direction=\"in\"/>\n"
601 " <arg type=\"as\" direction=\"out\"/>\n"
603 " <method name=\"NameHasOwner\">\n"
604 " <arg type=\"s\" direction=\"in\"/>\n"
605 " <arg type=\"b\" direction=\"out\"/>\n"
607 " <method name=\"ReleaseName\">\n"
608 " <arg type=\"s\" direction=\"in\"/>\n"
609 " <arg type=\"u\" direction=\"out\"/>\n"
611 " <method name=\"ReloadConfig\">\n"
613 " <method name=\"RequestName\">\n"
614 " <arg type=\"s\" direction=\"in\"/>\n"
615 " <arg type=\"u\" direction=\"in\"/>\n"
616 " <arg type=\"u\" direction=\"out\"/>\n"
618 " <method name=\"StartServiceByName\">\n"
619 " <arg type=\"s\" direction=\"in\"/>\n"
620 " <arg type=\"u\" direction=\"in\"/>\n"
621 " <arg type=\"u\" direction=\"out\"/>\n"
623 " <method name=\"UpdateActivationEnvironment\">\n"
624 " <arg type=\"a{ss}\" direction=\"in\"/>\n"
626 " <signal name=\"NameAcquired\">\n"
627 " <arg type=\"s\"/>\n"
629 " <signal name=\"NameLost\">\n"
630 " <arg type=\"s\"/>\n"
632 " <signal name=\"NameOwnerChanged\">\n"
633 " <arg type=\"s\"/>\n"
634 " <arg type=\"s\"/>\n"
635 " <arg type=\"s\"/>\n"
640 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
643 r = sd_bus_message_read(m, "s", &match);
645 return synthetic_reply_method_errno(m, r, NULL);
647 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
649 return synthetic_reply_method_errno(m, r, NULL);
651 return synthetic_reply_method_return(m, NULL);
653 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
656 r = sd_bus_message_read(m, "s", &match);
658 return synthetic_reply_method_errno(m, r, NULL);
660 r = bus_remove_match_by_string(a, match, NULL, NULL);
662 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
664 return synthetic_reply_method_errno(m, r, NULL);
666 return synthetic_reply_method_return(m, NULL);
668 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
669 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
670 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
672 r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
674 return synthetic_reply_method_errno(m, r, &error);
676 return synthetic_reply_method_return(m, "y", creds->label, strlen(creds->label));
678 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
679 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
680 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
682 r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error);
684 return synthetic_reply_method_errno(m, r, &error);
686 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
688 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
689 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
690 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
692 r = get_creds_by_message(a, m, SD_BUS_CREDS_UID, &creds, &error);
694 return synthetic_reply_method_errno(m, r, &error);
696 return synthetic_reply_method_return(m, "u", (uint32_t) creds->uid);
698 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
699 sd_id128_t server_id;
700 char buf[SD_ID128_STRING_MAX];
702 r = sd_bus_get_owner_id(a, &server_id);
704 return synthetic_reply_method_errno(m, r, NULL);
706 return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
708 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
710 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
711 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
713 r = sd_bus_message_read(m, "s", &name);
715 return synthetic_reply_method_errno(m, r, NULL);
717 if (streq(name, "org.freedesktop.DBus"))
718 return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
720 r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
722 return synthetic_reply_method_errno(m, r, &error);
724 return synthetic_reply_method_return(m, "s", creds->unique_name);
726 /* "Hello" is handled in process_hello() */
728 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
729 _cleanup_strv_free_ char **names = NULL;
731 r = sd_bus_list_names(a, NULL, &names);
733 return synthetic_reply_method_errno(m, r, NULL);
735 /* Let's sort the names list to make it stable */
738 return synthetic_reply_return_strv(m, names);
740 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
741 _cleanup_strv_free_ char **names = NULL;
743 r = sd_bus_list_names(a, &names, NULL);
745 return synthetic_reply_method_errno(m, r, NULL);
747 r = strv_extend(&names, "org.freedesktop.DBus");
749 return synthetic_reply_method_errno(m, r, NULL);
751 /* Let's sort the names list to make it stable */
754 return synthetic_reply_return_strv(m, names);
756 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
757 struct kdbus_cmd_name_list cmd = {};
758 struct kdbus_name_list *name_list;
759 struct kdbus_cmd_free cmd_free;
760 struct kdbus_name_info *name;
761 _cleanup_strv_free_ char **owners = NULL;
762 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
766 r = sd_bus_message_read(m, "s", &arg0);
768 return synthetic_reply_method_errno(m, r, NULL);
770 r = sd_bus_get_name_creds(a, arg0, 0, NULL);
771 if (r == -ESRCH || r == -ENXIO) {
772 sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0);
773 return synthetic_reply_method_errno(m, r, &error);
776 return synthetic_reply_method_errno(m, r, NULL);
778 cmd.flags = KDBUS_NAME_LIST_QUEUED;
779 r = ioctl(a->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
781 return synthetic_reply_method_errno(m, -errno, NULL);
783 name_list = (struct kdbus_name_list *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
785 KDBUS_ITEM_FOREACH(name, name_list, names) {
786 const char *entry_name = NULL;
787 struct kdbus_item *item;
790 KDBUS_ITEM_FOREACH(item, name, items)
791 if (item->type == KDBUS_ITEM_OWNED_NAME)
792 entry_name = item->name.name;
794 if (!streq_ptr(entry_name, arg0))
797 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
802 r = strv_consume(&owners, n);
810 cmd_free.offset = cmd.offset;
812 r = ioctl(a->input_fd, KDBUS_CMD_FREE, &cmd_free);
814 return synthetic_reply_method_errno(m, r, NULL);
817 return synthetic_reply_method_errno(m, err, NULL);
819 return synthetic_reply_return_strv(m, owners);
821 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
824 r = sd_bus_message_read(m, "s", &name);
826 return synthetic_reply_method_errno(m, r, NULL);
828 if (streq(name, "org.freedesktop.DBus"))
829 return synthetic_reply_method_return(m, "b", true);
831 r = sd_bus_get_name_creds(a, name, 0, NULL);
832 if (r < 0 && r != -ESRCH && r != -ENXIO)
833 return synthetic_reply_method_errno(m, r, NULL);
835 return synthetic_reply_method_return(m, "b", r >= 0);
837 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
840 r = sd_bus_message_read(m, "s", &name);
842 return synthetic_reply_method_errno(m, r, NULL);
844 r = sd_bus_release_name(a, name);
847 return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
848 if (r == -EADDRINUSE)
849 return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
851 return synthetic_reply_method_errno(m, r, NULL);
854 hashmap_remove(names_hash, name);
856 return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
858 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
859 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
861 r = sd_bus_error_setf(&error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
863 return synthetic_reply_method_errno(m, r, &error);
865 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
867 uint32_t flags, param;
870 r = sd_bus_message_read(m, "su", &name, &flags);
872 return synthetic_reply_method_errno(m, r, NULL);
874 if (policy && !policy_check_own(policy, ucred, name))
875 return synthetic_reply_method_errno(m, -EPERM, NULL);
877 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
878 return synthetic_reply_method_errno(m, -EINVAL, NULL);
881 if (flags & BUS_NAME_ALLOW_REPLACEMENT)
882 param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
883 if (flags & BUS_NAME_REPLACE_EXISTING)
884 param |= SD_BUS_NAME_REPLACE_EXISTING;
885 if (!(flags & BUS_NAME_DO_NOT_QUEUE))
886 param |= SD_BUS_NAME_QUEUE;
888 r = sd_bus_request_name(a, name, param);
891 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
893 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
894 return synthetic_reply_method_errno(m, r, NULL);
899 r = hashmap_put(names_hash, name, NULL);
901 return synthetic_reply_method_errno(m, r, NULL);
904 return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
906 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
908 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
909 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
913 r = sd_bus_message_read(m, "su", &name, &flags);
915 return synthetic_reply_method_errno(m, r, NULL);
918 return synthetic_reply_method_errno(m, -EINVAL, NULL);
920 r = sd_bus_get_name_creds(a, name, 0, NULL);
921 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
922 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
924 return synthetic_reply_method_errno(m, r, NULL);
926 r = sd_bus_message_new_method_call(
931 "org.freedesktop.DBus.Peer",
934 return synthetic_reply_method_errno(m, r, NULL);
936 r = sd_bus_send(a, msg, NULL);
938 return synthetic_reply_method_errno(m, r, NULL);
940 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
942 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
943 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
944 _cleanup_strv_free_ char **args = NULL;
946 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
948 return synthetic_reply_method_errno(m, r, NULL);
950 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
951 _cleanup_free_ char *s = NULL;
955 r = sd_bus_message_read(m, "ss", &key, &value);
957 return synthetic_reply_method_errno(m, r, NULL);
959 s = strjoin(key, "=", value, NULL);
961 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
963 r = strv_extend(&args, s);
965 return synthetic_reply_method_errno(m, r, NULL);
967 r = sd_bus_message_exit_container(m);
969 return synthetic_reply_method_errno(m, r, NULL);
972 r = sd_bus_message_exit_container(m);
974 return synthetic_reply_method_errno(m, r, NULL);
977 return synthetic_reply_method_errno(m, -EINVAL, NULL);
979 r = sd_bus_message_new_method_call(
982 "org.freedesktop.systemd1",
983 "/org/freedesktop/systemd1",
984 "org.freedesktop.systemd1.Manager",
987 return synthetic_reply_method_errno(m, r, NULL);
989 r = sd_bus_message_append_strv(msg, args);
991 return synthetic_reply_method_errno(m, r, NULL);
993 r = sd_bus_call(a, msg, 0, NULL, NULL);
995 return synthetic_reply_method_errno(m, r, NULL);
997 return synthetic_reply_method_return(m, NULL);
1000 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1002 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
1004 return synthetic_reply_method_errno(m, r, &error);
1008 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred, bool *got_hello) {
1009 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
1018 /* As reaction to hello we need to respond with two messages:
1019 * the callback reply and the NameAcquired for the unique
1020 * name, since hello is otherwise obsolete on kdbus. */
1023 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1024 streq_ptr(m->destination, "org.freedesktop.DBus");
1031 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1036 log_error("Got duplicate hello, aborting.");
1040 if (policy && !policy_check_hello(policy, ucred)) {
1041 log_error("Policy denied HELLO");
1050 r = sd_bus_message_new_method_return(m, &n);
1052 log_error("Failed to generate HELLO reply: %s", strerror(-r));
1056 r = sd_bus_message_append(n, "s", a->unique_name);
1058 log_error("Failed to append unique name to HELLO reply: %s", strerror(-r));
1062 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1064 log_error("Failed to append sender to HELLO reply: %s", strerror(-r));
1068 r = bus_seal_synthetic_message(b, n);
1070 log_error("Failed to seal HELLO reply: %s", strerror(-r));
1074 r = sd_bus_send(b, n, NULL);
1076 log_error("Failed to send HELLO reply: %s", strerror(-r));
1080 n = sd_bus_message_unref(n);
1081 r = sd_bus_message_new_signal(
1084 "/org/freedesktop/DBus",
1085 "org.freedesktop.DBus",
1088 log_error("Failed to allocate initial NameAcquired message: %s", strerror(-r));
1092 r = sd_bus_message_append(n, "s", a->unique_name);
1094 log_error("Failed to append unique name to NameAcquired message: %s", strerror(-r));
1098 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1100 log_error("Failed to append sender to NameAcquired message: %s", strerror(-r));
1104 r = bus_seal_synthetic_message(b, n);
1106 log_error("Failed to seal NameAcquired message: %s", strerror(-r));
1110 r = sd_bus_send(b, n, NULL);
1112 log_error("Failed to send NameAcquired message: %s", strerror(-r));
1119 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1120 char **well_known = NULL;
1130 /* We will change the sender of messages from the bus driver
1131 * so that they originate from the bus driver. This is a
1132 * speciality originating from dbus1, where the bus driver did
1133 * not have a unique id, but only the well-known name. */
1135 c = sd_bus_message_get_creds(m);
1139 r = sd_bus_creds_get_well_known_names(c, &well_known);
1143 if (strv_contains(well_known, "org.freedesktop.DBus"))
1144 m->sender = "org.freedesktop.DBus";
1149 int main(int argc, char *argv[]) {
1151 _cleanup_bus_creds_unref_ sd_bus_creds *bus_creds = NULL;
1152 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1153 sd_id128_t server_id;
1154 int r, in_fd, out_fd;
1155 bool got_hello = false;
1157 struct ucred ucred = {};
1158 _cleanup_free_ char *peersec = NULL;
1161 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1162 log_parse_environment();
1165 r = parse_argv(argc, argv);
1169 r = policy_load(&policy, arg_configuration);
1171 log_error("Failed to load policy: %s", strerror(-r));
1175 /* policy_dump(&policy); */
1177 r = sd_listen_fds(0);
1179 in_fd = STDIN_FILENO;
1180 out_fd = STDOUT_FILENO;
1181 } else if (r == 1) {
1182 in_fd = SD_LISTEN_FDS_START;
1183 out_fd = SD_LISTEN_FDS_START;
1185 log_error("Illegal number of file descriptors passed");
1190 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1191 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1194 (void) getpeercred(in_fd, &ucred);
1195 (void) getpeersec(in_fd, &peersec);
1198 if (arg_drop_privileges) {
1199 const char *user = "systemd-bus-proxy";
1203 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1205 log_error("Cannot resolve user name %s: %s", user, strerror(-r));
1209 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1214 names_hash = hashmap_new(&string_hash_ops);
1222 log_error("Failed to allocate bus: %s", strerror(-r));
1226 r = sd_bus_set_description(a, "sd-proxy");
1228 log_error("Failed to set bus name: %s", strerror(-r));
1232 r = sd_bus_set_address(a, arg_address);
1234 log_error("Failed to set address to connect to: %s", strerror(-r));
1238 r = sd_bus_negotiate_fds(a, is_unix);
1240 log_error("Failed to set FD negotiation: %s", strerror(-r));
1244 if (ucred.pid > 0) {
1245 a->fake_pids.pid = ucred.pid;
1246 a->fake_pids_valid = true;
1248 a->fake_creds.uid = ucred.uid;
1249 a->fake_creds.euid = (uid_t) -1;
1250 a->fake_creds.suid = (uid_t) -1;
1251 a->fake_creds.fsuid = (uid_t) -1;
1252 a->fake_creds.gid = ucred.gid;
1253 a->fake_creds.egid = (gid_t) -1;
1254 a->fake_creds.sgid = (gid_t) -1;
1255 a->fake_creds.fsgid = (gid_t) -1;
1256 a->fake_creds_valid = true;
1260 a->fake_label = peersec;
1264 a->manual_peer_interface = true;
1266 r = sd_bus_start(a);
1268 log_error("Failed to start bus client: %s", strerror(-r));
1272 r = sd_bus_get_owner_id(a, &server_id);
1274 log_error("Failed to get server ID: %s", strerror(-r));
1278 r = sd_bus_get_owner_creds(a, SD_BUS_CREDS_UID, &bus_creds);
1280 log_error("Failed to get bus creds: %s", strerror(-r));
1286 log_error("Failed to allocate bus: %s", strerror(-r));
1290 r = sd_bus_set_fd(b, in_fd, out_fd);
1292 log_error("Failed to set fds: %s", strerror(-r));
1296 r = sd_bus_set_server(b, 1, server_id);
1298 log_error("Failed to set server mode: %s", strerror(-r));
1302 r = sd_bus_negotiate_fds(b, is_unix);
1304 log_error("Failed to set FD negotiation: %s", strerror(-r));
1308 r = sd_bus_set_anonymous(b, true);
1310 log_error("Failed to set anonymous authentication: %s", strerror(-r));
1314 b->manual_peer_interface = true;
1316 r = sd_bus_start(b);
1318 log_error("Failed to start bus client: %s", strerror(-r));
1322 r = rename_service(a, b);
1324 log_debug("Failed to rename process: %s", strerror(-r));
1327 _cleanup_free_ char *match = NULL;
1330 r = sd_bus_get_unique_name(a, &unique);
1332 log_error("Failed to get unique name: %s", strerror(-r));
1336 match = strjoin("type='signal',"
1337 "sender='org.freedesktop.DBus',"
1338 "path='/org/freedesktop/DBus',"
1339 "interface='org.freedesktop.DBus',"
1340 "member='NameOwnerChanged',"
1350 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1352 log_error("Failed to add match for NameLost: %s", strerror(-r));
1357 match = strjoin("type='signal',"
1358 "sender='org.freedesktop.DBus',"
1359 "path='/org/freedesktop/DBus',"
1360 "interface='org.freedesktop.DBus',"
1361 "member='NameOwnerChanged',"
1371 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1373 log_error("Failed to add match for NameAcquired: %s", strerror(-r));
1379 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1380 int events_a, events_b, fd;
1381 uint64_t timeout_a, timeout_b, t;
1382 struct timespec _ts, *ts;
1383 struct pollfd *pollfd;
1387 r = sd_bus_process(a, &m);
1389 /* treat 'connection reset by peer' as clean exit condition */
1390 if (r == -ECONNRESET)
1393 log_error("Failed to process bus a: %s", strerror(-r));
1399 /* We officially got EOF, let's quit */
1400 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1405 k = synthesize_name_acquired(a, b, m);
1408 log_error("Failed to synthesize message: %s", strerror(-r));
1414 k = sd_bus_send(b, m, NULL);
1416 if (k == -ECONNRESET)
1420 log_error("Failed to send message: %s", strerror(-r));
1431 r = sd_bus_process(b, &m);
1433 /* treat 'connection reset by peer' as clean exit condition */
1434 if (r == -ECONNRESET)
1437 log_error("Failed to process bus b: %s", strerror(-r));
1446 assert_se(sd_bus_creds_get_uid(bus_creds, &uid) == 0);
1449 if (uid == 0 || uid != ucred.uid)
1453 /* We officially got EOF, let's quit */
1454 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1459 k = process_hello(a, b, m, p, &ucred, &got_hello);
1462 log_error("Failed to process HELLO: %s", strerror(-r));
1469 k = process_driver(a, b, m, p, &ucred);
1472 log_error("Failed to process driver calls: %s", strerror(-r));
1484 k = process_policy(a, b, m, p, &ucred);
1487 log_error("Failed to process policy: %s", strerror(-r));
1491 k = sd_bus_send(a, m, NULL);
1493 if (k == -ECONNRESET)
1495 else if (k == -EREMCHG)
1499 log_error("Failed to send message: %s", strerror(-r));
1513 fd = sd_bus_get_fd(a);
1515 log_error("Failed to get fd: %s", strerror(-r));
1519 events_a = sd_bus_get_events(a);
1521 log_error("Failed to get events mask: %s", strerror(-r));
1525 r = sd_bus_get_timeout(a, &timeout_a);
1527 log_error("Failed to get timeout: %s", strerror(-r));
1531 events_b = sd_bus_get_events(b);
1533 log_error("Failed to get events mask: %s", strerror(-r));
1537 r = sd_bus_get_timeout(b, &timeout_b);
1539 log_error("Failed to get timeout: %s", strerror(-r));
1544 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1547 if (t == (uint64_t) -1)
1552 nw = now(CLOCK_MONOTONIC);
1558 ts = timespec_store(&_ts, t);
1561 pollfd = (struct pollfd[3]) {
1562 {.fd = fd, .events = events_a, },
1563 {.fd = in_fd, .events = events_b & POLLIN, },
1564 {.fd = out_fd, .events = events_b & POLLOUT, }
1567 r = ppoll(pollfd, 3, ts, NULL);
1569 log_error("ppoll() failed: %m");
1577 "STATUS=Shutting down.");
1579 policy_free(&policy);
1580 strv_free(arg_configuration);
1581 hashmap_free(names_hash);
1584 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;