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 r = sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
995 (void) sd_bus_creds_get_uid(&m->creds, &sender_uid);
996 (void) sd_bus_creds_get_gid(&m->creds, &sender_gid);
998 /* First check whether the sender can send the message to our name */
999 if (set_isempty(owned_names)) {
1000 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, NULL, m->path, m->interface, m->member))
1006 SET_FOREACH(n, owned_names, i)
1007 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, n, m->path, m->interface, m->member)) {
1014 /* Then check whether us (the recipient) can recieve from the sender's name */
1015 if (strv_isempty(sender_names)) {
1016 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1021 STRV_FOREACH(n, sender_names) {
1022 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member))
1028 /* Return an error back to the caller */
1029 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1030 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
1032 /* Return 1, indicating that the message shall not be processed any further */
1036 if (to->is_kernel) {
1037 _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL;
1038 uid_t destination_uid = UID_INVALID;
1039 gid_t destination_gid = GID_INVALID;
1040 const char *destination_unique = NULL;
1041 char **destination_names = NULL;
1042 bool granted = false;
1044 /* Driver messages are always OK */
1045 if (streq_ptr(m->destination, "org.freedesktop.DBus"))
1048 /* The message came from the legacy client, and is sent to kdbus. */
1049 if (m->destination) {
1050 r = bus_get_name_creds_kdbus(to, m->destination,
1051 SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
1052 SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID,
1053 true, &destination_creds);
1055 return handle_policy_error(m, r);
1057 r = sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
1059 return handle_policy_error(m, r);
1061 r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
1063 return handle_policy_error(m, r);
1065 (void) sd_bus_creds_get_uid(destination_creds, &destination_uid);
1066 (void) sd_bus_creds_get_gid(destination_creds, &destination_gid);
1069 /* First check if we (the sender) can send to this name */
1070 if (strv_isempty(destination_names)) {
1071 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1076 STRV_FOREACH(n, destination_names) {
1077 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member)) {
1079 /* If we made a receiver decision,
1080 then remember which name's policy
1081 we used, and to which unique ID it
1082 mapped when we made the
1083 decision. Then, let's pass this to
1084 the kernel when sending the
1085 message, so that it refuses the
1086 operation should the name and
1087 unique ID not map to each other
1090 r = free_and_strdup(&m->destination_ptr, *n);
1094 r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
1104 /* Then check if the recipient can receive from our name */
1106 if (set_isempty(owned_names)) {
1107 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, NULL, m->path, m->interface, m->member))
1113 SET_FOREACH(n, owned_names, i)
1114 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, n, m->path, m->interface, m->member))
1119 /* Return an error back to the caller */
1120 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1121 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
1123 /* Return 1, indicating that the message shall not be processed any further */
1130 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
1131 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
1140 /* As reaction to hello we need to respond with two messages:
1141 * the callback reply and the NameAcquired for the unique
1142 * name, since hello is otherwise obsolete on kdbus. */
1145 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1146 streq_ptr(m->destination, "org.freedesktop.DBus");
1153 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1158 log_error("Got duplicate hello, aborting.");
1167 r = sd_bus_message_new_method_return(m, &n);
1169 return log_error_errno(r, "Failed to generate HELLO reply: %m");
1171 r = sd_bus_message_append(n, "s", a->unique_name);
1173 return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
1175 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1177 return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
1179 r = bus_seal_synthetic_message(b, n);
1181 return log_error_errno(r, "Failed to seal HELLO reply: %m");
1183 r = sd_bus_send(b, n, NULL);
1185 return log_error_errno(r, "Failed to send HELLO reply: %m");
1187 n = sd_bus_message_unref(n);
1188 r = sd_bus_message_new_signal(
1191 "/org/freedesktop/DBus",
1192 "org.freedesktop.DBus",
1195 return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
1197 r = sd_bus_message_append(n, "s", a->unique_name);
1199 return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
1201 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1203 return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
1205 r = bus_seal_synthetic_message(b, n);
1207 return log_error_errno(r, "Failed to seal NameAcquired message: %m");
1209 r = sd_bus_send(b, n, NULL);
1211 return log_error_errno(r, "Failed to send NameAcquired message: %m");
1216 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1217 char **well_known = NULL;
1227 /* We will change the sender of messages from the bus driver
1228 * so that they originate from the bus driver. This is a
1229 * speciality originating from dbus1, where the bus driver did
1230 * not have a unique id, but only the well-known name. */
1232 c = sd_bus_message_get_creds(m);
1236 r = sd_bus_creds_get_well_known_names(c, &well_known);
1240 if (strv_contains(well_known, "org.freedesktop.DBus"))
1241 m->sender = "org.freedesktop.DBus";
1246 static int mac_smack_apply_label_and_drop_cap_mac_admin(pid_t its_pid, const char *new_label) {
1250 if (!mac_smack_use())
1253 if (new_label && its_pid > 0)
1254 r = mac_smack_apply_pid(its_pid, new_label);
1256 k = drop_capability(CAP_MAC_ADMIN);
1257 return r < 0 ? r : k;
1263 int main(int argc, char *argv[]) {
1265 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1266 sd_id128_t server_id;
1267 int r, in_fd, out_fd;
1268 bool got_hello = false;
1270 struct ucred ucred = {};
1271 _cleanup_free_ char *peersec = NULL;
1272 Policy policy_buffer = {}, *policy = NULL;
1273 _cleanup_set_free_free_ Set *owned_names = NULL;
1275 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1276 log_parse_environment();
1279 r = parse_argv(argc, argv);
1283 r = sd_listen_fds(0);
1285 in_fd = STDIN_FILENO;
1286 out_fd = STDOUT_FILENO;
1287 } else if (r == 1) {
1288 in_fd = SD_LISTEN_FDS_START;
1289 out_fd = SD_LISTEN_FDS_START;
1291 log_error("Illegal number of file descriptors passed");
1296 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1297 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1300 (void) getpeercred(in_fd, &ucred);
1301 (void) getpeersec(in_fd, &peersec);
1303 r = mac_smack_apply_label_and_drop_cap_mac_admin(getpid(), peersec);
1305 log_warning_errno(r, "Failed to set SMACK label (%s) and drop CAP_MAC_ADMIN: %m", peersec);
1308 if (arg_drop_privileges) {
1309 const char *user = "systemd-bus-proxy";
1313 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1315 log_error_errno(r, "Cannot resolve user name %s: %m", user);
1319 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1324 owned_names = set_new(&string_hash_ops);
1332 log_error_errno(r, "Failed to allocate bus: %m");
1336 r = sd_bus_set_description(a, "sd-proxy");
1338 log_error_errno(r, "Failed to set bus name: %m");
1342 r = sd_bus_set_address(a, arg_address);
1344 log_error_errno(r, "Failed to set address to connect to: %m");
1348 r = sd_bus_negotiate_fds(a, is_unix);
1350 log_error_errno(r, "Failed to set FD negotiation: %m");
1354 r = sd_bus_negotiate_creds(a, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1356 log_error_errno(r, "Failed to set credential negotiation: %m");
1360 if (ucred.pid > 0) {
1361 a->fake_pids.pid = ucred.pid;
1362 a->fake_pids_valid = true;
1364 a->fake_creds.uid = ucred.uid;
1365 a->fake_creds.euid = UID_INVALID;
1366 a->fake_creds.suid = UID_INVALID;
1367 a->fake_creds.fsuid = UID_INVALID;
1368 a->fake_creds.gid = ucred.gid;
1369 a->fake_creds.egid = GID_INVALID;
1370 a->fake_creds.sgid = GID_INVALID;
1371 a->fake_creds.fsgid = GID_INVALID;
1372 a->fake_creds_valid = true;
1376 a->fake_label = peersec;
1380 a->manual_peer_interface = true;
1382 r = sd_bus_start(a);
1384 log_error_errno(r, "Failed to start bus client: %m");
1388 r = sd_bus_get_bus_id(a, &server_id);
1390 log_error_errno(r, "Failed to get server ID: %m");
1395 if (!arg_configuration) {
1398 r = sd_bus_get_scope(a, &scope);
1400 log_error_errno(r, "Couldn't determine bus scope: %m");
1404 if (streq(scope, "system"))
1405 arg_configuration = strv_new(
1406 "/etc/dbus-1/system.conf",
1407 "/etc/dbus-1/system.d/",
1408 "/etc/dbus-1/system-local.conf",
1410 else if (streq(scope, "user"))
1411 arg_configuration = strv_new(
1412 "/etc/dbus-1/session.conf",
1413 "/etc/dbus-1/session.d/",
1414 "/etc/dbus-1/session-local.conf",
1417 log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope);
1421 if (!arg_configuration) {
1427 r = policy_load(&policy_buffer, arg_configuration);
1429 log_error_errno(r, "Failed to load policy: %m");
1433 policy = &policy_buffer;
1434 /* policy_dump(policy); */
1436 if (!policy_check_hello(policy, ucred.uid, ucred.gid)) {
1437 r = log_error_errno(EPERM, "Policy denied connection.");
1444 log_error_errno(r, "Failed to allocate bus: %m");
1448 r = sd_bus_set_fd(b, in_fd, out_fd);
1450 log_error_errno(r, "Failed to set fds: %m");
1454 r = sd_bus_set_server(b, 1, server_id);
1456 log_error_errno(r, "Failed to set server mode: %m");
1460 r = sd_bus_negotiate_fds(b, is_unix);
1462 log_error_errno(r, "Failed to set FD negotiation: %m");
1466 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1468 log_error_errno(r, "Failed to set credential negotiation: %m");
1472 r = sd_bus_set_anonymous(b, true);
1474 log_error_errno(r, "Failed to set anonymous authentication: %m");
1478 b->manual_peer_interface = true;
1480 r = sd_bus_start(b);
1482 log_error_errno(r, "Failed to start bus client: %m");
1486 r = rename_service(a, b);
1488 log_debug_errno(r, "Failed to rename process: %m");
1491 _cleanup_free_ char *match = NULL;
1494 r = sd_bus_get_unique_name(a, &unique);
1496 log_error_errno(r, "Failed to get unique name: %m");
1500 match = strjoin("type='signal',"
1501 "sender='org.freedesktop.DBus',"
1502 "path='/org/freedesktop/DBus',"
1503 "interface='org.freedesktop.DBus',"
1504 "member='NameOwnerChanged',"
1514 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1516 log_error_errno(r, "Failed to add match for NameLost: %m");
1521 match = strjoin("type='signal',"
1522 "sender='org.freedesktop.DBus',"
1523 "path='/org/freedesktop/DBus',"
1524 "interface='org.freedesktop.DBus',"
1525 "member='NameOwnerChanged',"
1535 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1537 log_error_errno(r, "Failed to add match for NameAcquired: %m");
1543 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1544 int events_a, events_b, fd;
1545 uint64_t timeout_a, timeout_b, t;
1546 struct timespec _ts, *ts;
1547 struct pollfd *pollfd;
1551 /* Read messages from bus, to pass them on to our client */
1553 r = sd_bus_process(a, &m);
1555 /* treat 'connection reset by peer' as clean exit condition */
1556 if (r == -ECONNRESET)
1559 log_error_errno(r, "Failed to process bus a: %m");
1565 bool processed = false;
1567 /* We officially got EOF, let's quit */
1568 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1573 k = synthesize_name_acquired(a, b, m);
1576 log_error_errno(r, "Failed to synthesize message: %m");
1583 k = process_policy(a, b, m, policy, &ucred, owned_names);
1586 log_error_errno(r, "Failed to process policy: %m");
1595 k = sd_bus_send(b, m, NULL);
1597 if (k == -ECONNRESET)
1601 log_error_errno(r, "Failed to send message to client: %m");
1614 /* Read messages from our client, to pass them on to the bus */
1615 r = sd_bus_process(b, &m);
1617 /* treat 'connection reset by peer' as clean exit condition */
1618 if (r == -ECONNRESET)
1621 log_error_errno(r, "Failed to process bus b: %m");
1627 bool processed = false;
1629 /* We officially got EOF, let's quit */
1630 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1635 k = process_hello(a, b, m, &got_hello);
1638 log_error_errno(r, "Failed to process HELLO: %m");
1646 k = process_driver(a, b, m, policy, &ucred, owned_names);
1649 log_error_errno(r, "Failed to process driver calls: %m");
1660 k = process_policy(b, a, m, policy, &ucred, owned_names);
1663 log_error_errno(r, "Failed to process policy: %m");
1672 k = sd_bus_send(a, m, NULL);
1675 /* The name database changed since the policy check, hence let's check again */
1677 else if (k == -ECONNRESET)
1681 log_error_errno(r, "Failed to send message to bus: %m");
1697 fd = sd_bus_get_fd(a);
1699 log_error_errno(r, "Failed to get fd: %m");
1703 events_a = sd_bus_get_events(a);
1705 log_error_errno(r, "Failed to get events mask: %m");
1709 r = sd_bus_get_timeout(a, &timeout_a);
1711 log_error_errno(r, "Failed to get timeout: %m");
1715 events_b = sd_bus_get_events(b);
1717 log_error_errno(r, "Failed to get events mask: %m");
1721 r = sd_bus_get_timeout(b, &timeout_b);
1723 log_error_errno(r, "Failed to get timeout: %m");
1728 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1731 if (t == (uint64_t) -1)
1736 nw = now(CLOCK_MONOTONIC);
1742 ts = timespec_store(&_ts, t);
1745 pollfd = (struct pollfd[3]) {
1746 {.fd = fd, .events = events_a, },
1747 {.fd = in_fd, .events = events_b & POLLIN, },
1748 {.fd = out_fd, .events = events_b & POLLOUT, }
1751 r = ppoll(pollfd, 3, ts, NULL);
1753 log_error_errno(errno, "ppoll() failed: %m");
1761 "STATUS=Shutting down.");
1763 policy_free(&policy_buffer);
1764 strv_free(arg_configuration);
1767 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;