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 process_policy(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred) {
451 bool granted = false;
463 /* The message came from the kernel, and is sent to our legacy client. */
464 r = sd_bus_creds_get_well_known_names(&m->creds, &names_strv);
468 STRV_FOREACH(name, names_strv) {
469 if (policy_check_send(policy, ucred, m->header->type, *name, m->path, m->interface, m->member)) {
470 r = free_and_strdup(&m->destination_ptr, *name);
487 HASHMAP_FOREACH(name, names_hash, i) {
488 if (policy_check_recv(policy, ucred, m->header->type, *name, m->path, m->interface, m->member))
494 sd_bus_creds *bus_creds;
496 /* The message came from the legacy client, and is sent to kdbus. */
497 r = sd_bus_get_name_creds(a, m->destination, SD_BUS_CREDS_WELL_KNOWN_NAMES, &bus_creds);
501 STRV_FOREACH(name, names_strv) {
502 if (policy_check_send(policy, ucred, m->header->type, *name, m->path, m->interface, m->member)) {
503 r = free_and_strdup(&m->destination_ptr, *name);
507 r = bus_kernel_parse_unique_name(m->sender, &m->verify_destination_id);
524 HASHMAP_FOREACH(name, names_hash, i) {
525 if (policy_check_recv(policy, ucred, m->header->type, *name, m->path, m->interface, m->member))
535 static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred) {
545 if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
548 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
549 if (0 && !isempty(sd_bus_message_get_signature(m, true))) {
550 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
552 r = sd_bus_error_setf(&error, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters");
554 return synthetic_reply_method_errno(m, r, &error);
557 return synthetic_reply_method_return(m, "s",
558 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
559 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
561 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
562 " <method name=\"Introspect\">\n"
563 " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
566 " <interface name=\"org.freedesktop.DBus\">\n"
567 " <method name=\"AddMatch\">\n"
568 " <arg type=\"s\" direction=\"in\"/>\n"
570 " <method name=\"RemoveMatch\">\n"
571 " <arg type=\"s\" direction=\"in\"/>\n"
573 " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
574 " <arg type=\"s\" direction=\"in\"/>\n"
575 " <arg type=\"ay\" direction=\"out\"/>\n"
577 " <method name=\"GetConnectionUnixProcessID\">\n"
578 " <arg type=\"s\" direction=\"in\"/>\n"
579 " <arg type=\"u\" direction=\"out\"/>\n"
581 " <method name=\"GetConnectionUnixUser\">\n"
582 " <arg type=\"s\" direction=\"in\"/>\n"
583 " <arg type=\"u\" direction=\"out\"/>\n"
585 " <method name=\"GetId\">\n"
586 " <arg type=\"s\" direction=\"out\"/>\n"
588 " <method name=\"GetNameOwner\">\n"
589 " <arg type=\"s\" direction=\"in\"/>\n"
590 " <arg type=\"s\" direction=\"out\"/>\n"
592 " <method name=\"Hello\">\n"
593 " <arg type=\"s\" direction=\"out\"/>\n"
595 " <method name=\"ListActivatableNames\">\n"
596 " <arg type=\"as\" direction=\"out\"/>\n"
598 " <method name=\"ListNames\">\n"
599 " <arg type=\"as\" direction=\"out\"/>\n"
601 " <method name=\"ListQueuedOwners\">\n"
602 " <arg type=\"s\" direction=\"in\"/>\n"
603 " <arg type=\"as\" direction=\"out\"/>\n"
605 " <method name=\"NameHasOwner\">\n"
606 " <arg type=\"s\" direction=\"in\"/>\n"
607 " <arg type=\"b\" direction=\"out\"/>\n"
609 " <method name=\"ReleaseName\">\n"
610 " <arg type=\"s\" direction=\"in\"/>\n"
611 " <arg type=\"u\" direction=\"out\"/>\n"
613 " <method name=\"ReloadConfig\">\n"
615 " <method name=\"RequestName\">\n"
616 " <arg type=\"s\" direction=\"in\"/>\n"
617 " <arg type=\"u\" direction=\"in\"/>\n"
618 " <arg type=\"u\" direction=\"out\"/>\n"
620 " <method name=\"StartServiceByName\">\n"
621 " <arg type=\"s\" direction=\"in\"/>\n"
622 " <arg type=\"u\" direction=\"in\"/>\n"
623 " <arg type=\"u\" direction=\"out\"/>\n"
625 " <method name=\"UpdateActivationEnvironment\">\n"
626 " <arg type=\"a{ss}\" direction=\"in\"/>\n"
628 " <signal name=\"NameAcquired\">\n"
629 " <arg type=\"s\"/>\n"
631 " <signal name=\"NameLost\">\n"
632 " <arg type=\"s\"/>\n"
634 " <signal name=\"NameOwnerChanged\">\n"
635 " <arg type=\"s\"/>\n"
636 " <arg type=\"s\"/>\n"
637 " <arg type=\"s\"/>\n"
642 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
645 r = sd_bus_message_read(m, "s", &match);
647 return synthetic_reply_method_errno(m, r, NULL);
649 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
651 return synthetic_reply_method_errno(m, r, NULL);
653 return synthetic_reply_method_return(m, NULL);
655 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
658 r = sd_bus_message_read(m, "s", &match);
660 return synthetic_reply_method_errno(m, r, NULL);
662 r = bus_remove_match_by_string(a, match, NULL, NULL);
664 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
666 return synthetic_reply_method_errno(m, r, NULL);
668 return synthetic_reply_method_return(m, NULL);
670 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
671 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
672 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
674 r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
676 return synthetic_reply_method_errno(m, r, &error);
678 return synthetic_reply_method_return(m, "y", creds->label, strlen(creds->label));
680 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
681 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
682 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
684 r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error);
686 return synthetic_reply_method_errno(m, r, &error);
688 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
690 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
691 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
692 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
694 r = get_creds_by_message(a, m, SD_BUS_CREDS_UID, &creds, &error);
696 return synthetic_reply_method_errno(m, r, &error);
698 return synthetic_reply_method_return(m, "u", (uint32_t) creds->uid);
700 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
701 sd_id128_t server_id;
702 char buf[SD_ID128_STRING_MAX];
704 r = sd_bus_get_owner_id(a, &server_id);
706 return synthetic_reply_method_errno(m, r, NULL);
708 return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
710 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
712 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
713 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
715 r = sd_bus_message_read(m, "s", &name);
717 return synthetic_reply_method_errno(m, r, NULL);
719 if (streq(name, "org.freedesktop.DBus"))
720 return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
722 r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
724 return synthetic_reply_method_errno(m, r, &error);
726 return synthetic_reply_method_return(m, "s", creds->unique_name);
728 /* "Hello" is handled in process_hello() */
730 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
731 _cleanup_strv_free_ char **names = NULL;
733 r = sd_bus_list_names(a, NULL, &names);
735 return synthetic_reply_method_errno(m, r, NULL);
737 /* Let's sort the names list to make it stable */
740 return synthetic_reply_return_strv(m, names);
742 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
743 _cleanup_strv_free_ char **names = NULL;
745 r = sd_bus_list_names(a, &names, NULL);
747 return synthetic_reply_method_errno(m, r, NULL);
749 r = strv_extend(&names, "org.freedesktop.DBus");
751 return synthetic_reply_method_errno(m, r, NULL);
753 /* Let's sort the names list to make it stable */
756 return synthetic_reply_return_strv(m, names);
758 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
759 struct kdbus_cmd_name_list cmd = {};
760 struct kdbus_name_list *name_list;
761 struct kdbus_cmd_free cmd_free;
762 struct kdbus_name_info *name;
763 _cleanup_strv_free_ char **owners = NULL;
764 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
768 r = sd_bus_message_read(m, "s", &arg0);
770 return synthetic_reply_method_errno(m, r, NULL);
772 if (!service_name_is_valid(arg0))
773 return synthetic_reply_method_errno(m, -EINVAL, NULL);
775 r = sd_bus_get_name_creds(a, arg0, 0, NULL);
776 if (r == -ESRCH || r == -ENXIO) {
777 sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0);
778 return synthetic_reply_method_errno(m, r, &error);
781 return synthetic_reply_method_errno(m, r, NULL);
783 cmd.flags = KDBUS_NAME_LIST_QUEUED;
784 r = ioctl(a->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
786 return synthetic_reply_method_errno(m, -errno, NULL);
788 name_list = (struct kdbus_name_list *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
790 KDBUS_ITEM_FOREACH(name, name_list, names) {
791 const char *entry_name = NULL;
792 struct kdbus_item *item;
795 KDBUS_ITEM_FOREACH(item, name, items)
796 if (item->type == KDBUS_ITEM_OWNED_NAME)
797 entry_name = item->name.name;
799 if (!streq_ptr(entry_name, arg0))
802 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
807 r = strv_consume(&owners, n);
815 cmd_free.offset = cmd.offset;
817 r = ioctl(a->input_fd, KDBUS_CMD_FREE, &cmd_free);
819 return synthetic_reply_method_errno(m, r, NULL);
822 return synthetic_reply_method_errno(m, err, NULL);
824 return synthetic_reply_return_strv(m, owners);
826 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
829 r = sd_bus_message_read(m, "s", &name);
831 return synthetic_reply_method_errno(m, r, NULL);
833 if (!service_name_is_valid(name))
834 return synthetic_reply_method_errno(m, -EINVAL, NULL);
836 if (streq(name, "org.freedesktop.DBus"))
837 return synthetic_reply_method_return(m, "b", true);
839 r = sd_bus_get_name_creds(a, name, 0, NULL);
840 if (r < 0 && r != -ESRCH && r != -ENXIO)
841 return synthetic_reply_method_errno(m, r, NULL);
843 return synthetic_reply_method_return(m, "b", r >= 0);
845 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
848 r = sd_bus_message_read(m, "s", &name);
850 return synthetic_reply_method_errno(m, r, NULL);
852 if (!service_name_is_valid(name))
853 return synthetic_reply_method_errno(m, -EINVAL, NULL);
855 r = sd_bus_release_name(a, name);
858 return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
859 if (r == -EADDRINUSE)
860 return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
862 return synthetic_reply_method_errno(m, r, NULL);
865 hashmap_remove(names_hash, name);
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;
881 r = sd_bus_message_read(m, "su", &name, &flags);
883 return synthetic_reply_method_errno(m, r, NULL);
885 if (policy && !policy_check_own(policy, ucred, name))
886 return synthetic_reply_method_errno(m, -EPERM, NULL);
888 if (!service_name_is_valid(name))
889 return synthetic_reply_method_errno(m, -EINVAL, NULL);
890 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
891 return synthetic_reply_method_errno(m, -EINVAL, NULL);
894 if (flags & BUS_NAME_ALLOW_REPLACEMENT)
895 param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
896 if (flags & BUS_NAME_REPLACE_EXISTING)
897 param |= SD_BUS_NAME_REPLACE_EXISTING;
898 if (!(flags & BUS_NAME_DO_NOT_QUEUE))
899 param |= SD_BUS_NAME_QUEUE;
901 r = sd_bus_request_name(a, name, param);
904 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
906 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
907 return synthetic_reply_method_errno(m, r, NULL);
912 r = hashmap_put(names_hash, name, NULL);
914 return synthetic_reply_method_errno(m, r, NULL);
917 return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
919 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
921 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
922 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
926 r = sd_bus_message_read(m, "su", &name, &flags);
928 return synthetic_reply_method_errno(m, r, NULL);
930 if (!service_name_is_valid(name))
931 return synthetic_reply_method_errno(m, -EINVAL, NULL);
933 return synthetic_reply_method_errno(m, -EINVAL, NULL);
935 r = sd_bus_get_name_creds(a, name, 0, NULL);
936 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
937 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
939 return synthetic_reply_method_errno(m, r, NULL);
941 r = sd_bus_message_new_method_call(
946 "org.freedesktop.DBus.Peer",
949 return synthetic_reply_method_errno(m, r, NULL);
951 r = sd_bus_send(a, msg, NULL);
953 return synthetic_reply_method_errno(m, r, NULL);
955 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
957 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
958 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
959 _cleanup_strv_free_ char **args = NULL;
961 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
963 return synthetic_reply_method_errno(m, r, NULL);
965 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
966 _cleanup_free_ char *s = NULL;
970 r = sd_bus_message_read(m, "ss", &key, &value);
972 return synthetic_reply_method_errno(m, r, NULL);
974 s = strjoin(key, "=", value, NULL);
976 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
978 r = strv_extend(&args, s);
980 return synthetic_reply_method_errno(m, r, NULL);
982 r = sd_bus_message_exit_container(m);
984 return synthetic_reply_method_errno(m, r, NULL);
987 r = sd_bus_message_exit_container(m);
989 return synthetic_reply_method_errno(m, r, NULL);
992 return synthetic_reply_method_errno(m, -EINVAL, NULL);
994 r = sd_bus_message_new_method_call(
997 "org.freedesktop.systemd1",
998 "/org/freedesktop/systemd1",
999 "org.freedesktop.systemd1.Manager",
1002 return synthetic_reply_method_errno(m, r, NULL);
1004 r = sd_bus_message_append_strv(msg, args);
1006 return synthetic_reply_method_errno(m, r, NULL);
1008 r = sd_bus_call(a, msg, 0, NULL, NULL);
1010 return synthetic_reply_method_errno(m, r, NULL);
1012 return synthetic_reply_method_return(m, NULL);
1015 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1017 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
1019 return synthetic_reply_method_errno(m, r, &error);
1023 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred, bool *got_hello) {
1024 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
1033 /* As reaction to hello we need to respond with two messages:
1034 * the callback reply and the NameAcquired for the unique
1035 * name, since hello is otherwise obsolete on kdbus. */
1038 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1039 streq_ptr(m->destination, "org.freedesktop.DBus");
1046 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1051 log_error("Got duplicate hello, aborting.");
1055 if (policy && !policy_check_hello(policy, ucred)) {
1056 log_error("Policy denied HELLO");
1065 r = sd_bus_message_new_method_return(m, &n);
1067 log_error("Failed to generate HELLO reply: %s", strerror(-r));
1071 r = sd_bus_message_append(n, "s", a->unique_name);
1073 log_error("Failed to append unique name to HELLO reply: %s", strerror(-r));
1077 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1079 log_error("Failed to append sender to HELLO reply: %s", strerror(-r));
1083 r = bus_seal_synthetic_message(b, n);
1085 log_error("Failed to seal HELLO reply: %s", strerror(-r));
1089 r = sd_bus_send(b, n, NULL);
1091 log_error("Failed to send HELLO reply: %s", strerror(-r));
1095 n = sd_bus_message_unref(n);
1096 r = sd_bus_message_new_signal(
1099 "/org/freedesktop/DBus",
1100 "org.freedesktop.DBus",
1103 log_error("Failed to allocate initial NameAcquired message: %s", strerror(-r));
1107 r = sd_bus_message_append(n, "s", a->unique_name);
1109 log_error("Failed to append unique name to NameAcquired message: %s", strerror(-r));
1113 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1115 log_error("Failed to append sender to NameAcquired message: %s", strerror(-r));
1119 r = bus_seal_synthetic_message(b, n);
1121 log_error("Failed to seal NameAcquired message: %s", strerror(-r));
1125 r = sd_bus_send(b, n, NULL);
1127 log_error("Failed to send NameAcquired message: %s", strerror(-r));
1134 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1135 char **well_known = NULL;
1145 /* We will change the sender of messages from the bus driver
1146 * so that they originate from the bus driver. This is a
1147 * speciality originating from dbus1, where the bus driver did
1148 * not have a unique id, but only the well-known name. */
1150 c = sd_bus_message_get_creds(m);
1154 r = sd_bus_creds_get_well_known_names(c, &well_known);
1158 if (strv_contains(well_known, "org.freedesktop.DBus"))
1159 m->sender = "org.freedesktop.DBus";
1164 int main(int argc, char *argv[]) {
1166 _cleanup_bus_creds_unref_ sd_bus_creds *bus_creds = NULL;
1167 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1168 sd_id128_t server_id;
1169 int r, in_fd, out_fd;
1170 bool got_hello = false;
1172 struct ucred ucred = {};
1173 _cleanup_free_ char *peersec = NULL;
1176 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1177 log_parse_environment();
1180 r = parse_argv(argc, argv);
1184 r = policy_load(&policy, arg_configuration);
1186 log_error("Failed to load policy: %s", strerror(-r));
1190 /* policy_dump(&policy); */
1192 r = sd_listen_fds(0);
1194 in_fd = STDIN_FILENO;
1195 out_fd = STDOUT_FILENO;
1196 } else if (r == 1) {
1197 in_fd = SD_LISTEN_FDS_START;
1198 out_fd = SD_LISTEN_FDS_START;
1200 log_error("Illegal number of file descriptors passed");
1205 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1206 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1209 (void) getpeercred(in_fd, &ucred);
1210 (void) getpeersec(in_fd, &peersec);
1213 if (arg_drop_privileges) {
1214 const char *user = "systemd-bus-proxy";
1218 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1220 log_error("Cannot resolve user name %s: %s", user, strerror(-r));
1224 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1229 names_hash = hashmap_new(&string_hash_ops);
1237 log_error("Failed to allocate bus: %s", strerror(-r));
1241 r = sd_bus_set_description(a, "sd-proxy");
1243 log_error("Failed to set bus name: %s", strerror(-r));
1247 r = sd_bus_set_address(a, arg_address);
1249 log_error("Failed to set address to connect to: %s", strerror(-r));
1253 r = sd_bus_negotiate_fds(a, is_unix);
1255 log_error("Failed to set FD negotiation: %s", strerror(-r));
1259 if (ucred.pid > 0) {
1260 a->fake_creds.pid = ucred.pid;
1261 a->fake_creds.uid = ucred.uid;
1262 a->fake_creds.gid = ucred.gid;
1263 a->fake_creds_valid = true;
1267 a->fake_label = peersec;
1271 a->manual_peer_interface = true;
1273 r = sd_bus_start(a);
1275 log_error("Failed to start bus client: %s", strerror(-r));
1279 r = sd_bus_get_owner_id(a, &server_id);
1281 log_error("Failed to get server ID: %s", strerror(-r));
1285 r = sd_bus_get_owner_creds(a, SD_BUS_CREDS_UID, &bus_creds);
1287 log_error("Failed to get bus creds: %s", strerror(-r));
1293 log_error("Failed to allocate bus: %s", strerror(-r));
1297 r = sd_bus_set_fd(b, in_fd, out_fd);
1299 log_error("Failed to set fds: %s", strerror(-r));
1303 r = sd_bus_set_server(b, 1, server_id);
1305 log_error("Failed to set server mode: %s", strerror(-r));
1309 r = sd_bus_negotiate_fds(b, is_unix);
1311 log_error("Failed to set FD negotiation: %s", strerror(-r));
1315 r = sd_bus_set_anonymous(b, true);
1317 log_error("Failed to set anonymous authentication: %s", strerror(-r));
1321 b->manual_peer_interface = true;
1323 r = sd_bus_start(b);
1325 log_error("Failed to start bus client: %s", strerror(-r));
1329 r = rename_service(a, b);
1331 log_debug("Failed to rename process: %s", strerror(-r));
1334 _cleanup_free_ char *match = NULL;
1337 r = sd_bus_get_unique_name(a, &unique);
1339 log_error("Failed to get unique name: %s", strerror(-r));
1343 match = strjoin("type='signal',"
1344 "sender='org.freedesktop.DBus',"
1345 "path='/org/freedesktop/DBus',"
1346 "interface='org.freedesktop.DBus',"
1347 "member='NameOwnerChanged',"
1357 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1359 log_error("Failed to add match for NameLost: %s", strerror(-r));
1364 match = strjoin("type='signal',"
1365 "sender='org.freedesktop.DBus',"
1366 "path='/org/freedesktop/DBus',"
1367 "interface='org.freedesktop.DBus',"
1368 "member='NameOwnerChanged',"
1378 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1380 log_error("Failed to add match for NameAcquired: %s", strerror(-r));
1386 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1387 int events_a, events_b, fd;
1388 uint64_t timeout_a, timeout_b, t;
1389 struct timespec _ts, *ts;
1390 struct pollfd *pollfd;
1394 r = sd_bus_process(a, &m);
1396 /* treat 'connection reset by peer' as clean exit condition */
1397 if (r == -ECONNRESET)
1400 log_error("Failed to process bus a: %s", strerror(-r));
1406 /* We officially got EOF, let's quit */
1407 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1412 k = synthesize_name_acquired(a, b, m);
1415 log_error("Failed to synthesize message: %s", strerror(-r));
1421 k = sd_bus_send(b, m, NULL);
1423 if (k == -ECONNRESET)
1427 log_error("Failed to send message: %s", strerror(-r));
1438 r = sd_bus_process(b, &m);
1440 /* treat 'connection reset by peer' as clean exit condition */
1441 if (r == -ECONNRESET)
1444 log_error("Failed to process bus b: %s", strerror(-r));
1453 assert_se(sd_bus_creds_get_uid(bus_creds, &uid) == 0);
1456 if (uid == 0 || uid != ucred.uid)
1460 /* We officially got EOF, let's quit */
1461 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1466 k = process_hello(a, b, m, p, &ucred, &got_hello);
1469 log_error("Failed to process HELLO: %s", strerror(-r));
1476 k = process_driver(a, b, m, p, &ucred);
1479 log_error("Failed to process driver calls: %s", strerror(-r));
1491 k = process_policy(a, b, m, p, &ucred);
1494 log_error("Failed to process policy: %s", strerror(-r));
1498 k = sd_bus_send(a, m, NULL);
1500 if (k == -ECONNRESET)
1502 else if (k == -EREMCHG)
1506 log_error("Failed to send message: %s", strerror(-r));
1520 fd = sd_bus_get_fd(a);
1522 log_error("Failed to get fd: %s", strerror(-r));
1526 events_a = sd_bus_get_events(a);
1528 log_error("Failed to get events mask: %s", strerror(-r));
1532 r = sd_bus_get_timeout(a, &timeout_a);
1534 log_error("Failed to get timeout: %s", strerror(-r));
1538 events_b = sd_bus_get_events(b);
1540 log_error("Failed to get events mask: %s", strerror(-r));
1544 r = sd_bus_get_timeout(b, &timeout_b);
1546 log_error("Failed to get timeout: %s", strerror(-r));
1551 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1554 if (t == (uint64_t) -1)
1559 nw = now(CLOCK_MONOTONIC);
1565 ts = timespec_store(&_ts, t);
1568 pollfd = (struct pollfd[3]) {
1569 {.fd = fd, .events = events_a, },
1570 {.fd = in_fd, .events = events_b & POLLIN, },
1571 {.fd = out_fd, .events = events_b & POLLOUT, }
1574 r = ppoll(pollfd, 3, ts, NULL);
1576 log_error("ppoll() failed: %m");
1584 "STATUS=Shutting down.");
1586 policy_free(&policy);
1587 strv_free(arg_configuration);
1588 hashmap_free(names_hash);
1591 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;