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"
49 #include "smack-util.h"
51 static char *arg_address = NULL;
52 static char *arg_command_line_buffer = NULL;
53 static bool arg_drop_privileges = false;
54 static char **arg_configuration = 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_ADDRESS ")\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_ADDRESS);
179 static int rename_service(sd_bus *a, sd_bus *b) {
180 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
181 _cleanup_free_ char *p = NULL, *name = NULL;
191 r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM, &creds);
195 r = sd_bus_creds_get_uid(creds, &uid);
199 r = sd_bus_creds_get_pid(creds, &pid);
203 r = sd_bus_creds_get_cmdline(creds, &cmdline);
207 r = sd_bus_creds_get_comm(creds, &comm);
211 name = uid_to_name(uid);
215 p = strv_join(cmdline, " ");
219 /* The status string gets the full command line ... */
221 "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)",
225 /* ... and the argv line only the short comm */
226 if (arg_command_line_buffer) {
229 m = strlen(arg_command_line_buffer);
230 w = snprintf(arg_command_line_buffer, m,
231 "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]",
236 memzero(arg_command_line_buffer + w, m - w);
239 log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s",
247 static int synthesize_name_acquired(sd_bus *a, sd_bus *b, sd_bus_message *m) {
248 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
249 const char *name, *old_owner, *new_owner;
256 /* If we get NameOwnerChanged for our own name, we need to
257 * synthesize NameLost/NameAcquired, since socket clients need
258 * that, even though it is obsoleted on kdbus */
263 if (!sd_bus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged") ||
264 !streq_ptr(m->path, "/org/freedesktop/DBus") ||
265 !streq_ptr(m->sender, "org.freedesktop.DBus"))
268 r = sd_bus_message_read(m, "sss", &name, &old_owner, &new_owner);
272 r = sd_bus_message_rewind(m, true);
276 if (streq(old_owner, a->unique_name)) {
278 r = sd_bus_message_new_signal(
281 "/org/freedesktop/DBus",
282 "org.freedesktop.DBus",
285 } else if (streq(new_owner, a->unique_name)) {
287 r = sd_bus_message_new_signal(
290 "/org/freedesktop/DBus",
291 "org.freedesktop.DBus",
299 r = sd_bus_message_append(n, "s", name);
303 r = bus_message_append_sender(n, "org.freedesktop.DBus");
307 r = bus_seal_synthetic_message(b, n);
311 return sd_bus_send(b, n, NULL);
314 static int synthetic_driver_send(sd_bus *b, sd_bus_message *m) {
320 r = bus_message_append_sender(m, "org.freedesktop.DBus");
324 r = bus_seal_synthetic_message(b, m);
328 return sd_bus_send(b, m, NULL);
331 static int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) {
332 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
337 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
340 r = sd_bus_message_new_method_error(call, &m, e);
344 return synthetic_driver_send(call->bus, m);
347 static int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) {
349 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
353 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
356 if (sd_bus_error_is_set(p))
357 return synthetic_reply_method_error(call, p);
359 sd_bus_error_set_errno(&berror, error);
361 return synthetic_reply_method_error(call, &berror);
364 static int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) {
365 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
370 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
373 r = sd_bus_message_new_method_return(call, &m);
377 if (!isempty(types)) {
381 r = bus_message_append_ap(m, types, ap);
387 return synthetic_driver_send(call->bus, m);
390 static int synthetic_reply_return_strv(sd_bus_message *call, char **l) {
391 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
396 r = sd_bus_message_new_method_return(call, &m);
398 return synthetic_reply_method_errno(call, r, NULL);
400 r = sd_bus_message_append_strv(m, l);
402 return synthetic_reply_method_errno(call, r, NULL);
404 return synthetic_driver_send(call->bus, m);
407 static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
408 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
415 r = sd_bus_get_name_creds(bus, name, mask, &c);
416 if (r == -ESRCH || r == -ENXIO)
417 return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
421 if ((c->mask & mask) != mask)
430 static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
438 r = sd_bus_message_read(m, "s", &name);
442 return get_creds_by_name(bus, name, mask, _creds, error);
445 static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred, Set *owned_names) {
455 if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
458 /* The "Hello()" call is is handled in process_hello() */
460 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
462 if (!sd_bus_message_has_signature(m, ""))
463 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
465 return synthetic_reply_method_return(m, "s",
466 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
467 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
469 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
470 " <method name=\"Introspect\">\n"
471 " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
474 " <interface name=\"org.freedesktop.DBus\">\n"
475 " <method name=\"AddMatch\">\n"
476 " <arg type=\"s\" direction=\"in\"/>\n"
478 " <method name=\"RemoveMatch\">\n"
479 " <arg type=\"s\" direction=\"in\"/>\n"
481 " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
482 " <arg type=\"s\" direction=\"in\"/>\n"
483 " <arg type=\"ay\" direction=\"out\"/>\n"
485 " <method name=\"GetConnectionUnixProcessID\">\n"
486 " <arg type=\"s\" direction=\"in\"/>\n"
487 " <arg type=\"u\" direction=\"out\"/>\n"
489 " <method name=\"GetConnectionUnixUser\">\n"
490 " <arg type=\"s\" direction=\"in\"/>\n"
491 " <arg type=\"u\" direction=\"out\"/>\n"
493 " <method name=\"GetId\">\n"
494 " <arg type=\"s\" direction=\"out\"/>\n"
496 " <method name=\"GetNameOwner\">\n"
497 " <arg type=\"s\" direction=\"in\"/>\n"
498 " <arg type=\"s\" direction=\"out\"/>\n"
500 " <method name=\"Hello\">\n"
501 " <arg type=\"s\" direction=\"out\"/>\n"
503 " <method name=\"ListActivatableNames\">\n"
504 " <arg type=\"as\" direction=\"out\"/>\n"
506 " <method name=\"ListNames\">\n"
507 " <arg type=\"as\" direction=\"out\"/>\n"
509 " <method name=\"ListQueuedOwners\">\n"
510 " <arg type=\"s\" direction=\"in\"/>\n"
511 " <arg type=\"as\" direction=\"out\"/>\n"
513 " <method name=\"NameHasOwner\">\n"
514 " <arg type=\"s\" direction=\"in\"/>\n"
515 " <arg type=\"b\" direction=\"out\"/>\n"
517 " <method name=\"ReleaseName\">\n"
518 " <arg type=\"s\" direction=\"in\"/>\n"
519 " <arg type=\"u\" direction=\"out\"/>\n"
521 " <method name=\"ReloadConfig\">\n"
523 " <method name=\"RequestName\">\n"
524 " <arg type=\"s\" direction=\"in\"/>\n"
525 " <arg type=\"u\" direction=\"in\"/>\n"
526 " <arg type=\"u\" direction=\"out\"/>\n"
528 " <method name=\"StartServiceByName\">\n"
529 " <arg type=\"s\" direction=\"in\"/>\n"
530 " <arg type=\"u\" direction=\"in\"/>\n"
531 " <arg type=\"u\" direction=\"out\"/>\n"
533 " <method name=\"UpdateActivationEnvironment\">\n"
534 " <arg type=\"a{ss}\" direction=\"in\"/>\n"
536 " <signal name=\"NameAcquired\">\n"
537 " <arg type=\"s\"/>\n"
539 " <signal name=\"NameLost\">\n"
540 " <arg type=\"s\"/>\n"
542 " <signal name=\"NameOwnerChanged\">\n"
543 " <arg type=\"s\"/>\n"
544 " <arg type=\"s\"/>\n"
545 " <arg type=\"s\"/>\n"
550 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
553 if (!sd_bus_message_has_signature(m, "s"))
554 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
556 r = sd_bus_message_read(m, "s", &match);
558 return synthetic_reply_method_errno(m, r, NULL);
560 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
562 return synthetic_reply_method_errno(m, r, NULL);
564 return synthetic_reply_method_return(m, NULL);
566 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
569 if (!sd_bus_message_has_signature(m, "s"))
570 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
572 r = sd_bus_message_read(m, "s", &match);
574 return synthetic_reply_method_errno(m, r, NULL);
576 r = bus_remove_match_by_string(a, match, NULL, NULL);
578 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
580 return synthetic_reply_method_errno(m, r, NULL);
582 return synthetic_reply_method_return(m, NULL);
584 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
585 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
586 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
588 if (!sd_bus_message_has_signature(m, "s"))
589 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
591 r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
593 return synthetic_reply_method_errno(m, r, &error);
595 return synthetic_reply_method_return(m, "y", creds->label, strlen(creds->label));
597 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
598 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
599 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
601 if (!sd_bus_message_has_signature(m, "s"))
602 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
604 r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error);
606 return synthetic_reply_method_errno(m, r, &error);
608 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
610 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
611 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
612 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
614 if (!sd_bus_message_has_signature(m, "s"))
615 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
617 r = get_creds_by_message(a, m, SD_BUS_CREDS_UID, &creds, &error);
619 return synthetic_reply_method_errno(m, r, &error);
621 return synthetic_reply_method_return(m, "u", (uint32_t) creds->uid);
623 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
624 sd_id128_t server_id;
625 char buf[SD_ID128_STRING_MAX];
627 if (!sd_bus_message_has_signature(m, ""))
628 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
630 r = sd_bus_get_bus_id(a, &server_id);
632 return synthetic_reply_method_errno(m, r, NULL);
634 return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
636 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
638 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
639 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
641 if (!sd_bus_message_has_signature(m, "s"))
642 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
644 r = sd_bus_message_read(m, "s", &name);
646 return synthetic_reply_method_errno(m, r, NULL);
648 if (streq(name, "org.freedesktop.DBus"))
649 return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
651 r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
653 return synthetic_reply_method_errno(m, r, &error);
655 return synthetic_reply_method_return(m, "s", creds->unique_name);
657 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
658 _cleanup_strv_free_ char **names = NULL;
660 if (!sd_bus_message_has_signature(m, ""))
661 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
663 r = sd_bus_list_names(a, NULL, &names);
665 return synthetic_reply_method_errno(m, r, NULL);
667 /* Let's sort the names list to make it stable */
670 return synthetic_reply_return_strv(m, names);
672 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
673 _cleanup_strv_free_ char **names = NULL;
675 if (!sd_bus_message_has_signature(m, ""))
676 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
678 r = sd_bus_list_names(a, &names, NULL);
680 return synthetic_reply_method_errno(m, r, NULL);
682 r = strv_extend(&names, "org.freedesktop.DBus");
684 return synthetic_reply_method_errno(m, r, NULL);
686 /* Let's sort the names list to make it stable */
689 return synthetic_reply_return_strv(m, names);
691 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
692 struct kdbus_cmd_name_list cmd = {};
693 struct kdbus_name_list *name_list;
694 struct kdbus_name_info *name;
695 _cleanup_strv_free_ char **owners = NULL;
696 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
700 if (!sd_bus_message_has_signature(m, "s"))
701 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
703 r = sd_bus_message_read(m, "s", &arg0);
705 return synthetic_reply_method_errno(m, r, NULL);
707 r = sd_bus_get_name_creds(a, arg0, 0, NULL);
708 if (r == -ESRCH || r == -ENXIO) {
709 sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0);
710 return synthetic_reply_method_errno(m, r, &error);
713 return synthetic_reply_method_errno(m, r, NULL);
715 cmd.flags = KDBUS_NAME_LIST_QUEUED;
716 r = ioctl(a->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
718 return synthetic_reply_method_errno(m, -errno, NULL);
720 name_list = (struct kdbus_name_list *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
722 KDBUS_ITEM_FOREACH(name, name_list, names) {
723 const char *entry_name = NULL;
724 struct kdbus_item *item;
727 KDBUS_ITEM_FOREACH(item, name, items)
728 if (item->type == KDBUS_ITEM_OWNED_NAME)
729 entry_name = item->name.name;
731 if (!streq_ptr(entry_name, arg0))
734 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
739 r = strv_consume(&owners, n);
746 r = bus_kernel_cmd_free(a, cmd.offset);
748 return synthetic_reply_method_errno(m, r, NULL);
751 return synthetic_reply_method_errno(m, err, NULL);
753 return synthetic_reply_return_strv(m, owners);
755 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
758 if (!sd_bus_message_has_signature(m, "s"))
759 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
761 r = sd_bus_message_read(m, "s", &name);
763 return synthetic_reply_method_errno(m, r, NULL);
765 if (streq(name, "org.freedesktop.DBus"))
766 return synthetic_reply_method_return(m, "b", true);
768 r = sd_bus_get_name_creds(a, name, 0, NULL);
769 if (r < 0 && r != -ESRCH && r != -ENXIO)
770 return synthetic_reply_method_errno(m, r, NULL);
772 return synthetic_reply_method_return(m, "b", r >= 0);
774 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
777 if (!sd_bus_message_has_signature(m, "s"))
778 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
780 r = sd_bus_message_read(m, "s", &name);
782 return synthetic_reply_method_errno(m, r, NULL);
784 r = sd_bus_release_name(a, name);
787 return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
788 if (r == -EADDRINUSE)
789 return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
791 return synthetic_reply_method_errno(m, r, NULL);
794 set_remove(owned_names, (char*) name);
796 return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
798 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
799 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
801 if (!sd_bus_message_has_signature(m, ""))
802 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
804 r = sd_bus_error_setf(&error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
806 return synthetic_reply_method_errno(m, r, &error);
808 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
810 uint32_t flags, param;
813 if (!sd_bus_message_has_signature(m, "su"))
814 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
816 r = sd_bus_message_read(m, "su", &name, &flags);
818 return synthetic_reply_method_errno(m, r, NULL);
820 if (policy && !policy_check_own(policy, ucred->uid, ucred->gid, name))
821 return synthetic_reply_method_errno(m, -EPERM, NULL);
823 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
824 return synthetic_reply_method_errno(m, -EINVAL, NULL);
827 if (flags & BUS_NAME_ALLOW_REPLACEMENT)
828 param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
829 if (flags & BUS_NAME_REPLACE_EXISTING)
830 param |= SD_BUS_NAME_REPLACE_EXISTING;
831 if (!(flags & BUS_NAME_DO_NOT_QUEUE))
832 param |= SD_BUS_NAME_QUEUE;
834 r = set_put_strdup(owned_names, name);
836 return synthetic_reply_method_errno(m, r, NULL);
838 r = sd_bus_request_name(a, name, param);
841 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
843 set_remove(owned_names, (char*) name);
846 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
847 return synthetic_reply_method_errno(m, r, NULL);
853 return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
855 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
857 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
858 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
862 if (!sd_bus_message_has_signature(m, "su"))
863 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
865 r = sd_bus_message_read(m, "su", &name, &flags);
867 return synthetic_reply_method_errno(m, r, NULL);
870 return synthetic_reply_method_errno(m, -EINVAL, NULL);
872 r = sd_bus_get_name_creds(a, name, 0, NULL);
873 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
874 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
876 return synthetic_reply_method_errno(m, r, NULL);
878 r = sd_bus_message_new_method_call(
883 "org.freedesktop.DBus.Peer",
886 return synthetic_reply_method_errno(m, r, NULL);
888 r = sd_bus_send(a, msg, NULL);
890 return synthetic_reply_method_errno(m, r, NULL);
892 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
894 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
895 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
896 _cleanup_strv_free_ char **args = NULL;
898 if (!sd_bus_message_has_signature(m, "a{ss}"))
899 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
901 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
903 return synthetic_reply_method_errno(m, r, NULL);
905 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
906 _cleanup_free_ char *s = NULL;
910 r = sd_bus_message_read(m, "ss", &key, &value);
912 return synthetic_reply_method_errno(m, r, NULL);
914 s = strjoin(key, "=", value, NULL);
916 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
918 r = strv_extend(&args, s);
920 return synthetic_reply_method_errno(m, r, NULL);
922 r = sd_bus_message_exit_container(m);
924 return synthetic_reply_method_errno(m, r, NULL);
927 r = sd_bus_message_exit_container(m);
929 return synthetic_reply_method_errno(m, r, NULL);
932 return synthetic_reply_method_errno(m, -EINVAL, NULL);
934 r = sd_bus_message_new_method_call(
937 "org.freedesktop.systemd1",
938 "/org/freedesktop/systemd1",
939 "org.freedesktop.systemd1.Manager",
942 return synthetic_reply_method_errno(m, r, NULL);
944 r = sd_bus_message_append_strv(msg, args);
946 return synthetic_reply_method_errno(m, r, NULL);
948 r = sd_bus_call(a, msg, 0, NULL, NULL);
950 return synthetic_reply_method_errno(m, r, NULL);
952 return synthetic_reply_method_return(m, NULL);
955 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
957 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
959 return synthetic_reply_method_errno(m, r, &error);
963 static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
973 if (from->is_kernel) {
974 uid_t sender_uid = UID_INVALID;
975 gid_t sender_gid = GID_INVALID;
976 char **sender_names = NULL;
977 bool granted = false;
979 /* Driver messages are always OK */
980 if (streq_ptr(m->sender, "org.freedesktop.DBus"))
983 /* The message came from the kernel, and is sent to our legacy client. */
984 r = sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
988 (void) sd_bus_creds_get_uid(&m->creds, &sender_uid);
989 (void) sd_bus_creds_get_gid(&m->creds, &sender_gid);
991 /* First check whether the sender can send the message to our name */
992 if (set_isempty(owned_names)) {
993 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, NULL, m->path, m->interface, m->member))
999 SET_FOREACH(n, owned_names, i)
1000 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, n, m->path, m->interface, m->member)) {
1007 /* Then check whether us (the recipient) can recieve from the sender's name */
1008 if (strv_isempty(sender_names)) {
1009 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1014 STRV_FOREACH(n, sender_names) {
1015 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member))
1021 /* Return an error back to the caller */
1022 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1023 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
1025 /* Return 1, indicating that the message shall not be processed any further */
1029 if (to->is_kernel) {
1030 _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL;
1031 uid_t destination_uid = UID_INVALID;
1032 gid_t destination_gid = GID_INVALID;
1033 const char *destination_unique = NULL;
1034 char **destination_names = NULL;
1035 bool granted = false;
1037 /* Driver messages are always OK */
1038 if (streq_ptr(m->destination, "org.freedesktop.DBus"))
1041 /* The message came from the legacy client, and is sent to kdbus. */
1042 if (m->destination) {
1043 r = bus_get_name_creds_kdbus(to, m->destination,
1044 SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
1045 SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID,
1046 true, &destination_creds);
1050 r = sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
1054 r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
1058 (void) sd_bus_creds_get_uid(destination_creds, &destination_uid);
1059 (void) sd_bus_creds_get_gid(destination_creds, &destination_gid);
1062 /* First check if we (the sender) can send to this name */
1063 if (strv_isempty(destination_names)) {
1064 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1069 STRV_FOREACH(n, destination_names) {
1070 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member)) {
1072 /* If we made a receiver decision,
1073 then remember which name's policy
1074 we used, and to which unique ID it
1075 mapped when we made the
1076 decision. Then, let's pass this to
1077 the kernel when sending the
1078 message, so that it refuses the
1079 operation should the name and
1080 unique ID not map to each other
1083 r = free_and_strdup(&m->destination_ptr, *n);
1087 r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
1097 /* Then check if the recipient can receive from our name */
1099 if (set_isempty(owned_names)) {
1100 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, NULL, m->path, m->interface, m->member))
1106 SET_FOREACH(n, owned_names, i)
1107 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, n, m->path, m->interface, m->member))
1112 /* Return an error back to the caller */
1113 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1114 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
1116 /* Return 1, indicating that the message shall not be processed any further */
1123 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
1124 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
1133 /* As reaction to hello we need to respond with two messages:
1134 * the callback reply and the NameAcquired for the unique
1135 * name, since hello is otherwise obsolete on kdbus. */
1138 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1139 streq_ptr(m->destination, "org.freedesktop.DBus");
1146 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1151 log_error("Got duplicate hello, aborting.");
1160 r = sd_bus_message_new_method_return(m, &n);
1162 return log_error_errno(r, "Failed to generate HELLO reply: %m");
1164 r = sd_bus_message_append(n, "s", a->unique_name);
1166 return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
1168 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1170 return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
1172 r = bus_seal_synthetic_message(b, n);
1174 return log_error_errno(r, "Failed to seal HELLO reply: %m");
1176 r = sd_bus_send(b, n, NULL);
1178 return log_error_errno(r, "Failed to send HELLO reply: %m");
1180 n = sd_bus_message_unref(n);
1181 r = sd_bus_message_new_signal(
1184 "/org/freedesktop/DBus",
1185 "org.freedesktop.DBus",
1188 return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
1190 r = sd_bus_message_append(n, "s", a->unique_name);
1192 return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
1194 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1196 return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
1198 r = bus_seal_synthetic_message(b, n);
1200 return log_error_errno(r, "Failed to seal NameAcquired message: %m");
1202 r = sd_bus_send(b, n, NULL);
1204 return log_error_errno(r, "Failed to send NameAcquired message: %m");
1209 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1210 char **well_known = NULL;
1220 /* We will change the sender of messages from the bus driver
1221 * so that they originate from the bus driver. This is a
1222 * speciality originating from dbus1, where the bus driver did
1223 * not have a unique id, but only the well-known name. */
1225 c = sd_bus_message_get_creds(m);
1229 r = sd_bus_creds_get_well_known_names(c, &well_known);
1233 if (strv_contains(well_known, "org.freedesktop.DBus"))
1234 m->sender = "org.freedesktop.DBus";
1239 static int mac_smack_apply_label_and_drop_cap_mac_admin(pid_t its_pid, const char *new_label) {
1243 if (!mac_smack_use())
1246 if (new_label && its_pid > 0)
1247 r = mac_smack_apply_pid(its_pid, new_label);
1249 k = drop_capability(CAP_MAC_ADMIN);
1250 return r < 0 ? r : k;
1256 int main(int argc, char *argv[]) {
1258 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1259 sd_id128_t server_id;
1260 int r, in_fd, out_fd;
1261 bool got_hello = false;
1263 struct ucred ucred = {};
1264 _cleanup_free_ char *peersec = NULL;
1265 Policy policy_buffer = {}, *policy = NULL;
1266 _cleanup_set_free_free_ Set *owned_names = NULL;
1268 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1269 log_parse_environment();
1272 r = parse_argv(argc, argv);
1276 r = sd_listen_fds(0);
1278 in_fd = STDIN_FILENO;
1279 out_fd = STDOUT_FILENO;
1280 } else if (r == 1) {
1281 in_fd = SD_LISTEN_FDS_START;
1282 out_fd = SD_LISTEN_FDS_START;
1284 log_error("Illegal number of file descriptors passed");
1289 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1290 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1293 (void) getpeercred(in_fd, &ucred);
1294 (void) getpeersec(in_fd, &peersec);
1296 r = mac_smack_apply_label_and_drop_cap_mac_admin(getpid(), peersec);
1298 log_warning_errno(r, "Failed to set SMACK label (%s) and drop CAP_MAC_ADMIN: %m", peersec);
1301 if (arg_drop_privileges) {
1302 const char *user = "systemd-bus-proxy";
1306 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1308 log_error_errno(r, "Cannot resolve user name %s: %m", user);
1312 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1317 owned_names = set_new(&string_hash_ops);
1325 log_error_errno(r, "Failed to allocate bus: %m");
1329 r = sd_bus_set_description(a, "sd-proxy");
1331 log_error_errno(r, "Failed to set bus name: %m");
1335 r = sd_bus_set_address(a, arg_address);
1337 log_error_errno(r, "Failed to set address to connect to: %m");
1341 r = sd_bus_negotiate_fds(a, is_unix);
1343 log_error_errno(r, "Failed to set FD negotiation: %m");
1347 r = sd_bus_negotiate_creds(a, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1349 log_error_errno(r, "Failed to set credential negotiation: %m");
1353 if (ucred.pid > 0) {
1354 a->fake_pids.pid = ucred.pid;
1355 a->fake_pids_valid = true;
1357 a->fake_creds.uid = ucred.uid;
1358 a->fake_creds.euid = UID_INVALID;
1359 a->fake_creds.suid = UID_INVALID;
1360 a->fake_creds.fsuid = UID_INVALID;
1361 a->fake_creds.gid = ucred.gid;
1362 a->fake_creds.egid = GID_INVALID;
1363 a->fake_creds.sgid = GID_INVALID;
1364 a->fake_creds.fsgid = GID_INVALID;
1365 a->fake_creds_valid = true;
1369 a->fake_label = peersec;
1373 a->manual_peer_interface = true;
1375 r = sd_bus_start(a);
1377 log_error_errno(r, "Failed to start bus client: %m");
1381 r = sd_bus_get_bus_id(a, &server_id);
1383 log_error_errno(r, "Failed to get server ID: %m");
1388 if (!arg_configuration) {
1391 r = sd_bus_get_scope(a, &scope);
1393 log_error_errno(r, "Couldn't determine bus scope: %m");
1397 if (streq(scope, "system"))
1398 arg_configuration = strv_new(
1399 "/etc/dbus-1/system.conf",
1400 "/etc/dbus-1/system.d/",
1401 "/etc/dbus-1/system-local.conf",
1403 else if (streq(scope, "user"))
1404 arg_configuration = strv_new(
1405 "/etc/dbus-1/session.conf",
1406 "/etc/dbus-1/session.d/",
1407 "/etc/dbus-1/session-local.conf",
1410 log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope);
1414 if (!arg_configuration) {
1420 r = policy_load(&policy_buffer, arg_configuration);
1422 log_error_errno(r, "Failed to load policy: %m");
1426 policy = &policy_buffer;
1427 /* policy_dump(policy); */
1429 if (!policy_check_hello(policy, ucred.uid, ucred.gid)) {
1430 r = log_error_errno(EPERM, "Policy denied connection.");
1437 log_error_errno(r, "Failed to allocate bus: %m");
1441 r = sd_bus_set_fd(b, in_fd, out_fd);
1443 log_error_errno(r, "Failed to set fds: %m");
1447 r = sd_bus_set_server(b, 1, server_id);
1449 log_error_errno(r, "Failed to set server mode: %m");
1453 r = sd_bus_negotiate_fds(b, is_unix);
1455 log_error_errno(r, "Failed to set FD negotiation: %m");
1459 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1461 log_error_errno(r, "Failed to set credential negotiation: %m");
1465 r = sd_bus_set_anonymous(b, true);
1467 log_error_errno(r, "Failed to set anonymous authentication: %m");
1471 b->manual_peer_interface = true;
1473 r = sd_bus_start(b);
1475 log_error_errno(r, "Failed to start bus client: %m");
1479 r = rename_service(a, b);
1481 log_debug_errno(r, "Failed to rename process: %m");
1484 _cleanup_free_ char *match = NULL;
1487 r = sd_bus_get_unique_name(a, &unique);
1489 log_error_errno(r, "Failed to get unique name: %m");
1493 match = strjoin("type='signal',"
1494 "sender='org.freedesktop.DBus',"
1495 "path='/org/freedesktop/DBus',"
1496 "interface='org.freedesktop.DBus',"
1497 "member='NameOwnerChanged',"
1507 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1509 log_error_errno(r, "Failed to add match for NameLost: %m");
1514 match = strjoin("type='signal',"
1515 "sender='org.freedesktop.DBus',"
1516 "path='/org/freedesktop/DBus',"
1517 "interface='org.freedesktop.DBus',"
1518 "member='NameOwnerChanged',"
1528 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1530 log_error_errno(r, "Failed to add match for NameAcquired: %m");
1536 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1537 int events_a, events_b, fd;
1538 uint64_t timeout_a, timeout_b, t;
1539 struct timespec _ts, *ts;
1540 struct pollfd *pollfd;
1544 /* Read messages from bus, to pass them on to our client */
1546 r = sd_bus_process(a, &m);
1548 /* treat 'connection reset by peer' as clean exit condition */
1549 if (r == -ECONNRESET)
1552 log_error_errno(r, "Failed to process bus a: %m");
1558 bool processed = false;
1560 /* We officially got EOF, let's quit */
1561 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1566 k = synthesize_name_acquired(a, b, m);
1569 log_error_errno(r, "Failed to synthesize message: %m");
1576 k = process_policy(a, b, m, policy, &ucred, owned_names);
1579 log_error_errno(r, "Failed to process policy: %m");
1588 k = sd_bus_send(b, m, NULL);
1590 if (k == -ECONNRESET)
1594 log_error_errno(r, "Failed to send message to client: %m");
1607 /* Read messages from our client, to pass them on to the bus */
1608 r = sd_bus_process(b, &m);
1610 /* treat 'connection reset by peer' as clean exit condition */
1611 if (r == -ECONNRESET)
1614 log_error_errno(r, "Failed to process bus b: %m");
1620 bool processed = false;
1622 /* We officially got EOF, let's quit */
1623 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1628 k = process_hello(a, b, m, &got_hello);
1631 log_error_errno(r, "Failed to process HELLO: %m");
1639 k = process_driver(a, b, m, policy, &ucred, owned_names);
1642 log_error_errno(r, "Failed to process driver calls: %m");
1653 k = process_policy(b, a, m, policy, &ucred, owned_names);
1656 log_error_errno(r, "Failed to process policy: %m");
1665 k = sd_bus_send(a, m, NULL);
1668 /* The name database changed since the policy check, hence let's check again */
1670 else if (k == -ECONNRESET)
1674 log_error_errno(r, "Failed to send message to bus: %m");
1690 fd = sd_bus_get_fd(a);
1692 log_error_errno(r, "Failed to get fd: %m");
1696 events_a = sd_bus_get_events(a);
1698 log_error_errno(r, "Failed to get events mask: %m");
1702 r = sd_bus_get_timeout(a, &timeout_a);
1704 log_error_errno(r, "Failed to get timeout: %m");
1708 events_b = sd_bus_get_events(b);
1710 log_error_errno(r, "Failed to get events mask: %m");
1714 r = sd_bus_get_timeout(b, &timeout_b);
1716 log_error_errno(r, "Failed to get timeout: %m");
1721 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1724 if (t == (uint64_t) -1)
1729 nw = now(CLOCK_MONOTONIC);
1735 ts = timespec_store(&_ts, t);
1738 pollfd = (struct pollfd[3]) {
1739 {.fd = fd, .events = events_a, },
1740 {.fd = in_fd, .events = events_b & POLLIN, },
1741 {.fd = out_fd, .events = events_b & POLLOUT, }
1744 r = ppoll(pollfd, 3, ts, NULL);
1746 log_error_errno(errno, "ppoll() failed: %m");
1754 "STATUS=Shutting down.");
1756 policy_free(&policy_buffer);
1757 strv_free(arg_configuration);
1760 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;