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) {
481 r = sd_bus_creds_get_well_known_names(&m->creds, &names_strv);
485 if (!policy_check_recv(policy, ucred, names_hash, m->header->type, m->path, m->interface, m->member))
488 if (!policy_check_send(policy, ucred, names_strv, m->header->type, m->path, m->interface, m->member))
494 static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred) {
504 if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
507 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
508 if (0 && !isempty(sd_bus_message_get_signature(m, true))) {
509 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
511 r = sd_bus_error_setf(&error, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters");
513 return synthetic_reply_method_errno(m, r, &error);
516 return synthetic_reply_method_return(m, "s",
517 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
518 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
520 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
521 " <method name=\"Introspect\">\n"
522 " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
525 " <interface name=\"org.freedesktop.DBus\">\n"
526 " <method name=\"AddMatch\">\n"
527 " <arg type=\"s\" direction=\"in\"/>\n"
529 " <method name=\"RemoveMatch\">\n"
530 " <arg type=\"s\" direction=\"in\"/>\n"
532 " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
533 " <arg type=\"s\" direction=\"in\"/>\n"
534 " <arg type=\"ay\" direction=\"out\"/>\n"
536 " <method name=\"GetConnectionUnixProcessID\">\n"
537 " <arg type=\"s\" direction=\"in\"/>\n"
538 " <arg type=\"u\" direction=\"out\"/>\n"
540 " <method name=\"GetConnectionUnixUser\">\n"
541 " <arg type=\"s\" direction=\"in\"/>\n"
542 " <arg type=\"u\" direction=\"out\"/>\n"
544 " <method name=\"GetId\">\n"
545 " <arg type=\"s\" direction=\"out\"/>\n"
547 " <method name=\"GetNameOwner\">\n"
548 " <arg type=\"s\" direction=\"in\"/>\n"
549 " <arg type=\"s\" direction=\"out\"/>\n"
551 " <method name=\"Hello\">\n"
552 " <arg type=\"s\" direction=\"out\"/>\n"
554 " <method name=\"ListActivatableNames\">\n"
555 " <arg type=\"as\" direction=\"out\"/>\n"
557 " <method name=\"ListNames\">\n"
558 " <arg type=\"as\" direction=\"out\"/>\n"
560 " <method name=\"ListQueuedOwners\">\n"
561 " <arg type=\"s\" direction=\"in\"/>\n"
562 " <arg type=\"as\" direction=\"out\"/>\n"
564 " <method name=\"NameHasOwner\">\n"
565 " <arg type=\"s\" direction=\"in\"/>\n"
566 " <arg type=\"b\" direction=\"out\"/>\n"
568 " <method name=\"ReleaseName\">\n"
569 " <arg type=\"s\" direction=\"in\"/>\n"
570 " <arg type=\"u\" direction=\"out\"/>\n"
572 " <method name=\"ReloadConfig\">\n"
574 " <method name=\"RequestName\">\n"
575 " <arg type=\"s\" direction=\"in\"/>\n"
576 " <arg type=\"u\" direction=\"in\"/>\n"
577 " <arg type=\"u\" direction=\"out\"/>\n"
579 " <method name=\"StartServiceByName\">\n"
580 " <arg type=\"s\" direction=\"in\"/>\n"
581 " <arg type=\"u\" direction=\"in\"/>\n"
582 " <arg type=\"u\" direction=\"out\"/>\n"
584 " <method name=\"UpdateActivationEnvironment\">\n"
585 " <arg type=\"a{ss}\" direction=\"in\"/>\n"
587 " <signal name=\"NameAcquired\">\n"
588 " <arg type=\"s\"/>\n"
590 " <signal name=\"NameLost\">\n"
591 " <arg type=\"s\"/>\n"
593 " <signal name=\"NameOwnerChanged\">\n"
594 " <arg type=\"s\"/>\n"
595 " <arg type=\"s\"/>\n"
596 " <arg type=\"s\"/>\n"
601 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
604 r = sd_bus_message_read(m, "s", &match);
606 return synthetic_reply_method_errno(m, r, NULL);
608 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
610 return synthetic_reply_method_errno(m, r, NULL);
612 return synthetic_reply_method_return(m, NULL);
614 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
617 r = sd_bus_message_read(m, "s", &match);
619 return synthetic_reply_method_errno(m, r, NULL);
621 r = bus_remove_match_by_string(a, match, NULL, NULL);
623 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
625 return synthetic_reply_method_errno(m, r, NULL);
627 return synthetic_reply_method_return(m, NULL);
629 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
630 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
631 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
633 r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
635 return synthetic_reply_method_errno(m, r, &error);
637 return synthetic_reply_method_return(m, "y", creds->label, strlen(creds->label));
639 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
640 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
641 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
643 r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error);
645 return synthetic_reply_method_errno(m, r, &error);
647 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
649 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
650 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
651 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
653 r = get_creds_by_message(a, m, SD_BUS_CREDS_UID, &creds, &error);
655 return synthetic_reply_method_errno(m, r, &error);
657 return synthetic_reply_method_return(m, "u", (uint32_t) creds->uid);
659 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
660 sd_id128_t server_id;
661 char buf[SD_ID128_STRING_MAX];
663 r = sd_bus_get_owner_id(a, &server_id);
665 return synthetic_reply_method_errno(m, r, NULL);
667 return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
669 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
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 = sd_bus_message_read(m, "s", &name);
676 return synthetic_reply_method_errno(m, r, NULL);
678 if (streq(name, "org.freedesktop.DBus"))
679 return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
681 r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
683 return synthetic_reply_method_errno(m, r, &error);
685 return synthetic_reply_method_return(m, "s", creds->unique_name);
687 /* "Hello" is handled in process_hello() */
689 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
690 _cleanup_strv_free_ char **names = NULL;
692 r = sd_bus_list_names(a, NULL, &names);
694 return synthetic_reply_method_errno(m, r, NULL);
696 /* Let's sort the names list to make it stable */
699 return synthetic_reply_return_strv(m, names);
701 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
702 _cleanup_strv_free_ char **names = NULL;
704 r = sd_bus_list_names(a, &names, NULL);
706 return synthetic_reply_method_errno(m, r, NULL);
708 r = strv_extend(&names, "org.freedesktop.DBus");
710 return synthetic_reply_method_errno(m, r, NULL);
712 /* Let's sort the names list to make it stable */
715 return synthetic_reply_return_strv(m, names);
717 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
718 struct kdbus_cmd_name_list cmd = {};
719 struct kdbus_name_list *name_list;
720 struct kdbus_cmd_free cmd_free;
721 struct kdbus_name_info *name;
722 _cleanup_strv_free_ char **owners = NULL;
723 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
727 r = sd_bus_message_read(m, "s", &arg0);
729 return synthetic_reply_method_errno(m, r, NULL);
731 if (!service_name_is_valid(arg0))
732 return synthetic_reply_method_errno(m, -EINVAL, NULL);
734 r = sd_bus_get_name_creds(a, arg0, 0, NULL);
735 if (r == -ESRCH || r == -ENXIO) {
736 sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0);
737 return synthetic_reply_method_errno(m, r, &error);
740 return synthetic_reply_method_errno(m, r, NULL);
742 cmd.flags = KDBUS_NAME_LIST_QUEUED;
743 r = ioctl(a->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
745 return synthetic_reply_method_errno(m, -errno, NULL);
747 name_list = (struct kdbus_name_list *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
749 KDBUS_ITEM_FOREACH(name, name_list, names) {
750 const char *entry_name = NULL;
751 struct kdbus_item *item;
754 KDBUS_ITEM_FOREACH(item, name, items)
755 if (item->type == KDBUS_ITEM_OWNED_NAME)
756 entry_name = item->name.name;
758 if (!streq_ptr(entry_name, arg0))
761 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
766 r = strv_consume(&owners, n);
774 cmd_free.offset = cmd.offset;
776 r = ioctl(a->input_fd, KDBUS_CMD_FREE, &cmd_free);
778 return synthetic_reply_method_errno(m, r, NULL);
781 return synthetic_reply_method_errno(m, err, NULL);
783 return synthetic_reply_return_strv(m, owners);
785 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
788 r = sd_bus_message_read(m, "s", &name);
790 return synthetic_reply_method_errno(m, r, NULL);
792 if (!service_name_is_valid(name))
793 return synthetic_reply_method_errno(m, -EINVAL, NULL);
795 if (streq(name, "org.freedesktop.DBus"))
796 return synthetic_reply_method_return(m, "b", true);
798 r = sd_bus_get_name_creds(a, name, 0, NULL);
799 if (r < 0 && r != -ESRCH && r != -ENXIO)
800 return synthetic_reply_method_errno(m, r, NULL);
802 return synthetic_reply_method_return(m, "b", r >= 0);
804 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
807 r = sd_bus_message_read(m, "s", &name);
809 return synthetic_reply_method_errno(m, r, NULL);
811 if (!service_name_is_valid(name))
812 return synthetic_reply_method_errno(m, -EINVAL, NULL);
814 r = sd_bus_release_name(a, name);
817 return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
818 if (r == -EADDRINUSE)
819 return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
821 return synthetic_reply_method_errno(m, r, NULL);
824 hashmap_remove(names_hash, name);
826 return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
828 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
829 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
831 r = sd_bus_error_setf(&error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
833 return synthetic_reply_method_errno(m, r, &error);
835 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
837 uint32_t flags, param;
840 r = sd_bus_message_read(m, "su", &name, &flags);
842 return synthetic_reply_method_errno(m, r, NULL);
844 if (!policy_check_own(policy, ucred, name))
845 return synthetic_reply_method_errno(m, -EPERM, NULL);
847 if (!service_name_is_valid(name))
848 return synthetic_reply_method_errno(m, -EINVAL, NULL);
849 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
850 return synthetic_reply_method_errno(m, -EINVAL, NULL);
853 if (flags & BUS_NAME_ALLOW_REPLACEMENT)
854 param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
855 if (flags & BUS_NAME_REPLACE_EXISTING)
856 param |= SD_BUS_NAME_REPLACE_EXISTING;
857 if (!(flags & BUS_NAME_DO_NOT_QUEUE))
858 param |= SD_BUS_NAME_QUEUE;
860 r = sd_bus_request_name(a, name, param);
863 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
865 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
866 return synthetic_reply_method_errno(m, r, NULL);
871 r = hashmap_put(names_hash, name, NULL);
873 return synthetic_reply_method_errno(m, r, NULL);
876 return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
878 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
880 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
881 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
885 r = sd_bus_message_read(m, "su", &name, &flags);
887 return synthetic_reply_method_errno(m, r, NULL);
889 if (!service_name_is_valid(name))
890 return synthetic_reply_method_errno(m, -EINVAL, NULL);
892 return synthetic_reply_method_errno(m, -EINVAL, NULL);
894 r = sd_bus_get_name_creds(a, name, 0, NULL);
895 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
896 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
898 return synthetic_reply_method_errno(m, r, NULL);
900 r = sd_bus_message_new_method_call(
905 "org.freedesktop.DBus.Peer",
908 return synthetic_reply_method_errno(m, r, NULL);
910 r = sd_bus_send(a, msg, NULL);
912 return synthetic_reply_method_errno(m, r, NULL);
914 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
916 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
917 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
918 _cleanup_strv_free_ char **args = NULL;
920 if (!peer_is_privileged(a, m))
921 return synthetic_reply_method_errno(m, -EPERM, NULL);
923 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
925 return synthetic_reply_method_errno(m, r, NULL);
927 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
928 _cleanup_free_ char *s = NULL;
932 r = sd_bus_message_read(m, "ss", &key, &value);
934 return synthetic_reply_method_errno(m, r, NULL);
936 s = strjoin(key, "=", value, NULL);
938 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
940 r = strv_extend(&args, s);
942 return synthetic_reply_method_errno(m, r, NULL);
944 r = sd_bus_message_exit_container(m);
946 return synthetic_reply_method_errno(m, r, NULL);
949 r = sd_bus_message_exit_container(m);
951 return synthetic_reply_method_errno(m, r, NULL);
954 return synthetic_reply_method_errno(m, -EINVAL, NULL);
956 r = sd_bus_message_new_method_call(
959 "org.freedesktop.systemd1",
960 "/org/freedesktop/systemd1",
961 "org.freedesktop.systemd1.Manager",
964 return synthetic_reply_method_errno(m, r, NULL);
966 r = sd_bus_message_append_strv(msg, args);
968 return synthetic_reply_method_errno(m, r, NULL);
970 r = sd_bus_call(a, msg, 0, NULL, NULL);
972 return synthetic_reply_method_errno(m, r, NULL);
974 return synthetic_reply_method_return(m, NULL);
977 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
979 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
981 return synthetic_reply_method_errno(m, r, &error);
985 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred, bool *got_hello) {
986 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
995 /* As reaction to hello we need to respond with two messages:
996 * the callback reply and the NameAcquired for the unique
997 * name, since hello is otherwise obsolete on kdbus. */
1000 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1001 streq_ptr(m->destination, "org.freedesktop.DBus");
1008 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1013 log_error("Got duplicate hello, aborting.");
1017 if (!policy_check_hello(policy, ucred)) {
1018 log_error("Policy denied HELLO");
1027 r = sd_bus_message_new_method_return(m, &n);
1029 log_error("Failed to generate HELLO reply: %s", strerror(-r));
1033 r = sd_bus_message_append(n, "s", a->unique_name);
1035 log_error("Failed to append unique name to HELLO reply: %s", strerror(-r));
1039 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1041 log_error("Failed to append sender to HELLO reply: %s", strerror(-r));
1045 r = bus_seal_synthetic_message(b, n);
1047 log_error("Failed to seal HELLO reply: %s", strerror(-r));
1051 r = sd_bus_send(b, n, NULL);
1053 log_error("Failed to send HELLO reply: %s", strerror(-r));
1057 n = sd_bus_message_unref(n);
1058 r = sd_bus_message_new_signal(
1061 "/org/freedesktop/DBus",
1062 "org.freedesktop.DBus",
1065 log_error("Failed to allocate initial NameAcquired message: %s", strerror(-r));
1069 r = sd_bus_message_append(n, "s", a->unique_name);
1071 log_error("Failed to append unique name to NameAcquired message: %s", strerror(-r));
1075 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1077 log_error("Failed to append sender to NameAcquired message: %s", strerror(-r));
1081 r = bus_seal_synthetic_message(b, n);
1083 log_error("Failed to seal NameAcquired message: %s", strerror(-r));
1087 r = sd_bus_send(b, n, NULL);
1089 log_error("Failed to send NameAcquired message: %s", strerror(-r));
1096 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1097 char **well_known = NULL;
1107 /* We will change the sender of messages from the bus driver
1108 * so that they originate from the bus driver. This is a
1109 * speciality originating from dbus1, where the bus driver did
1110 * not have a unique id, but only the well-known name. */
1112 c = sd_bus_message_get_creds(m);
1116 r = sd_bus_creds_get_well_known_names(c, &well_known);
1120 if (strv_contains(well_known, "org.freedesktop.DBus"))
1121 m->sender = "org.freedesktop.DBus";
1126 int main(int argc, char *argv[]) {
1128 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1129 sd_id128_t server_id;
1130 int r, in_fd, out_fd;
1131 bool got_hello = false;
1133 struct ucred ucred = {};
1134 _cleanup_free_ char *peersec = NULL;
1137 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1138 log_parse_environment();
1141 r = parse_argv(argc, argv);
1145 r = policy_load(&policy, arg_configuration);
1147 log_error("Failed to load policy: %s", strerror(-r));
1151 /* policy_dump(&policy); */
1153 r = sd_listen_fds(0);
1155 in_fd = STDIN_FILENO;
1156 out_fd = STDOUT_FILENO;
1157 } else if (r == 1) {
1158 in_fd = SD_LISTEN_FDS_START;
1159 out_fd = SD_LISTEN_FDS_START;
1161 log_error("Illegal number of file descriptors passed");
1166 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1167 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1170 (void) getpeercred(in_fd, &ucred);
1171 (void) getpeersec(in_fd, &peersec);
1174 if (arg_drop_privileges) {
1175 const char *user = "systemd-bus-proxy";
1179 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1181 log_error("Cannot resolve user name %s: %s", user, strerror(-r));
1185 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1190 names_hash = hashmap_new(&string_hash_ops);
1198 log_error("Failed to allocate bus: %s", strerror(-r));
1202 r = sd_bus_set_description(a, "sd-proxy");
1204 log_error("Failed to set bus name: %s", strerror(-r));
1208 r = sd_bus_set_address(a, arg_address);
1210 log_error("Failed to set address to connect to: %s", strerror(-r));
1214 r = sd_bus_negotiate_fds(a, is_unix);
1216 log_error("Failed to set FD negotiation: %s", strerror(-r));
1220 if (ucred.pid > 0) {
1221 a->fake_creds.pid = ucred.pid;
1222 a->fake_creds.uid = ucred.uid;
1223 a->fake_creds.gid = ucred.gid;
1224 a->fake_creds_valid = true;
1228 a->fake_label = peersec;
1232 a->manual_peer_interface = true;
1234 r = sd_bus_start(a);
1236 log_error("Failed to start bus client: %s", strerror(-r));
1240 r = sd_bus_get_owner_id(a, &server_id);
1242 log_error("Failed to get server ID: %s", strerror(-r));
1248 log_error("Failed to allocate bus: %s", strerror(-r));
1252 r = sd_bus_set_fd(b, in_fd, out_fd);
1254 log_error("Failed to set fds: %s", strerror(-r));
1258 r = sd_bus_set_server(b, 1, server_id);
1260 log_error("Failed to set server mode: %s", strerror(-r));
1264 r = sd_bus_negotiate_fds(b, is_unix);
1266 log_error("Failed to set FD negotiation: %s", strerror(-r));
1270 r = sd_bus_set_anonymous(b, true);
1272 log_error("Failed to set anonymous authentication: %s", strerror(-r));
1276 b->manual_peer_interface = true;
1278 r = sd_bus_start(b);
1280 log_error("Failed to start bus client: %s", strerror(-r));
1284 r = rename_service(a, b);
1286 log_debug("Failed to rename process: %s", strerror(-r));
1289 _cleanup_free_ char *match = NULL;
1292 r = sd_bus_get_unique_name(a, &unique);
1294 log_error("Failed to get unique name: %s", strerror(-r));
1298 match = strjoin("type='signal',"
1299 "sender='org.freedesktop.DBus',"
1300 "path='/org/freedesktop/DBus',"
1301 "interface='org.freedesktop.DBus',"
1302 "member='NameOwnerChanged',"
1312 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1314 log_error("Failed to add match for NameLost: %s", strerror(-r));
1319 match = strjoin("type='signal',"
1320 "sender='org.freedesktop.DBus',"
1321 "path='/org/freedesktop/DBus',"
1322 "interface='org.freedesktop.DBus',"
1323 "member='NameOwnerChanged',"
1333 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1335 log_error("Failed to add match for NameAcquired: %s", strerror(-r));
1341 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1342 int events_a, events_b, fd;
1343 uint64_t timeout_a, timeout_b, t;
1344 struct timespec _ts, *ts;
1345 struct pollfd *pollfd;
1349 r = sd_bus_process(a, &m);
1351 /* treat 'connection reset by peer' as clean exit condition */
1352 if (r == -ECONNRESET)
1355 log_error("Failed to process bus a: %s", strerror(-r));
1361 /* We officially got EOF, let's quit */
1362 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1367 k = synthesize_name_acquired(a, b, m);
1370 log_error("Failed to synthesize message: %s", strerror(-r));
1376 k = sd_bus_send(b, m, NULL);
1378 if (k == -ECONNRESET)
1382 log_error("Failed to send message: %s", strerror(-r));
1393 r = sd_bus_process(b, &m);
1395 /* treat 'connection reset by peer' as clean exit condition */
1396 if (r == -ECONNRESET)
1399 log_error("Failed to process bus b: %s", strerror(-r));
1405 /* We officially got EOF, let's quit */
1406 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1411 k = process_hello(a, b, m, &policy, &ucred, &got_hello);
1414 log_error("Failed to process HELLO: %s", strerror(-r));
1421 k = process_driver(a, b, m, &policy, &ucred);
1424 log_error("Failed to process driver calls: %s", strerror(-r));
1431 k = process_policy(a, b, m, &policy, &ucred);
1434 log_error("Failed to process policy: %s", strerror(-r));
1438 k = sd_bus_send(a, m, NULL);
1440 if (k == -ECONNRESET)
1444 log_error("Failed to send message: %s", strerror(-r));
1456 fd = sd_bus_get_fd(a);
1458 log_error("Failed to get fd: %s", strerror(-r));
1462 events_a = sd_bus_get_events(a);
1464 log_error("Failed to get events mask: %s", strerror(-r));
1468 r = sd_bus_get_timeout(a, &timeout_a);
1470 log_error("Failed to get timeout: %s", strerror(-r));
1474 events_b = sd_bus_get_events(b);
1476 log_error("Failed to get events mask: %s", strerror(-r));
1480 r = sd_bus_get_timeout(b, &timeout_b);
1482 log_error("Failed to get timeout: %s", strerror(-r));
1487 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1490 if (t == (uint64_t) -1)
1495 nw = now(CLOCK_MONOTONIC);
1501 ts = timespec_store(&_ts, t);
1504 pollfd = (struct pollfd[3]) {
1505 {.fd = fd, .events = events_a, },
1506 {.fd = in_fd, .events = events_b & POLLIN, },
1507 {.fd = out_fd, .events = events_b & POLLOUT, }
1510 r = ppoll(pollfd, 3, ts, NULL);
1512 log_error("ppoll() failed: %m");
1520 "STATUS=Shutting down.");
1522 policy_free(&policy);
1523 strv_free(arg_configuration);
1524 hashmap_free(names_hash);
1527 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;