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"
48 #include "bus-control.h"
50 static char *arg_address = NULL;
51 static char *arg_command_line_buffer = NULL;
52 static bool arg_drop_privileges = false;
53 static char **arg_configuration = NULL;
55 static int help(void) {
57 printf("%s [OPTIONS...]\n\n"
58 "Connect STDIO or a socket to a given bus address.\n\n"
59 " -h --help Show this help\n"
60 " --version Show package version\n"
61 " --drop-privileges Drop privileges\n"
62 " --configuration=PATH Configuration file or directory\n"
63 " --machine=MACHINE Connect to specified machine\n"
64 " --address=ADDRESS Connect to the bus specified by ADDRESS\n"
65 " (default: " DEFAULT_SYSTEM_BUS_ADDRESS ")\n",
66 program_invocation_short_name);
71 static int parse_argv(int argc, char *argv[]) {
81 static const struct option options[] = {
82 { "help", no_argument, NULL, 'h' },
83 { "version", no_argument, NULL, ARG_VERSION },
84 { "address", required_argument, NULL, ARG_ADDRESS },
85 { "drop-privileges", no_argument, NULL, ARG_DROP_PRIVILEGES },
86 { "configuration", required_argument, NULL, ARG_CONFIGURATION },
87 { "machine", required_argument, NULL, ARG_MACHINE },
96 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
105 puts(PACKAGE_STRING);
106 puts(SYSTEMD_FEATURES);
121 case ARG_DROP_PRIVILEGES:
122 arg_drop_privileges = true;
125 case ARG_CONFIGURATION:
126 r = strv_extend(&arg_configuration, optarg);
132 _cleanup_free_ char *e = NULL;
135 e = bus_address_escape(optarg);
140 a = strjoin("x-container-kernel:machine=", e, ";x-container-unix:machine=", e, NULL);
142 a = strjoin("x-container-unix:machine=", e, NULL);
157 assert_not_reached("Unhandled option");
160 /* If the first command line argument is only "x" characters
161 * we'll write who we are talking to into it, so that "ps" is
163 arg_command_line_buffer = argv[optind];
164 if (argc > optind + 1 || (arg_command_line_buffer && !in_charset(arg_command_line_buffer, "x"))) {
165 log_error("Too many arguments");
170 arg_address = strdup(DEFAULT_SYSTEM_BUS_ADDRESS);
178 static int rename_service(sd_bus *a, sd_bus *b) {
179 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
180 _cleanup_free_ char *p = NULL, *name = NULL;
190 r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM, &creds);
194 r = sd_bus_creds_get_uid(creds, &uid);
198 r = sd_bus_creds_get_pid(creds, &pid);
202 r = sd_bus_creds_get_cmdline(creds, &cmdline);
206 r = sd_bus_creds_get_comm(creds, &comm);
210 name = uid_to_name(uid);
214 p = strv_join(cmdline, " ");
218 /* The status string gets the full command line ... */
220 "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)",
224 /* ... and the argv line only the short comm */
225 if (arg_command_line_buffer) {
228 m = strlen(arg_command_line_buffer);
229 w = snprintf(arg_command_line_buffer, m,
230 "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]",
235 memzero(arg_command_line_buffer + w, m - w);
238 log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s",
246 static int synthesize_name_acquired(sd_bus *a, sd_bus *b, sd_bus_message *m) {
247 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
248 const char *name, *old_owner, *new_owner;
255 /* If we get NameOwnerChanged for our own name, we need to
256 * synthesize NameLost/NameAcquired, since socket clients need
257 * that, even though it is obsoleted on kdbus */
262 if (!sd_bus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged") ||
263 !streq_ptr(m->path, "/org/freedesktop/DBus") ||
264 !streq_ptr(m->sender, "org.freedesktop.DBus"))
267 r = sd_bus_message_read(m, "sss", &name, &old_owner, &new_owner);
271 r = sd_bus_message_rewind(m, true);
275 if (streq(old_owner, a->unique_name)) {
277 r = sd_bus_message_new_signal(
280 "/org/freedesktop/DBus",
281 "org.freedesktop.DBus",
284 } else if (streq(new_owner, a->unique_name)) {
286 r = sd_bus_message_new_signal(
289 "/org/freedesktop/DBus",
290 "org.freedesktop.DBus",
298 r = sd_bus_message_append(n, "s", name);
302 r = bus_message_append_sender(n, "org.freedesktop.DBus");
306 r = bus_seal_synthetic_message(b, n);
310 return sd_bus_send(b, n, NULL);
313 static int synthetic_driver_send(sd_bus *b, sd_bus_message *m) {
319 r = bus_message_append_sender(m, "org.freedesktop.DBus");
323 r = bus_seal_synthetic_message(b, m);
327 return sd_bus_send(b, m, NULL);
330 static int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) {
331 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
336 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
339 r = sd_bus_message_new_method_error(call, &m, e);
343 return synthetic_driver_send(call->bus, m);
346 static int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) {
348 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
352 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
355 if (sd_bus_error_is_set(p))
356 return synthetic_reply_method_error(call, p);
358 sd_bus_error_set_errno(&berror, error);
360 return synthetic_reply_method_error(call, &berror);
363 static int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) {
364 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
369 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
372 r = sd_bus_message_new_method_return(call, &m);
376 if (!isempty(types)) {
380 r = bus_message_append_ap(m, types, ap);
386 return synthetic_driver_send(call->bus, m);
389 static int synthetic_reply_return_strv(sd_bus_message *call, char **l) {
390 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
395 r = sd_bus_message_new_method_return(call, &m);
397 return synthetic_reply_method_errno(call, r, NULL);
399 r = sd_bus_message_append_strv(m, l);
401 return synthetic_reply_method_errno(call, r, NULL);
403 return synthetic_driver_send(call->bus, m);
406 static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
407 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
414 r = sd_bus_get_name_creds(bus, name, mask, &c);
415 if (r == -ESRCH || r == -ENXIO)
416 return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
420 if ((c->mask & mask) != mask)
429 static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
437 r = sd_bus_message_read(m, "s", &name);
441 return get_creds_by_name(bus, name, mask, _creds, error);
444 static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred, Set *owned_names) {
454 if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
457 /* The "Hello()" call is is handled in process_hello() */
459 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
461 if (!sd_bus_message_has_signature(m, ""))
462 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
464 return synthetic_reply_method_return(m, "s",
465 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
466 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
468 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
469 " <method name=\"Introspect\">\n"
470 " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
473 " <interface name=\"org.freedesktop.DBus\">\n"
474 " <method name=\"AddMatch\">\n"
475 " <arg type=\"s\" direction=\"in\"/>\n"
477 " <method name=\"RemoveMatch\">\n"
478 " <arg type=\"s\" direction=\"in\"/>\n"
480 " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
481 " <arg type=\"s\" direction=\"in\"/>\n"
482 " <arg type=\"ay\" direction=\"out\"/>\n"
484 " <method name=\"GetConnectionUnixProcessID\">\n"
485 " <arg type=\"s\" direction=\"in\"/>\n"
486 " <arg type=\"u\" direction=\"out\"/>\n"
488 " <method name=\"GetConnectionUnixUser\">\n"
489 " <arg type=\"s\" direction=\"in\"/>\n"
490 " <arg type=\"u\" direction=\"out\"/>\n"
492 " <method name=\"GetId\">\n"
493 " <arg type=\"s\" direction=\"out\"/>\n"
495 " <method name=\"GetNameOwner\">\n"
496 " <arg type=\"s\" direction=\"in\"/>\n"
497 " <arg type=\"s\" direction=\"out\"/>\n"
499 " <method name=\"Hello\">\n"
500 " <arg type=\"s\" direction=\"out\"/>\n"
502 " <method name=\"ListActivatableNames\">\n"
503 " <arg type=\"as\" direction=\"out\"/>\n"
505 " <method name=\"ListNames\">\n"
506 " <arg type=\"as\" direction=\"out\"/>\n"
508 " <method name=\"ListQueuedOwners\">\n"
509 " <arg type=\"s\" direction=\"in\"/>\n"
510 " <arg type=\"as\" direction=\"out\"/>\n"
512 " <method name=\"NameHasOwner\">\n"
513 " <arg type=\"s\" direction=\"in\"/>\n"
514 " <arg type=\"b\" direction=\"out\"/>\n"
516 " <method name=\"ReleaseName\">\n"
517 " <arg type=\"s\" direction=\"in\"/>\n"
518 " <arg type=\"u\" direction=\"out\"/>\n"
520 " <method name=\"ReloadConfig\">\n"
522 " <method name=\"RequestName\">\n"
523 " <arg type=\"s\" direction=\"in\"/>\n"
524 " <arg type=\"u\" direction=\"in\"/>\n"
525 " <arg type=\"u\" direction=\"out\"/>\n"
527 " <method name=\"StartServiceByName\">\n"
528 " <arg type=\"s\" direction=\"in\"/>\n"
529 " <arg type=\"u\" direction=\"in\"/>\n"
530 " <arg type=\"u\" direction=\"out\"/>\n"
532 " <method name=\"UpdateActivationEnvironment\">\n"
533 " <arg type=\"a{ss}\" direction=\"in\"/>\n"
535 " <signal name=\"NameAcquired\">\n"
536 " <arg type=\"s\"/>\n"
538 " <signal name=\"NameLost\">\n"
539 " <arg type=\"s\"/>\n"
541 " <signal name=\"NameOwnerChanged\">\n"
542 " <arg type=\"s\"/>\n"
543 " <arg type=\"s\"/>\n"
544 " <arg type=\"s\"/>\n"
549 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
552 if (!sd_bus_message_has_signature(m, "s"))
553 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
555 r = sd_bus_message_read(m, "s", &match);
557 return synthetic_reply_method_errno(m, r, NULL);
559 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
561 return synthetic_reply_method_errno(m, r, NULL);
563 return synthetic_reply_method_return(m, NULL);
565 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
568 if (!sd_bus_message_has_signature(m, "s"))
569 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
571 r = sd_bus_message_read(m, "s", &match);
573 return synthetic_reply_method_errno(m, r, NULL);
575 r = bus_remove_match_by_string(a, match, NULL, NULL);
577 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
579 return synthetic_reply_method_errno(m, r, NULL);
581 return synthetic_reply_method_return(m, NULL);
583 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
584 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
585 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
587 if (!sd_bus_message_has_signature(m, "s"))
588 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
590 r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
592 return synthetic_reply_method_errno(m, r, &error);
594 return synthetic_reply_method_return(m, "y", creds->label, strlen(creds->label));
596 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
597 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
598 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
600 if (!sd_bus_message_has_signature(m, "s"))
601 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
603 r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error);
605 return synthetic_reply_method_errno(m, r, &error);
607 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
609 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
610 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
611 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
613 if (!sd_bus_message_has_signature(m, "s"))
614 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
616 r = get_creds_by_message(a, m, SD_BUS_CREDS_UID, &creds, &error);
618 return synthetic_reply_method_errno(m, r, &error);
620 return synthetic_reply_method_return(m, "u", (uint32_t) creds->uid);
622 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
623 sd_id128_t server_id;
624 char buf[SD_ID128_STRING_MAX];
626 if (!sd_bus_message_has_signature(m, ""))
627 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
629 r = sd_bus_get_bus_id(a, &server_id);
631 return synthetic_reply_method_errno(m, r, NULL);
633 return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
635 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
637 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
638 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
640 if (!sd_bus_message_has_signature(m, "s"))
641 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
643 r = sd_bus_message_read(m, "s", &name);
645 return synthetic_reply_method_errno(m, r, NULL);
647 if (streq(name, "org.freedesktop.DBus"))
648 return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
650 r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
652 return synthetic_reply_method_errno(m, r, &error);
654 return synthetic_reply_method_return(m, "s", creds->unique_name);
656 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
657 _cleanup_strv_free_ char **names = NULL;
659 if (!sd_bus_message_has_signature(m, ""))
660 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
662 r = sd_bus_list_names(a, NULL, &names);
664 return synthetic_reply_method_errno(m, r, NULL);
666 /* Let's sort the names list to make it stable */
669 return synthetic_reply_return_strv(m, names);
671 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
672 _cleanup_strv_free_ char **names = NULL;
674 if (!sd_bus_message_has_signature(m, ""))
675 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
677 r = sd_bus_list_names(a, &names, NULL);
679 return synthetic_reply_method_errno(m, r, NULL);
681 r = strv_extend(&names, "org.freedesktop.DBus");
683 return synthetic_reply_method_errno(m, r, NULL);
685 /* Let's sort the names list to make it stable */
688 return synthetic_reply_return_strv(m, names);
690 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
691 struct kdbus_cmd_name_list cmd = {};
692 struct kdbus_name_list *name_list;
693 struct kdbus_name_info *name;
694 _cleanup_strv_free_ char **owners = NULL;
695 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
699 if (!sd_bus_message_has_signature(m, "s"))
700 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
702 r = sd_bus_message_read(m, "s", &arg0);
704 return synthetic_reply_method_errno(m, r, NULL);
706 r = sd_bus_get_name_creds(a, arg0, 0, NULL);
707 if (r == -ESRCH || r == -ENXIO) {
708 sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0);
709 return synthetic_reply_method_errno(m, r, &error);
712 return synthetic_reply_method_errno(m, r, NULL);
714 cmd.flags = KDBUS_NAME_LIST_QUEUED;
715 r = ioctl(a->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
717 return synthetic_reply_method_errno(m, -errno, NULL);
719 name_list = (struct kdbus_name_list *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
721 KDBUS_ITEM_FOREACH(name, name_list, names) {
722 const char *entry_name = NULL;
723 struct kdbus_item *item;
726 KDBUS_ITEM_FOREACH(item, name, items)
727 if (item->type == KDBUS_ITEM_OWNED_NAME)
728 entry_name = item->name.name;
730 if (!streq_ptr(entry_name, arg0))
733 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
738 r = strv_consume(&owners, n);
745 r = bus_kernel_cmd_free(a, cmd.offset);
747 return synthetic_reply_method_errno(m, r, NULL);
750 return synthetic_reply_method_errno(m, err, NULL);
752 return synthetic_reply_return_strv(m, owners);
754 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
757 if (!sd_bus_message_has_signature(m, "s"))
758 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
760 r = sd_bus_message_read(m, "s", &name);
762 return synthetic_reply_method_errno(m, r, NULL);
764 if (streq(name, "org.freedesktop.DBus"))
765 return synthetic_reply_method_return(m, "b", true);
767 r = sd_bus_get_name_creds(a, name, 0, NULL);
768 if (r < 0 && r != -ESRCH && r != -ENXIO)
769 return synthetic_reply_method_errno(m, r, NULL);
771 return synthetic_reply_method_return(m, "b", r >= 0);
773 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
776 if (!sd_bus_message_has_signature(m, "s"))
777 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
779 r = sd_bus_message_read(m, "s", &name);
781 return synthetic_reply_method_errno(m, r, NULL);
783 r = sd_bus_release_name(a, name);
786 return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
787 if (r == -EADDRINUSE)
788 return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
790 return synthetic_reply_method_errno(m, r, NULL);
793 set_remove(owned_names, (char*) name);
795 return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
797 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
798 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
800 if (!sd_bus_message_has_signature(m, ""))
801 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
803 r = sd_bus_error_setf(&error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
805 return synthetic_reply_method_errno(m, r, &error);
807 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
809 uint32_t flags, param;
812 if (!sd_bus_message_has_signature(m, "su"))
813 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
815 r = sd_bus_message_read(m, "su", &name, &flags);
817 return synthetic_reply_method_errno(m, r, NULL);
819 if (policy && !policy_check_own(policy, ucred->uid, ucred->gid, name))
820 return synthetic_reply_method_errno(m, -EPERM, NULL);
822 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
823 return synthetic_reply_method_errno(m, -EINVAL, NULL);
826 if (flags & BUS_NAME_ALLOW_REPLACEMENT)
827 param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
828 if (flags & BUS_NAME_REPLACE_EXISTING)
829 param |= SD_BUS_NAME_REPLACE_EXISTING;
830 if (!(flags & BUS_NAME_DO_NOT_QUEUE))
831 param |= SD_BUS_NAME_QUEUE;
833 r = set_put_strdup(owned_names, name);
835 return synthetic_reply_method_errno(m, r, NULL);
837 r = sd_bus_request_name(a, name, param);
840 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
842 set_remove(owned_names, (char*) name);
845 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
846 return synthetic_reply_method_errno(m, r, NULL);
852 return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
854 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
856 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
857 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
861 if (!sd_bus_message_has_signature(m, "su"))
862 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
864 r = sd_bus_message_read(m, "su", &name, &flags);
866 return synthetic_reply_method_errno(m, r, NULL);
869 return synthetic_reply_method_errno(m, -EINVAL, NULL);
871 r = sd_bus_get_name_creds(a, name, 0, NULL);
872 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
873 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
875 return synthetic_reply_method_errno(m, r, NULL);
877 r = sd_bus_message_new_method_call(
882 "org.freedesktop.DBus.Peer",
885 return synthetic_reply_method_errno(m, r, NULL);
887 r = sd_bus_send(a, msg, NULL);
889 return synthetic_reply_method_errno(m, r, NULL);
891 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
893 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
894 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
895 _cleanup_strv_free_ char **args = NULL;
897 if (!sd_bus_message_has_signature(m, "a{ss}"))
898 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
900 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
902 return synthetic_reply_method_errno(m, r, NULL);
904 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
905 _cleanup_free_ char *s = NULL;
909 r = sd_bus_message_read(m, "ss", &key, &value);
911 return synthetic_reply_method_errno(m, r, NULL);
913 s = strjoin(key, "=", value, NULL);
915 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
917 r = strv_extend(&args, s);
919 return synthetic_reply_method_errno(m, r, NULL);
921 r = sd_bus_message_exit_container(m);
923 return synthetic_reply_method_errno(m, r, NULL);
926 r = sd_bus_message_exit_container(m);
928 return synthetic_reply_method_errno(m, r, NULL);
931 return synthetic_reply_method_errno(m, -EINVAL, NULL);
933 r = sd_bus_message_new_method_call(
936 "org.freedesktop.systemd1",
937 "/org/freedesktop/systemd1",
938 "org.freedesktop.systemd1.Manager",
941 return synthetic_reply_method_errno(m, r, NULL);
943 r = sd_bus_message_append_strv(msg, args);
945 return synthetic_reply_method_errno(m, r, NULL);
947 r = sd_bus_call(a, msg, 0, NULL, NULL);
949 return synthetic_reply_method_errno(m, r, NULL);
951 return synthetic_reply_method_return(m, NULL);
954 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
956 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
958 return synthetic_reply_method_errno(m, r, &error);
962 static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
972 if (from->is_kernel) {
973 uid_t sender_uid = UID_INVALID;
974 gid_t sender_gid = GID_INVALID;
975 char **sender_names = NULL;
976 bool granted = false;
978 /* Driver messages are always OK */
979 if (streq_ptr(m->sender, "org.freedesktop.DBus"))
982 /* The message came from the kernel, and is sent to our legacy client. */
983 r = sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
987 (void) sd_bus_creds_get_uid(&m->creds, &sender_uid);
988 (void) sd_bus_creds_get_gid(&m->creds, &sender_gid);
990 /* First check whether the sender can send the message to our name */
991 if (set_isempty(owned_names)) {
992 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, NULL, m->path, m->interface, m->member))
998 SET_FOREACH(n, owned_names, i)
999 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, n, m->path, m->interface, m->member)) {
1006 /* Then check whether us (the recipient) can recieve from the sender's name */
1007 if (strv_isempty(sender_names)) {
1008 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1013 STRV_FOREACH(n, sender_names) {
1014 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member))
1020 /* Return an error back to the caller */
1021 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1022 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
1024 /* Return 1, indicating that the message shall not be processed any further */
1028 if (to->is_kernel) {
1029 _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL;
1030 uid_t destination_uid = UID_INVALID;
1031 gid_t destination_gid = GID_INVALID;
1032 const char *destination_unique = NULL;
1033 char **destination_names = NULL;
1034 bool granted = false;
1036 /* Driver messages are always OK */
1037 if (streq_ptr(m->destination, "org.freedesktop.DBus"))
1040 /* The message came from the legacy client, and is sent to kdbus. */
1041 if (m->destination) {
1042 r = bus_get_name_creds_kdbus(to, m->destination,
1043 SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
1044 SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID,
1045 true, &destination_creds);
1049 r = sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
1053 r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
1057 (void) sd_bus_creds_get_uid(destination_creds, &destination_uid);
1058 (void) sd_bus_creds_get_gid(destination_creds, &destination_gid);
1061 /* First check if we (the sender) can send to this name */
1062 if (strv_isempty(destination_names)) {
1063 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1068 STRV_FOREACH(n, destination_names) {
1069 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member)) {
1071 /* If we made a receiver decision,
1072 then remember which name's policy
1073 we used, and to which unique ID it
1074 mapped when we made the
1075 decision. Then, let's pass this to
1076 the kernel when sending the
1077 message, so that it refuses the
1078 operation should the name and
1079 unique ID not map to each other
1082 r = free_and_strdup(&m->destination_ptr, *n);
1086 r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
1096 /* Then check if the recipient can receive from our name */
1098 if (set_isempty(owned_names)) {
1099 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, NULL, m->path, m->interface, m->member))
1105 SET_FOREACH(n, owned_names, i)
1106 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, n, m->path, m->interface, m->member))
1111 /* Return an error back to the caller */
1112 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1113 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
1115 /* Return 1, indicating that the message shall not be processed any further */
1122 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
1123 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
1132 /* As reaction to hello we need to respond with two messages:
1133 * the callback reply and the NameAcquired for the unique
1134 * name, since hello is otherwise obsolete on kdbus. */
1137 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1138 streq_ptr(m->destination, "org.freedesktop.DBus");
1145 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1150 log_error("Got duplicate hello, aborting.");
1159 r = sd_bus_message_new_method_return(m, &n);
1161 return log_error_errno(r, "Failed to generate HELLO reply: %m");
1163 r = sd_bus_message_append(n, "s", a->unique_name);
1165 return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
1167 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1169 return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
1171 r = bus_seal_synthetic_message(b, n);
1173 return log_error_errno(r, "Failed to seal HELLO reply: %m");
1175 r = sd_bus_send(b, n, NULL);
1177 return log_error_errno(r, "Failed to send HELLO reply: %m");
1179 n = sd_bus_message_unref(n);
1180 r = sd_bus_message_new_signal(
1183 "/org/freedesktop/DBus",
1184 "org.freedesktop.DBus",
1187 return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
1189 r = sd_bus_message_append(n, "s", a->unique_name);
1191 return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
1193 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1195 return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
1197 r = bus_seal_synthetic_message(b, n);
1199 return log_error_errno(r, "Failed to seal NameAcquired message: %m");
1201 r = sd_bus_send(b, n, NULL);
1203 return log_error_errno(r, "Failed to send NameAcquired message: %m");
1208 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1209 char **well_known = NULL;
1219 /* We will change the sender of messages from the bus driver
1220 * so that they originate from the bus driver. This is a
1221 * speciality originating from dbus1, where the bus driver did
1222 * not have a unique id, but only the well-known name. */
1224 c = sd_bus_message_get_creds(m);
1228 r = sd_bus_creds_get_well_known_names(c, &well_known);
1232 if (strv_contains(well_known, "org.freedesktop.DBus"))
1233 m->sender = "org.freedesktop.DBus";
1238 int main(int argc, char *argv[]) {
1240 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1241 sd_id128_t server_id;
1242 int r, in_fd, out_fd;
1243 bool got_hello = false;
1245 struct ucred ucred = {};
1246 _cleanup_free_ char *peersec = NULL;
1247 Policy policy_buffer = {}, *policy = NULL;
1248 _cleanup_set_free_free_ Set *owned_names = NULL;
1250 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1251 log_parse_environment();
1254 r = parse_argv(argc, argv);
1258 r = sd_listen_fds(0);
1260 in_fd = STDIN_FILENO;
1261 out_fd = STDOUT_FILENO;
1262 } else if (r == 1) {
1263 in_fd = SD_LISTEN_FDS_START;
1264 out_fd = SD_LISTEN_FDS_START;
1266 log_error("Illegal number of file descriptors passed");
1271 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1272 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1275 (void) getpeercred(in_fd, &ucred);
1276 (void) getpeersec(in_fd, &peersec);
1279 if (arg_drop_privileges) {
1280 const char *user = "systemd-bus-proxy";
1284 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1286 log_error_errno(r, "Cannot resolve user name %s: %m", user);
1290 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1295 owned_names = set_new(&string_hash_ops);
1303 log_error_errno(r, "Failed to allocate bus: %m");
1307 r = sd_bus_set_description(a, "sd-proxy");
1309 log_error_errno(r, "Failed to set bus name: %m");
1313 r = sd_bus_set_address(a, arg_address);
1315 log_error_errno(r, "Failed to set address to connect to: %m");
1319 r = sd_bus_negotiate_fds(a, is_unix);
1321 log_error_errno(r, "Failed to set FD negotiation: %m");
1325 r = sd_bus_negotiate_creds(a, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1327 log_error_errno(r, "Failed to set credential negotiation: %m");
1331 if (ucred.pid > 0) {
1332 a->fake_pids.pid = ucred.pid;
1333 a->fake_pids_valid = true;
1335 a->fake_creds.uid = ucred.uid;
1336 a->fake_creds.euid = UID_INVALID;
1337 a->fake_creds.suid = UID_INVALID;
1338 a->fake_creds.fsuid = UID_INVALID;
1339 a->fake_creds.gid = ucred.gid;
1340 a->fake_creds.egid = GID_INVALID;
1341 a->fake_creds.sgid = GID_INVALID;
1342 a->fake_creds.fsgid = GID_INVALID;
1343 a->fake_creds_valid = true;
1347 a->fake_label = peersec;
1351 a->manual_peer_interface = true;
1353 r = sd_bus_start(a);
1355 log_error_errno(r, "Failed to start bus client: %m");
1359 r = sd_bus_get_bus_id(a, &server_id);
1361 log_error_errno(r, "Failed to get server ID: %m");
1366 if (!arg_configuration) {
1369 r = sd_bus_get_scope(a, &scope);
1371 log_error_errno(r, "Couldn't determine bus scope: %m");
1375 if (streq(scope, "system"))
1376 arg_configuration = strv_new(
1377 "/etc/dbus-1/system.conf",
1378 "/etc/dbus-1/system.d/",
1379 "/etc/dbus-1/system-local.conf",
1381 else if (streq(scope, "user"))
1382 arg_configuration = strv_new(
1383 "/etc/dbus-1/session.conf",
1384 "/etc/dbus-1/session.d/",
1385 "/etc/dbus-1/session-local.conf",
1388 log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope);
1392 if (!arg_configuration) {
1398 r = policy_load(&policy_buffer, arg_configuration);
1400 log_error_errno(r, "Failed to load policy: %m");
1404 policy = &policy_buffer;
1405 /* policy_dump(policy); */
1407 if (!policy_check_hello(policy, ucred.uid, ucred.gid)) {
1408 r = log_error_errno(EPERM, "Policy denied connection.");
1415 log_error_errno(r, "Failed to allocate bus: %m");
1419 r = sd_bus_set_fd(b, in_fd, out_fd);
1421 log_error_errno(r, "Failed to set fds: %m");
1425 r = sd_bus_set_server(b, 1, server_id);
1427 log_error_errno(r, "Failed to set server mode: %m");
1431 r = sd_bus_negotiate_fds(b, is_unix);
1433 log_error_errno(r, "Failed to set FD negotiation: %m");
1437 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1439 log_error_errno(r, "Failed to set credential negotiation: %m");
1443 r = sd_bus_set_anonymous(b, true);
1445 log_error_errno(r, "Failed to set anonymous authentication: %m");
1449 b->manual_peer_interface = true;
1451 r = sd_bus_start(b);
1453 log_error_errno(r, "Failed to start bus client: %m");
1457 r = rename_service(a, b);
1459 log_debug_errno(r, "Failed to rename process: %m");
1462 _cleanup_free_ char *match = NULL;
1465 r = sd_bus_get_unique_name(a, &unique);
1467 log_error_errno(r, "Failed to get unique name: %m");
1471 match = strjoin("type='signal',"
1472 "sender='org.freedesktop.DBus',"
1473 "path='/org/freedesktop/DBus',"
1474 "interface='org.freedesktop.DBus',"
1475 "member='NameOwnerChanged',"
1485 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1487 log_error_errno(r, "Failed to add match for NameLost: %m");
1492 match = strjoin("type='signal',"
1493 "sender='org.freedesktop.DBus',"
1494 "path='/org/freedesktop/DBus',"
1495 "interface='org.freedesktop.DBus',"
1496 "member='NameOwnerChanged',"
1506 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1508 log_error_errno(r, "Failed to add match for NameAcquired: %m");
1514 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1515 int events_a, events_b, fd;
1516 uint64_t timeout_a, timeout_b, t;
1517 struct timespec _ts, *ts;
1518 struct pollfd *pollfd;
1522 /* Read messages from bus, to pass them on to our client */
1524 r = sd_bus_process(a, &m);
1526 /* treat 'connection reset by peer' as clean exit condition */
1527 if (r == -ECONNRESET)
1530 log_error_errno(r, "Failed to process bus a: %m");
1536 bool processed = false;
1538 /* We officially got EOF, let's quit */
1539 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1544 k = synthesize_name_acquired(a, b, m);
1547 log_error_errno(r, "Failed to synthesize message: %m");
1554 k = process_policy(a, b, m, policy, &ucred, owned_names);
1557 log_error_errno(r, "Failed to process policy: %m");
1566 k = sd_bus_send(b, m, NULL);
1568 if (k == -ECONNRESET)
1572 log_error_errno(r, "Failed to send message to client: %m");
1585 /* Read messages from our client, to pass them on to the bus */
1586 r = sd_bus_process(b, &m);
1588 /* treat 'connection reset by peer' as clean exit condition */
1589 if (r == -ECONNRESET)
1592 log_error_errno(r, "Failed to process bus b: %m");
1598 bool processed = false;
1600 /* We officially got EOF, let's quit */
1601 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1606 k = process_hello(a, b, m, &got_hello);
1609 log_error_errno(r, "Failed to process HELLO: %m");
1617 k = process_driver(a, b, m, policy, &ucred, owned_names);
1620 log_error_errno(r, "Failed to process driver calls: %m");
1631 k = process_policy(b, a, m, policy, &ucred, owned_names);
1634 log_error_errno(r, "Failed to process policy: %m");
1643 k = sd_bus_send(a, m, NULL);
1646 /* The name database changed since the policy check, hence let's check again */
1648 else if (k == -ECONNRESET)
1652 log_error_errno(r, "Failed to send message to bus: %m");
1668 fd = sd_bus_get_fd(a);
1670 log_error_errno(r, "Failed to get fd: %m");
1674 events_a = sd_bus_get_events(a);
1676 log_error_errno(r, "Failed to get events mask: %m");
1680 r = sd_bus_get_timeout(a, &timeout_a);
1682 log_error_errno(r, "Failed to get timeout: %m");
1686 events_b = sd_bus_get_events(b);
1688 log_error_errno(r, "Failed to get events mask: %m");
1692 r = sd_bus_get_timeout(b, &timeout_b);
1694 log_error_errno(r, "Failed to get timeout: %m");
1699 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1702 if (t == (uint64_t) -1)
1707 nw = now(CLOCK_MONOTONIC);
1713 ts = timespec_store(&_ts, t);
1716 pollfd = (struct pollfd[3]) {
1717 {.fd = fd, .events = events_a, },
1718 {.fd = in_fd, .events = events_b & POLLIN, },
1719 {.fd = out_fd, .events = events_b & POLLOUT, }
1722 r = ppoll(pollfd, 3, ts, NULL);
1724 log_error_errno(errno, "ppoll() failed: %m");
1732 "STATUS=Shutting down.");
1734 policy_free(&policy_buffer);
1735 strv_free(arg_configuration);
1738 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;