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) {
480 /* The message came from the kernel, and is sent to our legacy client. */
481 r = sd_bus_creds_get_well_known_names(&m->creds, &names_strv);
486 if (!policy_check_recv(policy, ucred, names_hash, m->header->type, m->path, m->interface, m->member))
489 if (!policy_check_send(policy, ucred, names_strv, m->header->type, m->path, m->interface, m->member))
502 static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred) {
512 if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
515 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
516 if (0 && !isempty(sd_bus_message_get_signature(m, true))) {
517 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
519 r = sd_bus_error_setf(&error, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters");
521 return synthetic_reply_method_errno(m, r, &error);
524 return synthetic_reply_method_return(m, "s",
525 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
526 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
528 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
529 " <method name=\"Introspect\">\n"
530 " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
533 " <interface name=\"org.freedesktop.DBus\">\n"
534 " <method name=\"AddMatch\">\n"
535 " <arg type=\"s\" direction=\"in\"/>\n"
537 " <method name=\"RemoveMatch\">\n"
538 " <arg type=\"s\" direction=\"in\"/>\n"
540 " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
541 " <arg type=\"s\" direction=\"in\"/>\n"
542 " <arg type=\"ay\" direction=\"out\"/>\n"
544 " <method name=\"GetConnectionUnixProcessID\">\n"
545 " <arg type=\"s\" direction=\"in\"/>\n"
546 " <arg type=\"u\" direction=\"out\"/>\n"
548 " <method name=\"GetConnectionUnixUser\">\n"
549 " <arg type=\"s\" direction=\"in\"/>\n"
550 " <arg type=\"u\" direction=\"out\"/>\n"
552 " <method name=\"GetId\">\n"
553 " <arg type=\"s\" direction=\"out\"/>\n"
555 " <method name=\"GetNameOwner\">\n"
556 " <arg type=\"s\" direction=\"in\"/>\n"
557 " <arg type=\"s\" direction=\"out\"/>\n"
559 " <method name=\"Hello\">\n"
560 " <arg type=\"s\" direction=\"out\"/>\n"
562 " <method name=\"ListActivatableNames\">\n"
563 " <arg type=\"as\" direction=\"out\"/>\n"
565 " <method name=\"ListNames\">\n"
566 " <arg type=\"as\" direction=\"out\"/>\n"
568 " <method name=\"ListQueuedOwners\">\n"
569 " <arg type=\"s\" direction=\"in\"/>\n"
570 " <arg type=\"as\" direction=\"out\"/>\n"
572 " <method name=\"NameHasOwner\">\n"
573 " <arg type=\"s\" direction=\"in\"/>\n"
574 " <arg type=\"b\" direction=\"out\"/>\n"
576 " <method name=\"ReleaseName\">\n"
577 " <arg type=\"s\" direction=\"in\"/>\n"
578 " <arg type=\"u\" direction=\"out\"/>\n"
580 " <method name=\"ReloadConfig\">\n"
582 " <method name=\"RequestName\">\n"
583 " <arg type=\"s\" direction=\"in\"/>\n"
584 " <arg type=\"u\" direction=\"in\"/>\n"
585 " <arg type=\"u\" direction=\"out\"/>\n"
587 " <method name=\"StartServiceByName\">\n"
588 " <arg type=\"s\" direction=\"in\"/>\n"
589 " <arg type=\"u\" direction=\"in\"/>\n"
590 " <arg type=\"u\" direction=\"out\"/>\n"
592 " <method name=\"UpdateActivationEnvironment\">\n"
593 " <arg type=\"a{ss}\" direction=\"in\"/>\n"
595 " <signal name=\"NameAcquired\">\n"
596 " <arg type=\"s\"/>\n"
598 " <signal name=\"NameLost\">\n"
599 " <arg type=\"s\"/>\n"
601 " <signal name=\"NameOwnerChanged\">\n"
602 " <arg type=\"s\"/>\n"
603 " <arg type=\"s\"/>\n"
604 " <arg type=\"s\"/>\n"
609 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
612 r = sd_bus_message_read(m, "s", &match);
614 return synthetic_reply_method_errno(m, r, NULL);
616 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
618 return synthetic_reply_method_errno(m, r, NULL);
620 return synthetic_reply_method_return(m, NULL);
622 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
625 r = sd_bus_message_read(m, "s", &match);
627 return synthetic_reply_method_errno(m, r, NULL);
629 r = bus_remove_match_by_string(a, match, NULL, NULL);
631 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
633 return synthetic_reply_method_errno(m, r, NULL);
635 return synthetic_reply_method_return(m, NULL);
637 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
638 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
639 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
641 r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
643 return synthetic_reply_method_errno(m, r, &error);
645 return synthetic_reply_method_return(m, "y", creds->label, strlen(creds->label));
647 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
648 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
649 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
651 r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error);
653 return synthetic_reply_method_errno(m, r, &error);
655 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
657 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
658 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
659 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
661 r = get_creds_by_message(a, m, SD_BUS_CREDS_UID, &creds, &error);
663 return synthetic_reply_method_errno(m, r, &error);
665 return synthetic_reply_method_return(m, "u", (uint32_t) creds->uid);
667 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
668 sd_id128_t server_id;
669 char buf[SD_ID128_STRING_MAX];
671 r = sd_bus_get_owner_id(a, &server_id);
673 return synthetic_reply_method_errno(m, r, NULL);
675 return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
677 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
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 = sd_bus_message_read(m, "s", &name);
684 return synthetic_reply_method_errno(m, r, NULL);
686 if (streq(name, "org.freedesktop.DBus"))
687 return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
689 r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
691 return synthetic_reply_method_errno(m, r, &error);
693 return synthetic_reply_method_return(m, "s", creds->unique_name);
695 /* "Hello" is handled in process_hello() */
697 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
698 _cleanup_strv_free_ char **names = NULL;
700 r = sd_bus_list_names(a, NULL, &names);
702 return synthetic_reply_method_errno(m, r, NULL);
704 /* Let's sort the names list to make it stable */
707 return synthetic_reply_return_strv(m, names);
709 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
710 _cleanup_strv_free_ char **names = NULL;
712 r = sd_bus_list_names(a, &names, NULL);
714 return synthetic_reply_method_errno(m, r, NULL);
716 r = strv_extend(&names, "org.freedesktop.DBus");
718 return synthetic_reply_method_errno(m, r, NULL);
720 /* Let's sort the names list to make it stable */
723 return synthetic_reply_return_strv(m, names);
725 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
726 struct kdbus_cmd_name_list cmd = {};
727 struct kdbus_name_list *name_list;
728 struct kdbus_cmd_free cmd_free;
729 struct kdbus_name_info *name;
730 _cleanup_strv_free_ char **owners = NULL;
731 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
735 r = sd_bus_message_read(m, "s", &arg0);
737 return synthetic_reply_method_errno(m, r, NULL);
739 if (!service_name_is_valid(arg0))
740 return synthetic_reply_method_errno(m, -EINVAL, NULL);
742 r = sd_bus_get_name_creds(a, arg0, 0, NULL);
743 if (r == -ESRCH || r == -ENXIO) {
744 sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0);
745 return synthetic_reply_method_errno(m, r, &error);
748 return synthetic_reply_method_errno(m, r, NULL);
750 cmd.flags = KDBUS_NAME_LIST_QUEUED;
751 r = ioctl(a->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
753 return synthetic_reply_method_errno(m, -errno, NULL);
755 name_list = (struct kdbus_name_list *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
757 KDBUS_ITEM_FOREACH(name, name_list, names) {
758 const char *entry_name = NULL;
759 struct kdbus_item *item;
762 KDBUS_ITEM_FOREACH(item, name, items)
763 if (item->type == KDBUS_ITEM_OWNED_NAME)
764 entry_name = item->name.name;
766 if (!streq_ptr(entry_name, arg0))
769 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
774 r = strv_consume(&owners, n);
782 cmd_free.offset = cmd.offset;
784 r = ioctl(a->input_fd, KDBUS_CMD_FREE, &cmd_free);
786 return synthetic_reply_method_errno(m, r, NULL);
789 return synthetic_reply_method_errno(m, err, NULL);
791 return synthetic_reply_return_strv(m, owners);
793 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
796 r = sd_bus_message_read(m, "s", &name);
798 return synthetic_reply_method_errno(m, r, NULL);
800 if (!service_name_is_valid(name))
801 return synthetic_reply_method_errno(m, -EINVAL, NULL);
803 if (streq(name, "org.freedesktop.DBus"))
804 return synthetic_reply_method_return(m, "b", true);
806 r = sd_bus_get_name_creds(a, name, 0, NULL);
807 if (r < 0 && r != -ESRCH && r != -ENXIO)
808 return synthetic_reply_method_errno(m, r, NULL);
810 return synthetic_reply_method_return(m, "b", r >= 0);
812 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
815 r = sd_bus_message_read(m, "s", &name);
817 return synthetic_reply_method_errno(m, r, NULL);
819 if (!service_name_is_valid(name))
820 return synthetic_reply_method_errno(m, -EINVAL, NULL);
822 r = sd_bus_release_name(a, name);
825 return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
826 if (r == -EADDRINUSE)
827 return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
829 return synthetic_reply_method_errno(m, r, NULL);
832 hashmap_remove(names_hash, name);
834 return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
836 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
837 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
839 r = sd_bus_error_setf(&error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
841 return synthetic_reply_method_errno(m, r, &error);
843 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
845 uint32_t flags, param;
848 r = sd_bus_message_read(m, "su", &name, &flags);
850 return synthetic_reply_method_errno(m, r, NULL);
852 if (!policy_check_own(policy, ucred, name))
853 return synthetic_reply_method_errno(m, -EPERM, NULL);
855 if (!service_name_is_valid(name))
856 return synthetic_reply_method_errno(m, -EINVAL, NULL);
857 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
858 return synthetic_reply_method_errno(m, -EINVAL, NULL);
861 if (flags & BUS_NAME_ALLOW_REPLACEMENT)
862 param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
863 if (flags & BUS_NAME_REPLACE_EXISTING)
864 param |= SD_BUS_NAME_REPLACE_EXISTING;
865 if (!(flags & BUS_NAME_DO_NOT_QUEUE))
866 param |= SD_BUS_NAME_QUEUE;
868 r = sd_bus_request_name(a, name, param);
871 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
873 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
874 return synthetic_reply_method_errno(m, r, NULL);
879 r = hashmap_put(names_hash, name, NULL);
881 return synthetic_reply_method_errno(m, r, NULL);
884 return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
886 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
888 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
889 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
893 r = sd_bus_message_read(m, "su", &name, &flags);
895 return synthetic_reply_method_errno(m, r, NULL);
897 if (!service_name_is_valid(name))
898 return synthetic_reply_method_errno(m, -EINVAL, NULL);
900 return synthetic_reply_method_errno(m, -EINVAL, NULL);
902 r = sd_bus_get_name_creds(a, name, 0, NULL);
903 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
904 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
906 return synthetic_reply_method_errno(m, r, NULL);
908 r = sd_bus_message_new_method_call(
913 "org.freedesktop.DBus.Peer",
916 return synthetic_reply_method_errno(m, r, NULL);
918 r = sd_bus_send(a, msg, NULL);
920 return synthetic_reply_method_errno(m, r, NULL);
922 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
924 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
925 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
926 _cleanup_strv_free_ char **args = NULL;
928 if (!peer_is_privileged(a, m))
929 return synthetic_reply_method_errno(m, -EPERM, NULL);
931 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
933 return synthetic_reply_method_errno(m, r, NULL);
935 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
936 _cleanup_free_ char *s = NULL;
940 r = sd_bus_message_read(m, "ss", &key, &value);
942 return synthetic_reply_method_errno(m, r, NULL);
944 s = strjoin(key, "=", value, NULL);
946 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
948 r = strv_extend(&args, s);
950 return synthetic_reply_method_errno(m, r, NULL);
952 r = sd_bus_message_exit_container(m);
954 return synthetic_reply_method_errno(m, r, NULL);
957 r = sd_bus_message_exit_container(m);
959 return synthetic_reply_method_errno(m, r, NULL);
962 return synthetic_reply_method_errno(m, -EINVAL, NULL);
964 r = sd_bus_message_new_method_call(
967 "org.freedesktop.systemd1",
968 "/org/freedesktop/systemd1",
969 "org.freedesktop.systemd1.Manager",
972 return synthetic_reply_method_errno(m, r, NULL);
974 r = sd_bus_message_append_strv(msg, args);
976 return synthetic_reply_method_errno(m, r, NULL);
978 r = sd_bus_call(a, msg, 0, NULL, NULL);
980 return synthetic_reply_method_errno(m, r, NULL);
982 return synthetic_reply_method_return(m, NULL);
985 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
987 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
989 return synthetic_reply_method_errno(m, r, &error);
993 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred, bool *got_hello) {
994 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
1003 /* As reaction to hello we need to respond with two messages:
1004 * the callback reply and the NameAcquired for the unique
1005 * name, since hello is otherwise obsolete on kdbus. */
1008 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1009 streq_ptr(m->destination, "org.freedesktop.DBus");
1016 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1021 log_error("Got duplicate hello, aborting.");
1025 if (!policy_check_hello(policy, ucred)) {
1026 log_error("Policy denied HELLO");
1035 r = sd_bus_message_new_method_return(m, &n);
1037 log_error("Failed to generate HELLO reply: %s", strerror(-r));
1041 r = sd_bus_message_append(n, "s", a->unique_name);
1043 log_error("Failed to append unique name to HELLO reply: %s", strerror(-r));
1047 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1049 log_error("Failed to append sender to HELLO reply: %s", strerror(-r));
1053 r = bus_seal_synthetic_message(b, n);
1055 log_error("Failed to seal HELLO reply: %s", strerror(-r));
1059 r = sd_bus_send(b, n, NULL);
1061 log_error("Failed to send HELLO reply: %s", strerror(-r));
1065 n = sd_bus_message_unref(n);
1066 r = sd_bus_message_new_signal(
1069 "/org/freedesktop/DBus",
1070 "org.freedesktop.DBus",
1073 log_error("Failed to allocate initial NameAcquired message: %s", strerror(-r));
1077 r = sd_bus_message_append(n, "s", a->unique_name);
1079 log_error("Failed to append unique name to NameAcquired message: %s", strerror(-r));
1083 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1085 log_error("Failed to append sender to NameAcquired message: %s", strerror(-r));
1089 r = bus_seal_synthetic_message(b, n);
1091 log_error("Failed to seal NameAcquired message: %s", strerror(-r));
1095 r = sd_bus_send(b, n, NULL);
1097 log_error("Failed to send NameAcquired message: %s", strerror(-r));
1104 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1105 char **well_known = NULL;
1115 /* We will change the sender of messages from the bus driver
1116 * so that they originate from the bus driver. This is a
1117 * speciality originating from dbus1, where the bus driver did
1118 * not have a unique id, but only the well-known name. */
1120 c = sd_bus_message_get_creds(m);
1124 r = sd_bus_creds_get_well_known_names(c, &well_known);
1128 if (strv_contains(well_known, "org.freedesktop.DBus"))
1129 m->sender = "org.freedesktop.DBus";
1134 int main(int argc, char *argv[]) {
1136 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1137 sd_id128_t server_id;
1138 int r, in_fd, out_fd;
1139 bool got_hello = false;
1141 struct ucred ucred = {};
1142 _cleanup_free_ char *peersec = NULL;
1145 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1146 log_parse_environment();
1149 r = parse_argv(argc, argv);
1153 r = policy_load(&policy, arg_configuration);
1155 log_error("Failed to load policy: %s", strerror(-r));
1159 /* policy_dump(&policy); */
1161 r = sd_listen_fds(0);
1163 in_fd = STDIN_FILENO;
1164 out_fd = STDOUT_FILENO;
1165 } else if (r == 1) {
1166 in_fd = SD_LISTEN_FDS_START;
1167 out_fd = SD_LISTEN_FDS_START;
1169 log_error("Illegal number of file descriptors passed");
1174 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1175 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1178 (void) getpeercred(in_fd, &ucred);
1179 (void) getpeersec(in_fd, &peersec);
1182 if (arg_drop_privileges) {
1183 const char *user = "systemd-bus-proxy";
1187 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1189 log_error("Cannot resolve user name %s: %s", user, strerror(-r));
1193 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1198 names_hash = hashmap_new(&string_hash_ops);
1206 log_error("Failed to allocate bus: %s", strerror(-r));
1210 r = sd_bus_set_description(a, "sd-proxy");
1212 log_error("Failed to set bus name: %s", strerror(-r));
1216 r = sd_bus_set_address(a, arg_address);
1218 log_error("Failed to set address to connect to: %s", strerror(-r));
1222 r = sd_bus_negotiate_fds(a, is_unix);
1224 log_error("Failed to set FD negotiation: %s", strerror(-r));
1228 if (ucred.pid > 0) {
1229 a->fake_creds.pid = ucred.pid;
1230 a->fake_creds.uid = ucred.uid;
1231 a->fake_creds.gid = ucred.gid;
1232 a->fake_creds_valid = true;
1236 a->fake_label = peersec;
1240 a->manual_peer_interface = true;
1242 r = sd_bus_start(a);
1244 log_error("Failed to start bus client: %s", strerror(-r));
1248 r = sd_bus_get_owner_id(a, &server_id);
1250 log_error("Failed to get server ID: %s", strerror(-r));
1256 log_error("Failed to allocate bus: %s", strerror(-r));
1260 r = sd_bus_set_fd(b, in_fd, out_fd);
1262 log_error("Failed to set fds: %s", strerror(-r));
1266 r = sd_bus_set_server(b, 1, server_id);
1268 log_error("Failed to set server mode: %s", strerror(-r));
1272 r = sd_bus_negotiate_fds(b, is_unix);
1274 log_error("Failed to set FD negotiation: %s", strerror(-r));
1278 r = sd_bus_set_anonymous(b, true);
1280 log_error("Failed to set anonymous authentication: %s", strerror(-r));
1284 b->manual_peer_interface = true;
1286 r = sd_bus_start(b);
1288 log_error("Failed to start bus client: %s", strerror(-r));
1292 r = rename_service(a, b);
1294 log_debug("Failed to rename process: %s", strerror(-r));
1297 _cleanup_free_ char *match = NULL;
1300 r = sd_bus_get_unique_name(a, &unique);
1302 log_error("Failed to get unique name: %s", strerror(-r));
1306 match = strjoin("type='signal',"
1307 "sender='org.freedesktop.DBus',"
1308 "path='/org/freedesktop/DBus',"
1309 "interface='org.freedesktop.DBus',"
1310 "member='NameOwnerChanged',"
1320 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1322 log_error("Failed to add match for NameLost: %s", strerror(-r));
1327 match = strjoin("type='signal',"
1328 "sender='org.freedesktop.DBus',"
1329 "path='/org/freedesktop/DBus',"
1330 "interface='org.freedesktop.DBus',"
1331 "member='NameOwnerChanged',"
1341 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1343 log_error("Failed to add match for NameAcquired: %s", strerror(-r));
1349 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1350 int events_a, events_b, fd;
1351 uint64_t timeout_a, timeout_b, t;
1352 struct timespec _ts, *ts;
1353 struct pollfd *pollfd;
1357 r = sd_bus_process(a, &m);
1359 /* treat 'connection reset by peer' as clean exit condition */
1360 if (r == -ECONNRESET)
1363 log_error("Failed to process bus a: %s", strerror(-r));
1369 /* We officially got EOF, let's quit */
1370 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1375 k = synthesize_name_acquired(a, b, m);
1378 log_error("Failed to synthesize message: %s", strerror(-r));
1384 k = sd_bus_send(b, m, NULL);
1386 if (k == -ECONNRESET)
1390 log_error("Failed to send message: %s", strerror(-r));
1401 r = sd_bus_process(b, &m);
1403 /* treat 'connection reset by peer' as clean exit condition */
1404 if (r == -ECONNRESET)
1407 log_error("Failed to process bus b: %s", strerror(-r));
1413 /* We officially got EOF, let's quit */
1414 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1419 k = process_hello(a, b, m, &policy, &ucred, &got_hello);
1422 log_error("Failed to process HELLO: %s", strerror(-r));
1429 k = process_driver(a, b, m, &policy, &ucred);
1432 log_error("Failed to process driver calls: %s", strerror(-r));
1439 k = process_policy(a, b, m, &policy, &ucred);
1442 log_error("Failed to process policy: %s", strerror(-r));
1446 k = sd_bus_send(a, m, NULL);
1448 if (k == -ECONNRESET)
1452 log_error("Failed to send message: %s", strerror(-r));
1464 fd = sd_bus_get_fd(a);
1466 log_error("Failed to get fd: %s", strerror(-r));
1470 events_a = sd_bus_get_events(a);
1472 log_error("Failed to get events mask: %s", strerror(-r));
1476 r = sd_bus_get_timeout(a, &timeout_a);
1478 log_error("Failed to get timeout: %s", strerror(-r));
1482 events_b = sd_bus_get_events(b);
1484 log_error("Failed to get events mask: %s", strerror(-r));
1488 r = sd_bus_get_timeout(b, &timeout_b);
1490 log_error("Failed to get timeout: %s", strerror(-r));
1495 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1498 if (t == (uint64_t) -1)
1503 nw = now(CLOCK_MONOTONIC);
1509 ts = timespec_store(&_ts, t);
1512 pollfd = (struct pollfd[3]) {
1513 {.fd = fd, .events = events_a, },
1514 {.fd = in_fd, .events = events_b & POLLIN, },
1515 {.fd = out_fd, .events = events_b & POLLOUT, }
1518 r = ppoll(pollfd, 3, ts, NULL);
1520 log_error("ppoll() failed: %m");
1528 "STATUS=Shutting down.");
1530 policy_free(&policy);
1531 strv_free(arg_configuration);
1532 hashmap_free(names_hash);
1535 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;