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 handle_policy_error(sd_bus_message *m, int r) {
964 if (r == -ESRCH || r == -ENXIO)
965 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination);
970 static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
980 if (from->is_kernel) {
981 uid_t sender_uid = UID_INVALID;
982 gid_t sender_gid = GID_INVALID;
983 char **sender_names = NULL;
984 bool granted = false;
986 /* Driver messages are always OK */
987 if (streq_ptr(m->sender, "org.freedesktop.DBus"))
990 /* The message came from the kernel, and is sent to our legacy client. */
991 sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
993 (void) sd_bus_creds_get_uid(&m->creds, &sender_uid);
994 (void) sd_bus_creds_get_gid(&m->creds, &sender_gid);
996 /* First check whether the sender can send the message to our name */
997 if (set_isempty(owned_names)) {
998 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, NULL, m->path, m->interface, m->member))
1004 SET_FOREACH(n, owned_names, i)
1005 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, n, m->path, m->interface, m->member)) {
1012 /* Then check whether us (the recipient) can recieve from the sender's name */
1013 if (strv_isempty(sender_names)) {
1014 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1019 STRV_FOREACH(n, sender_names) {
1020 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member))
1026 /* Return an error back to the caller */
1027 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1028 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
1030 /* Return 1, indicating that the message shall not be processed any further */
1034 if (to->is_kernel) {
1035 _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL;
1036 uid_t destination_uid = UID_INVALID;
1037 gid_t destination_gid = GID_INVALID;
1038 const char *destination_unique = NULL;
1039 char **destination_names = NULL;
1040 bool granted = false;
1042 /* Driver messages are always OK */
1043 if (streq_ptr(m->destination, "org.freedesktop.DBus"))
1046 /* The message came from the legacy client, and is sent to kdbus. */
1047 if (m->destination) {
1048 r = bus_get_name_creds_kdbus(to, m->destination,
1049 SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
1050 SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID,
1051 true, &destination_creds);
1053 return handle_policy_error(m, r);
1055 r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
1057 return handle_policy_error(m, r);
1059 sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
1061 (void) sd_bus_creds_get_uid(destination_creds, &destination_uid);
1062 (void) sd_bus_creds_get_gid(destination_creds, &destination_gid);
1065 /* First check if we (the sender) can send to this name */
1066 if (strv_isempty(destination_names)) {
1067 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1072 STRV_FOREACH(n, destination_names) {
1073 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member)) {
1075 /* If we made a receiver decision,
1076 then remember which name's policy
1077 we used, and to which unique ID it
1078 mapped when we made the
1079 decision. Then, let's pass this to
1080 the kernel when sending the
1081 message, so that it refuses the
1082 operation should the name and
1083 unique ID not map to each other
1086 r = free_and_strdup(&m->destination_ptr, *n);
1090 r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
1100 /* Then check if the recipient can receive from our name */
1102 if (set_isempty(owned_names)) {
1103 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, NULL, m->path, m->interface, m->member))
1109 SET_FOREACH(n, owned_names, i)
1110 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, n, m->path, m->interface, m->member))
1115 /* Return an error back to the caller */
1116 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1117 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
1119 /* Return 1, indicating that the message shall not be processed any further */
1126 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
1127 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
1136 /* As reaction to hello we need to respond with two messages:
1137 * the callback reply and the NameAcquired for the unique
1138 * name, since hello is otherwise obsolete on kdbus. */
1141 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1142 streq_ptr(m->destination, "org.freedesktop.DBus");
1149 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1154 log_error("Got duplicate hello, aborting.");
1163 r = sd_bus_message_new_method_return(m, &n);
1165 return log_error_errno(r, "Failed to generate HELLO reply: %m");
1167 r = sd_bus_message_append(n, "s", a->unique_name);
1169 return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
1171 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1173 return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
1175 r = bus_seal_synthetic_message(b, n);
1177 return log_error_errno(r, "Failed to seal HELLO reply: %m");
1179 r = sd_bus_send(b, n, NULL);
1181 return log_error_errno(r, "Failed to send HELLO reply: %m");
1183 n = sd_bus_message_unref(n);
1184 r = sd_bus_message_new_signal(
1187 "/org/freedesktop/DBus",
1188 "org.freedesktop.DBus",
1191 return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
1193 r = sd_bus_message_append(n, "s", a->unique_name);
1195 return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
1197 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1199 return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
1201 r = bus_seal_synthetic_message(b, n);
1203 return log_error_errno(r, "Failed to seal NameAcquired message: %m");
1205 r = sd_bus_send(b, n, NULL);
1207 return log_error_errno(r, "Failed to send NameAcquired message: %m");
1212 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1213 char **well_known = NULL;
1223 /* We will change the sender of messages from the bus driver
1224 * so that they originate from the bus driver. This is a
1225 * speciality originating from dbus1, where the bus driver did
1226 * not have a unique id, but only the well-known name. */
1228 c = sd_bus_message_get_creds(m);
1232 r = sd_bus_creds_get_well_known_names(c, &well_known);
1236 if (strv_contains(well_known, "org.freedesktop.DBus"))
1237 m->sender = "org.freedesktop.DBus";
1242 static int mac_smack_apply_label_and_drop_cap_mac_admin(pid_t its_pid, const char *new_label) {
1246 if (!mac_smack_use())
1249 if (new_label && its_pid > 0)
1250 r = mac_smack_apply_pid(its_pid, new_label);
1252 k = drop_capability(CAP_MAC_ADMIN);
1253 return r < 0 ? r : k;
1259 int main(int argc, char *argv[]) {
1261 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1262 sd_id128_t server_id;
1263 int r, in_fd, out_fd;
1264 bool got_hello = false;
1266 struct ucred ucred = {};
1267 _cleanup_free_ char *peersec = NULL;
1268 Policy policy_buffer = {}, *policy = NULL;
1269 _cleanup_set_free_free_ Set *owned_names = NULL;
1271 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1272 log_parse_environment();
1275 r = parse_argv(argc, argv);
1279 r = sd_listen_fds(0);
1281 in_fd = STDIN_FILENO;
1282 out_fd = STDOUT_FILENO;
1283 } else if (r == 1) {
1284 in_fd = SD_LISTEN_FDS_START;
1285 out_fd = SD_LISTEN_FDS_START;
1287 log_error("Illegal number of file descriptors passed");
1292 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1293 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1296 (void) getpeercred(in_fd, &ucred);
1297 (void) getpeersec(in_fd, &peersec);
1299 r = mac_smack_apply_label_and_drop_cap_mac_admin(getpid(), peersec);
1301 log_warning_errno(r, "Failed to set SMACK label (%s) and drop CAP_MAC_ADMIN: %m", peersec);
1304 if (arg_drop_privileges) {
1305 const char *user = "systemd-bus-proxy";
1309 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1311 log_error_errno(r, "Cannot resolve user name %s: %m", user);
1315 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1320 owned_names = set_new(&string_hash_ops);
1328 log_error_errno(r, "Failed to allocate bus: %m");
1332 r = sd_bus_set_description(a, "sd-proxy");
1334 log_error_errno(r, "Failed to set bus name: %m");
1338 r = sd_bus_set_address(a, arg_address);
1340 log_error_errno(r, "Failed to set address to connect to: %m");
1344 r = sd_bus_negotiate_fds(a, is_unix);
1346 log_error_errno(r, "Failed to set FD negotiation: %m");
1350 r = sd_bus_negotiate_creds(a, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1352 log_error_errno(r, "Failed to set credential negotiation: %m");
1356 if (ucred.pid > 0) {
1357 a->fake_pids.pid = ucred.pid;
1358 a->fake_pids_valid = true;
1360 a->fake_creds.uid = ucred.uid;
1361 a->fake_creds.euid = UID_INVALID;
1362 a->fake_creds.suid = UID_INVALID;
1363 a->fake_creds.fsuid = UID_INVALID;
1364 a->fake_creds.gid = ucred.gid;
1365 a->fake_creds.egid = GID_INVALID;
1366 a->fake_creds.sgid = GID_INVALID;
1367 a->fake_creds.fsgid = GID_INVALID;
1368 a->fake_creds_valid = true;
1372 a->fake_label = peersec;
1376 a->manual_peer_interface = true;
1378 r = sd_bus_start(a);
1380 log_error_errno(r, "Failed to start bus client: %m");
1384 r = sd_bus_get_bus_id(a, &server_id);
1386 log_error_errno(r, "Failed to get server ID: %m");
1391 if (!arg_configuration) {
1394 r = sd_bus_get_scope(a, &scope);
1396 log_error_errno(r, "Couldn't determine bus scope: %m");
1400 if (streq(scope, "system"))
1401 arg_configuration = strv_new(
1402 "/etc/dbus-1/system.conf",
1403 "/etc/dbus-1/system.d/",
1404 "/etc/dbus-1/system-local.conf",
1406 else if (streq(scope, "user"))
1407 arg_configuration = strv_new(
1408 "/etc/dbus-1/session.conf",
1409 "/etc/dbus-1/session.d/",
1410 "/etc/dbus-1/session-local.conf",
1413 log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope);
1417 if (!arg_configuration) {
1423 r = policy_load(&policy_buffer, arg_configuration);
1425 log_error_errno(r, "Failed to load policy: %m");
1429 policy = &policy_buffer;
1430 /* policy_dump(policy); */
1432 if (!policy_check_hello(policy, ucred.uid, ucred.gid)) {
1433 r = log_error_errno(EPERM, "Policy denied connection.");
1440 log_error_errno(r, "Failed to allocate bus: %m");
1444 r = sd_bus_set_fd(b, in_fd, out_fd);
1446 log_error_errno(r, "Failed to set fds: %m");
1450 r = sd_bus_set_server(b, 1, server_id);
1452 log_error_errno(r, "Failed to set server mode: %m");
1456 r = sd_bus_negotiate_fds(b, is_unix);
1458 log_error_errno(r, "Failed to set FD negotiation: %m");
1462 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1464 log_error_errno(r, "Failed to set credential negotiation: %m");
1468 r = sd_bus_set_anonymous(b, true);
1470 log_error_errno(r, "Failed to set anonymous authentication: %m");
1474 b->manual_peer_interface = true;
1476 r = sd_bus_start(b);
1478 log_error_errno(r, "Failed to start bus client: %m");
1482 r = rename_service(a, b);
1484 log_debug_errno(r, "Failed to rename process: %m");
1487 _cleanup_free_ char *match = NULL;
1490 r = sd_bus_get_unique_name(a, &unique);
1492 log_error_errno(r, "Failed to get unique name: %m");
1496 match = strjoin("type='signal',"
1497 "sender='org.freedesktop.DBus',"
1498 "path='/org/freedesktop/DBus',"
1499 "interface='org.freedesktop.DBus',"
1500 "member='NameOwnerChanged',"
1510 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1512 log_error_errno(r, "Failed to add match for NameLost: %m");
1517 match = strjoin("type='signal',"
1518 "sender='org.freedesktop.DBus',"
1519 "path='/org/freedesktop/DBus',"
1520 "interface='org.freedesktop.DBus',"
1521 "member='NameOwnerChanged',"
1531 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1533 log_error_errno(r, "Failed to add match for NameAcquired: %m");
1539 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1540 int events_a, events_b, fd;
1541 uint64_t timeout_a, timeout_b, t;
1542 struct timespec _ts, *ts;
1543 struct pollfd *pollfd;
1547 /* Read messages from bus, to pass them on to our client */
1549 r = sd_bus_process(a, &m);
1551 /* treat 'connection reset by peer' as clean exit condition */
1552 if (r == -ECONNRESET)
1555 log_error_errno(r, "Failed to process bus a: %m");
1561 bool processed = false;
1563 /* We officially got EOF, let's quit */
1564 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1569 k = synthesize_name_acquired(a, b, m);
1572 log_error_errno(r, "Failed to synthesize message: %m");
1579 k = process_policy(a, b, m, policy, &ucred, owned_names);
1582 log_error_errno(r, "Failed to process policy: %m");
1591 k = sd_bus_send(b, m, NULL);
1593 if (k == -ECONNRESET)
1597 log_error_errno(r, "Failed to send message to client: %m");
1610 /* Read messages from our client, to pass them on to the bus */
1611 r = sd_bus_process(b, &m);
1613 /* treat 'connection reset by peer' as clean exit condition */
1614 if (r == -ECONNRESET)
1617 log_error_errno(r, "Failed to process bus b: %m");
1623 bool processed = false;
1625 /* We officially got EOF, let's quit */
1626 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1631 k = process_hello(a, b, m, &got_hello);
1634 log_error_errno(r, "Failed to process HELLO: %m");
1642 k = process_driver(a, b, m, policy, &ucred, owned_names);
1645 log_error_errno(r, "Failed to process driver calls: %m");
1656 k = process_policy(b, a, m, policy, &ucred, owned_names);
1659 log_error_errno(r, "Failed to process policy: %m");
1668 k = sd_bus_send(a, m, NULL);
1671 /* The name database changed since the policy check, hence let's check again */
1673 else if (k == -ECONNRESET)
1677 log_error_errno(r, "Failed to send message to bus: %m");
1693 fd = sd_bus_get_fd(a);
1695 log_error_errno(r, "Failed to get fd: %m");
1699 events_a = sd_bus_get_events(a);
1701 log_error_errno(r, "Failed to get events mask: %m");
1705 r = sd_bus_get_timeout(a, &timeout_a);
1707 log_error_errno(r, "Failed to get timeout: %m");
1711 events_b = sd_bus_get_events(b);
1713 log_error_errno(r, "Failed to get events mask: %m");
1717 r = sd_bus_get_timeout(b, &timeout_b);
1719 log_error_errno(r, "Failed to get timeout: %m");
1724 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1727 if (t == (uint64_t) -1)
1732 nw = now(CLOCK_MONOTONIC);
1738 ts = timespec_store(&_ts, t);
1741 pollfd = (struct pollfd[3]) {
1742 {.fd = fd, .events = events_a, },
1743 {.fd = in_fd, .events = events_b & POLLIN, },
1744 {.fd = out_fd, .events = events_b & POLLOUT, }
1747 r = ppoll(pollfd, 3, ts, NULL);
1749 log_error_errno(errno, "ppoll() failed: %m");
1757 "STATUS=Shutting down.");
1759 policy_free(&policy_buffer);
1760 strv_free(arg_configuration);
1763 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;