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-control.h"
48 #include "smack-util.h"
50 #include "bus-xml-policy.h"
52 static char *arg_address = NULL;
53 static char *arg_command_line_buffer = NULL;
54 static bool arg_drop_privileges = false;
55 static char **arg_configuration = NULL;
57 static int help(void) {
59 printf("%s [OPTIONS...]\n\n"
60 "Connect STDIO or a socket to a given bus address.\n\n"
61 " -h --help Show this help\n"
62 " --version Show package version\n"
63 " --drop-privileges Drop privileges\n"
64 " --configuration=PATH Configuration file or directory\n"
65 " --machine=MACHINE Connect to specified machine\n"
66 " --address=ADDRESS Connect to the bus specified by ADDRESS\n"
67 " (default: " DEFAULT_SYSTEM_BUS_ADDRESS ")\n",
68 program_invocation_short_name);
73 static int parse_argv(int argc, char *argv[]) {
83 static const struct option options[] = {
84 { "help", no_argument, NULL, 'h' },
85 { "version", no_argument, NULL, ARG_VERSION },
86 { "address", required_argument, NULL, ARG_ADDRESS },
87 { "drop-privileges", no_argument, NULL, ARG_DROP_PRIVILEGES },
88 { "configuration", required_argument, NULL, ARG_CONFIGURATION },
89 { "machine", required_argument, NULL, ARG_MACHINE },
98 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
107 puts(PACKAGE_STRING);
108 puts(SYSTEMD_FEATURES);
123 case ARG_DROP_PRIVILEGES:
124 arg_drop_privileges = true;
127 case ARG_CONFIGURATION:
128 r = strv_extend(&arg_configuration, optarg);
134 _cleanup_free_ char *e = NULL;
137 e = bus_address_escape(optarg);
142 a = strjoin("x-container-kernel:machine=", e, ";x-container-unix:machine=", e, NULL);
144 a = strjoin("x-container-unix:machine=", e, NULL);
159 assert_not_reached("Unhandled option");
162 /* If the first command line argument is only "x" characters
163 * we'll write who we are talking to into it, so that "ps" is
165 arg_command_line_buffer = argv[optind];
166 if (argc > optind + 1 || (arg_command_line_buffer && !in_charset(arg_command_line_buffer, "x"))) {
167 log_error("Too many arguments");
172 arg_address = strdup(DEFAULT_SYSTEM_BUS_ADDRESS);
180 static int rename_service(sd_bus *a, sd_bus *b) {
181 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
182 _cleanup_free_ char *p = NULL, *name = NULL;
192 r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM, &creds);
196 r = sd_bus_creds_get_uid(creds, &uid);
200 r = sd_bus_creds_get_pid(creds, &pid);
204 r = sd_bus_creds_get_cmdline(creds, &cmdline);
208 r = sd_bus_creds_get_comm(creds, &comm);
212 name = uid_to_name(uid);
216 p = strv_join(cmdline, " ");
220 /* The status string gets the full command line ... */
222 "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)",
226 /* ... and the argv line only the short comm */
227 if (arg_command_line_buffer) {
230 m = strlen(arg_command_line_buffer);
231 w = snprintf(arg_command_line_buffer, m,
232 "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]",
237 memzero(arg_command_line_buffer + w, m - w);
240 log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s",
248 static int synthesize_name_acquired(sd_bus *a, sd_bus *b, sd_bus_message *m) {
249 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
250 const char *name, *old_owner, *new_owner;
257 /* If we get NameOwnerChanged for our own name, we need to
258 * synthesize NameLost/NameAcquired, since socket clients need
259 * that, even though it is obsoleted on kdbus */
264 if (!sd_bus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged") ||
265 !streq_ptr(m->path, "/org/freedesktop/DBus") ||
266 !streq_ptr(m->sender, "org.freedesktop.DBus"))
269 r = sd_bus_message_read(m, "sss", &name, &old_owner, &new_owner);
273 r = sd_bus_message_rewind(m, true);
277 if (streq(old_owner, a->unique_name)) {
279 r = sd_bus_message_new_signal(
282 "/org/freedesktop/DBus",
283 "org.freedesktop.DBus",
286 } else if (streq(new_owner, a->unique_name)) {
288 r = sd_bus_message_new_signal(
291 "/org/freedesktop/DBus",
292 "org.freedesktop.DBus",
300 r = sd_bus_message_append(n, "s", name);
304 r = bus_message_append_sender(n, "org.freedesktop.DBus");
308 r = bus_seal_synthetic_message(b, n);
312 return sd_bus_send(b, n, NULL);
315 static int synthetic_driver_send(sd_bus *b, sd_bus_message *m) {
321 r = bus_message_append_sender(m, "org.freedesktop.DBus");
325 r = bus_seal_synthetic_message(b, m);
329 return sd_bus_send(b, m, NULL);
332 static int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) {
333 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
338 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
341 r = sd_bus_message_new_method_error(call, &m, e);
345 return synthetic_driver_send(call->bus, m);
348 static int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) {
350 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
354 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
357 if (sd_bus_error_is_set(p))
358 return synthetic_reply_method_error(call, p);
360 sd_bus_error_set_errno(&berror, error);
362 return synthetic_reply_method_error(call, &berror);
365 static int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) {
366 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
371 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
374 r = sd_bus_message_new_method_return(call, &m);
378 if (!isempty(types)) {
382 r = bus_message_append_ap(m, types, ap);
388 return synthetic_driver_send(call->bus, m);
391 static int synthetic_reply_return_strv(sd_bus_message *call, char **l) {
392 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
397 r = sd_bus_message_new_method_return(call, &m);
399 return synthetic_reply_method_errno(call, r, NULL);
401 r = sd_bus_message_append_strv(m, l);
403 return synthetic_reply_method_errno(call, r, NULL);
405 return synthetic_driver_send(call->bus, m);
408 static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
409 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
416 r = sd_bus_get_name_creds(bus, name, mask, &c);
417 if (r == -ESRCH || r == -ENXIO)
418 return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
422 if ((c->mask & mask) != mask)
431 static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
439 r = sd_bus_message_read(m, "s", &name);
443 return get_creds_by_name(bus, name, mask, _creds, error);
446 static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred, Set *owned_names) {
456 if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
459 /* The "Hello()" call is is handled in process_hello() */
461 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
463 if (!sd_bus_message_has_signature(m, ""))
464 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
466 return synthetic_reply_method_return(m, "s",
467 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
468 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
470 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
471 " <method name=\"Introspect\">\n"
472 " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
475 " <interface name=\"org.freedesktop.DBus\">\n"
476 " <method name=\"AddMatch\">\n"
477 " <arg type=\"s\" direction=\"in\"/>\n"
479 " <method name=\"RemoveMatch\">\n"
480 " <arg type=\"s\" direction=\"in\"/>\n"
482 " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
483 " <arg type=\"s\" direction=\"in\"/>\n"
484 " <arg type=\"ay\" direction=\"out\"/>\n"
486 " <method name=\"GetConnectionUnixProcessID\">\n"
487 " <arg type=\"s\" direction=\"in\"/>\n"
488 " <arg type=\"u\" direction=\"out\"/>\n"
490 " <method name=\"GetConnectionUnixUser\">\n"
491 " <arg type=\"s\" direction=\"in\"/>\n"
492 " <arg type=\"u\" direction=\"out\"/>\n"
494 " <method name=\"GetId\">\n"
495 " <arg type=\"s\" direction=\"out\"/>\n"
497 " <method name=\"GetNameOwner\">\n"
498 " <arg type=\"s\" direction=\"in\"/>\n"
499 " <arg type=\"s\" direction=\"out\"/>\n"
501 " <method name=\"Hello\">\n"
502 " <arg type=\"s\" direction=\"out\"/>\n"
504 " <method name=\"ListActivatableNames\">\n"
505 " <arg type=\"as\" direction=\"out\"/>\n"
507 " <method name=\"ListNames\">\n"
508 " <arg type=\"as\" direction=\"out\"/>\n"
510 " <method name=\"ListQueuedOwners\">\n"
511 " <arg type=\"s\" direction=\"in\"/>\n"
512 " <arg type=\"as\" direction=\"out\"/>\n"
514 " <method name=\"NameHasOwner\">\n"
515 " <arg type=\"s\" direction=\"in\"/>\n"
516 " <arg type=\"b\" direction=\"out\"/>\n"
518 " <method name=\"ReleaseName\">\n"
519 " <arg type=\"s\" direction=\"in\"/>\n"
520 " <arg type=\"u\" direction=\"out\"/>\n"
522 " <method name=\"ReloadConfig\">\n"
524 " <method name=\"RequestName\">\n"
525 " <arg type=\"s\" direction=\"in\"/>\n"
526 " <arg type=\"u\" direction=\"in\"/>\n"
527 " <arg type=\"u\" direction=\"out\"/>\n"
529 " <method name=\"StartServiceByName\">\n"
530 " <arg type=\"s\" direction=\"in\"/>\n"
531 " <arg type=\"u\" direction=\"in\"/>\n"
532 " <arg type=\"u\" direction=\"out\"/>\n"
534 " <method name=\"UpdateActivationEnvironment\">\n"
535 " <arg type=\"a{ss}\" direction=\"in\"/>\n"
537 " <signal name=\"NameAcquired\">\n"
538 " <arg type=\"s\"/>\n"
540 " <signal name=\"NameLost\">\n"
541 " <arg type=\"s\"/>\n"
543 " <signal name=\"NameOwnerChanged\">\n"
544 " <arg type=\"s\"/>\n"
545 " <arg type=\"s\"/>\n"
546 " <arg type=\"s\"/>\n"
551 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
554 if (!sd_bus_message_has_signature(m, "s"))
555 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
557 r = sd_bus_message_read(m, "s", &match);
559 return synthetic_reply_method_errno(m, r, NULL);
561 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
563 return synthetic_reply_method_errno(m, r, NULL);
565 return synthetic_reply_method_return(m, NULL);
567 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
570 if (!sd_bus_message_has_signature(m, "s"))
571 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
573 r = sd_bus_message_read(m, "s", &match);
575 return synthetic_reply_method_errno(m, r, NULL);
577 r = bus_remove_match_by_string(a, match, NULL, NULL);
579 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
581 return synthetic_reply_method_errno(m, r, NULL);
583 return synthetic_reply_method_return(m, NULL);
585 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
586 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
587 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
589 if (!sd_bus_message_has_signature(m, "s"))
590 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
592 r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
594 return synthetic_reply_method_errno(m, r, &error);
596 return synthetic_reply_method_return(m, "y", creds->label, strlen(creds->label));
598 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
599 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
600 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
602 if (!sd_bus_message_has_signature(m, "s"))
603 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
605 r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error);
607 return synthetic_reply_method_errno(m, r, &error);
609 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
611 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
612 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
613 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
615 if (!sd_bus_message_has_signature(m, "s"))
616 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
618 r = get_creds_by_message(a, m, SD_BUS_CREDS_UID, &creds, &error);
620 return synthetic_reply_method_errno(m, r, &error);
622 return synthetic_reply_method_return(m, "u", (uint32_t) creds->uid);
624 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
625 sd_id128_t server_id;
626 char buf[SD_ID128_STRING_MAX];
628 if (!sd_bus_message_has_signature(m, ""))
629 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
631 r = sd_bus_get_bus_id(a, &server_id);
633 return synthetic_reply_method_errno(m, r, NULL);
635 return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
637 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
639 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
640 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
642 if (!sd_bus_message_has_signature(m, "s"))
643 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
645 r = sd_bus_message_read(m, "s", &name);
647 return synthetic_reply_method_errno(m, r, NULL);
649 if (streq(name, "org.freedesktop.DBus"))
650 return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
652 r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
654 return synthetic_reply_method_errno(m, r, &error);
656 return synthetic_reply_method_return(m, "s", creds->unique_name);
658 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
659 _cleanup_strv_free_ char **names = NULL;
661 if (!sd_bus_message_has_signature(m, ""))
662 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
664 r = sd_bus_list_names(a, NULL, &names);
666 return synthetic_reply_method_errno(m, r, NULL);
668 /* Let's sort the names list to make it stable */
671 return synthetic_reply_return_strv(m, names);
673 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
674 _cleanup_strv_free_ char **names = NULL;
676 if (!sd_bus_message_has_signature(m, ""))
677 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
679 r = sd_bus_list_names(a, &names, NULL);
681 return synthetic_reply_method_errno(m, r, NULL);
683 r = strv_extend(&names, "org.freedesktop.DBus");
685 return synthetic_reply_method_errno(m, r, NULL);
687 /* Let's sort the names list to make it stable */
690 return synthetic_reply_return_strv(m, names);
692 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
693 struct kdbus_cmd_name_list cmd = {};
694 struct kdbus_name_list *name_list;
695 struct kdbus_name_info *name;
696 _cleanup_strv_free_ char **owners = NULL;
697 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
701 if (!sd_bus_message_has_signature(m, "s"))
702 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
704 r = sd_bus_message_read(m, "s", &arg0);
706 return synthetic_reply_method_errno(m, r, NULL);
708 r = sd_bus_get_name_creds(a, arg0, 0, NULL);
709 if (r == -ESRCH || r == -ENXIO) {
710 sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0);
711 return synthetic_reply_method_errno(m, r, &error);
714 return synthetic_reply_method_errno(m, r, NULL);
716 cmd.flags = KDBUS_NAME_LIST_QUEUED;
717 r = ioctl(a->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
719 return synthetic_reply_method_errno(m, -errno, NULL);
721 name_list = (struct kdbus_name_list *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
723 KDBUS_ITEM_FOREACH(name, name_list, names) {
724 const char *entry_name = NULL;
725 struct kdbus_item *item;
728 KDBUS_ITEM_FOREACH(item, name, items)
729 if (item->type == KDBUS_ITEM_OWNED_NAME)
730 entry_name = item->name.name;
732 if (!streq_ptr(entry_name, arg0))
735 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
740 r = strv_consume(&owners, n);
747 r = bus_kernel_cmd_free(a, cmd.offset);
749 return synthetic_reply_method_errno(m, r, NULL);
752 return synthetic_reply_method_errno(m, err, NULL);
754 return synthetic_reply_return_strv(m, owners);
756 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
759 if (!sd_bus_message_has_signature(m, "s"))
760 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
762 r = sd_bus_message_read(m, "s", &name);
764 return synthetic_reply_method_errno(m, r, NULL);
766 if (streq(name, "org.freedesktop.DBus"))
767 return synthetic_reply_method_return(m, "b", true);
769 r = sd_bus_get_name_creds(a, name, 0, NULL);
770 if (r < 0 && r != -ESRCH && r != -ENXIO)
771 return synthetic_reply_method_errno(m, r, NULL);
773 return synthetic_reply_method_return(m, "b", r >= 0);
775 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
778 if (!sd_bus_message_has_signature(m, "s"))
779 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
781 r = sd_bus_message_read(m, "s", &name);
783 return synthetic_reply_method_errno(m, r, NULL);
785 r = sd_bus_release_name(a, name);
788 return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
789 if (r == -EADDRINUSE)
790 return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
792 return synthetic_reply_method_errno(m, r, NULL);
795 set_remove(owned_names, (char*) name);
797 return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
799 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
800 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
802 if (!sd_bus_message_has_signature(m, ""))
803 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
805 r = sd_bus_error_setf(&error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
807 return synthetic_reply_method_errno(m, r, &error);
809 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
811 uint32_t flags, param;
814 if (!sd_bus_message_has_signature(m, "su"))
815 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
817 r = sd_bus_message_read(m, "su", &name, &flags);
819 return synthetic_reply_method_errno(m, r, NULL);
821 if (policy && !policy_check_own(policy, ucred->uid, ucred->gid, name))
822 return synthetic_reply_method_errno(m, -EPERM, NULL);
824 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
825 return synthetic_reply_method_errno(m, -EINVAL, NULL);
828 if (flags & BUS_NAME_ALLOW_REPLACEMENT)
829 param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
830 if (flags & BUS_NAME_REPLACE_EXISTING)
831 param |= SD_BUS_NAME_REPLACE_EXISTING;
832 if (!(flags & BUS_NAME_DO_NOT_QUEUE))
833 param |= SD_BUS_NAME_QUEUE;
835 r = set_put_strdup(owned_names, name);
837 return synthetic_reply_method_errno(m, r, NULL);
839 r = sd_bus_request_name(a, name, param);
842 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
844 set_remove(owned_names, (char*) name);
847 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
848 return synthetic_reply_method_errno(m, r, NULL);
854 return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
856 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
858 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
859 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
863 if (!sd_bus_message_has_signature(m, "su"))
864 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
866 r = sd_bus_message_read(m, "su", &name, &flags);
868 return synthetic_reply_method_errno(m, r, NULL);
871 return synthetic_reply_method_errno(m, -EINVAL, NULL);
873 r = sd_bus_get_name_creds(a, name, 0, NULL);
874 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
875 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
877 return synthetic_reply_method_errno(m, r, NULL);
879 r = sd_bus_message_new_method_call(
884 "org.freedesktop.DBus.Peer",
887 return synthetic_reply_method_errno(m, r, NULL);
889 r = sd_bus_send(a, msg, NULL);
891 return synthetic_reply_method_errno(m, r, NULL);
893 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
895 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
896 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
897 _cleanup_strv_free_ char **args = NULL;
899 if (!sd_bus_message_has_signature(m, "a{ss}"))
900 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
902 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
904 return synthetic_reply_method_errno(m, r, NULL);
906 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
907 _cleanup_free_ char *s = NULL;
911 r = sd_bus_message_read(m, "ss", &key, &value);
913 return synthetic_reply_method_errno(m, r, NULL);
915 s = strjoin(key, "=", value, NULL);
917 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
919 r = strv_extend(&args, s);
921 return synthetic_reply_method_errno(m, r, NULL);
923 r = sd_bus_message_exit_container(m);
925 return synthetic_reply_method_errno(m, r, NULL);
928 r = sd_bus_message_exit_container(m);
930 return synthetic_reply_method_errno(m, r, NULL);
933 return synthetic_reply_method_errno(m, -EINVAL, NULL);
935 r = sd_bus_message_new_method_call(
938 "org.freedesktop.systemd1",
939 "/org/freedesktop/systemd1",
940 "org.freedesktop.systemd1.Manager",
943 return synthetic_reply_method_errno(m, r, NULL);
945 r = sd_bus_message_append_strv(msg, args);
947 return synthetic_reply_method_errno(m, r, NULL);
949 r = sd_bus_call(a, msg, 0, NULL, NULL);
951 return synthetic_reply_method_errno(m, r, NULL);
953 return synthetic_reply_method_return(m, NULL);
956 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
958 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
960 return synthetic_reply_method_errno(m, r, &error);
964 static int handle_policy_error(sd_bus_message *m, int r) {
965 if (r == -ESRCH || r == -ENXIO)
966 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination);
971 static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
981 if (from->is_kernel) {
982 uid_t sender_uid = UID_INVALID;
983 gid_t sender_gid = GID_INVALID;
984 char **sender_names = NULL;
985 bool granted = false;
987 /* Driver messages are always OK */
988 if (streq_ptr(m->sender, "org.freedesktop.DBus"))
991 /* The message came from the kernel, and is sent to our legacy client. */
992 sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
994 (void) sd_bus_creds_get_uid(&m->creds, &sender_uid);
995 (void) sd_bus_creds_get_gid(&m->creds, &sender_gid);
997 /* First check whether the sender can send the message to our name */
998 if (set_isempty(owned_names)) {
999 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, NULL, m->path, m->interface, m->member))
1005 SET_FOREACH(n, owned_names, i)
1006 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, n, m->path, m->interface, m->member)) {
1013 /* Then check whether us (the recipient) can recieve from the sender's name */
1014 if (strv_isempty(sender_names)) {
1015 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1020 STRV_FOREACH(n, sender_names) {
1021 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member))
1027 /* Return an error back to the caller */
1028 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1029 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
1031 /* Return 1, indicating that the message shall not be processed any further */
1035 if (to->is_kernel) {
1036 _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL;
1037 uid_t destination_uid = UID_INVALID;
1038 gid_t destination_gid = GID_INVALID;
1039 const char *destination_unique = NULL;
1040 char **destination_names = NULL;
1041 bool granted = false;
1043 /* Driver messages are always OK */
1044 if (streq_ptr(m->destination, "org.freedesktop.DBus"))
1047 /* The message came from the legacy client, and is sent to kdbus. */
1048 if (m->destination) {
1049 r = bus_get_name_creds_kdbus(to, m->destination,
1050 SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
1051 SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID,
1052 true, &destination_creds);
1054 return handle_policy_error(m, r);
1056 r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
1058 return handle_policy_error(m, r);
1060 sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
1062 (void) sd_bus_creds_get_uid(destination_creds, &destination_uid);
1063 (void) sd_bus_creds_get_gid(destination_creds, &destination_gid);
1066 /* First check if we (the sender) can send to this name */
1067 if (strv_isempty(destination_names)) {
1068 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1073 STRV_FOREACH(n, destination_names) {
1074 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member)) {
1076 /* If we made a receiver decision,
1077 then remember which name's policy
1078 we used, and to which unique ID it
1079 mapped when we made the
1080 decision. Then, let's pass this to
1081 the kernel when sending the
1082 message, so that it refuses the
1083 operation should the name and
1084 unique ID not map to each other
1087 r = free_and_strdup(&m->destination_ptr, *n);
1091 r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
1101 /* Then check if the recipient can receive from our name */
1103 if (set_isempty(owned_names)) {
1104 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, NULL, m->path, m->interface, m->member))
1110 SET_FOREACH(n, owned_names, i)
1111 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, n, m->path, m->interface, m->member))
1116 /* Return an error back to the caller */
1117 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1118 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
1120 /* Return 1, indicating that the message shall not be processed any further */
1127 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
1128 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
1137 /* As reaction to hello we need to respond with two messages:
1138 * the callback reply and the NameAcquired for the unique
1139 * name, since hello is otherwise obsolete on kdbus. */
1142 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1143 streq_ptr(m->destination, "org.freedesktop.DBus");
1150 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1155 log_error("Got duplicate hello, aborting.");
1164 r = sd_bus_message_new_method_return(m, &n);
1166 return log_error_errno(r, "Failed to generate HELLO reply: %m");
1168 r = sd_bus_message_append(n, "s", a->unique_name);
1170 return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
1172 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1174 return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
1176 r = bus_seal_synthetic_message(b, n);
1178 return log_error_errno(r, "Failed to seal HELLO reply: %m");
1180 r = sd_bus_send(b, n, NULL);
1182 return log_error_errno(r, "Failed to send HELLO reply: %m");
1184 n = sd_bus_message_unref(n);
1185 r = sd_bus_message_new_signal(
1188 "/org/freedesktop/DBus",
1189 "org.freedesktop.DBus",
1192 return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
1194 r = sd_bus_message_append(n, "s", a->unique_name);
1196 return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
1198 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1200 return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
1202 r = bus_seal_synthetic_message(b, n);
1204 return log_error_errno(r, "Failed to seal NameAcquired message: %m");
1206 r = sd_bus_send(b, n, NULL);
1208 return log_error_errno(r, "Failed to send NameAcquired message: %m");
1213 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1214 char **well_known = NULL;
1224 /* We will change the sender of messages from the bus driver
1225 * so that they originate from the bus driver. This is a
1226 * speciality originating from dbus1, where the bus driver did
1227 * not have a unique id, but only the well-known name. */
1229 c = sd_bus_message_get_creds(m);
1233 r = sd_bus_creds_get_well_known_names(c, &well_known);
1237 if (strv_contains(well_known, "org.freedesktop.DBus"))
1238 m->sender = "org.freedesktop.DBus";
1243 static int mac_smack_apply_label_and_drop_cap_mac_admin(pid_t its_pid, const char *new_label) {
1247 if (!mac_smack_use())
1250 if (new_label && its_pid > 0)
1251 r = mac_smack_apply_pid(its_pid, new_label);
1253 k = drop_capability(CAP_MAC_ADMIN);
1254 return r < 0 ? r : k;
1260 int main(int argc, char *argv[]) {
1262 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1263 sd_id128_t server_id;
1264 int r, in_fd, out_fd;
1265 bool got_hello = false;
1267 struct ucred ucred = {};
1268 _cleanup_free_ char *peersec = NULL;
1269 Policy policy_buffer = {}, *policy = NULL;
1270 _cleanup_set_free_free_ Set *owned_names = NULL;
1272 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1273 log_parse_environment();
1276 r = parse_argv(argc, argv);
1280 r = sd_listen_fds(0);
1282 in_fd = STDIN_FILENO;
1283 out_fd = STDOUT_FILENO;
1284 } else if (r == 1) {
1285 in_fd = SD_LISTEN_FDS_START;
1286 out_fd = SD_LISTEN_FDS_START;
1288 log_error("Illegal number of file descriptors passed");
1293 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1294 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1297 (void) getpeercred(in_fd, &ucred);
1298 (void) getpeersec(in_fd, &peersec);
1300 r = mac_smack_apply_label_and_drop_cap_mac_admin(getpid(), peersec);
1302 log_warning_errno(r, "Failed to set SMACK label (%s) and drop CAP_MAC_ADMIN: %m", peersec);
1305 if (arg_drop_privileges) {
1306 const char *user = "systemd-bus-proxy";
1310 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1312 log_error_errno(r, "Cannot resolve user name %s: %m", user);
1316 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1321 owned_names = set_new(&string_hash_ops);
1329 log_error_errno(r, "Failed to allocate bus: %m");
1333 r = sd_bus_set_description(a, "sd-proxy");
1335 log_error_errno(r, "Failed to set bus name: %m");
1339 r = sd_bus_set_address(a, arg_address);
1341 log_error_errno(r, "Failed to set address to connect to: %m");
1345 r = sd_bus_negotiate_fds(a, is_unix);
1347 log_error_errno(r, "Failed to set FD negotiation: %m");
1351 r = sd_bus_negotiate_creds(a, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1353 log_error_errno(r, "Failed to set credential negotiation: %m");
1357 if (ucred.pid > 0) {
1358 a->fake_pids.pid = ucred.pid;
1359 a->fake_pids_valid = true;
1361 a->fake_creds.uid = ucred.uid;
1362 a->fake_creds.euid = UID_INVALID;
1363 a->fake_creds.suid = UID_INVALID;
1364 a->fake_creds.fsuid = UID_INVALID;
1365 a->fake_creds.gid = ucred.gid;
1366 a->fake_creds.egid = GID_INVALID;
1367 a->fake_creds.sgid = GID_INVALID;
1368 a->fake_creds.fsgid = GID_INVALID;
1369 a->fake_creds_valid = true;
1373 a->fake_label = peersec;
1377 a->manual_peer_interface = true;
1379 r = sd_bus_start(a);
1381 log_error_errno(r, "Failed to start bus client: %m");
1385 r = sd_bus_get_bus_id(a, &server_id);
1387 log_error_errno(r, "Failed to get server ID: %m");
1392 if (!arg_configuration) {
1395 r = sd_bus_get_scope(a, &scope);
1397 log_error_errno(r, "Couldn't determine bus scope: %m");
1401 if (streq(scope, "system"))
1402 arg_configuration = strv_new(
1403 "/etc/dbus-1/system.conf",
1404 "/etc/dbus-1/system.d/",
1405 "/etc/dbus-1/system-local.conf",
1407 else if (streq(scope, "user"))
1408 arg_configuration = strv_new(
1409 "/etc/dbus-1/session.conf",
1410 "/etc/dbus-1/session.d/",
1411 "/etc/dbus-1/session-local.conf",
1414 log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope);
1418 if (!arg_configuration) {
1424 r = policy_load(&policy_buffer, arg_configuration);
1426 log_error_errno(r, "Failed to load policy: %m");
1430 policy = &policy_buffer;
1431 /* policy_dump(policy); */
1433 if (!policy_check_hello(policy, ucred.uid, ucred.gid)) {
1434 r = log_error_errno(EPERM, "Policy denied connection.");
1441 log_error_errno(r, "Failed to allocate bus: %m");
1445 r = sd_bus_set_fd(b, in_fd, out_fd);
1447 log_error_errno(r, "Failed to set fds: %m");
1451 r = sd_bus_set_server(b, 1, server_id);
1453 log_error_errno(r, "Failed to set server mode: %m");
1457 r = sd_bus_negotiate_fds(b, is_unix);
1459 log_error_errno(r, "Failed to set FD negotiation: %m");
1463 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1465 log_error_errno(r, "Failed to set credential negotiation: %m");
1469 r = sd_bus_set_anonymous(b, true);
1471 log_error_errno(r, "Failed to set anonymous authentication: %m");
1475 b->manual_peer_interface = true;
1477 r = sd_bus_start(b);
1479 log_error_errno(r, "Failed to start bus client: %m");
1483 r = rename_service(a, b);
1485 log_debug_errno(r, "Failed to rename process: %m");
1488 _cleanup_free_ char *match = NULL;
1491 r = sd_bus_get_unique_name(a, &unique);
1493 log_error_errno(r, "Failed to get unique name: %m");
1497 match = strjoin("type='signal',"
1498 "sender='org.freedesktop.DBus',"
1499 "path='/org/freedesktop/DBus',"
1500 "interface='org.freedesktop.DBus',"
1501 "member='NameOwnerChanged',"
1511 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1513 log_error_errno(r, "Failed to add match for NameLost: %m");
1518 match = strjoin("type='signal',"
1519 "sender='org.freedesktop.DBus',"
1520 "path='/org/freedesktop/DBus',"
1521 "interface='org.freedesktop.DBus',"
1522 "member='NameOwnerChanged',"
1532 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1534 log_error_errno(r, "Failed to add match for NameAcquired: %m");
1540 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1541 int events_a, events_b, fd;
1542 uint64_t timeout_a, timeout_b, t;
1543 struct timespec _ts, *ts;
1544 struct pollfd *pollfd;
1548 /* Read messages from bus, to pass them on to our client */
1550 r = sd_bus_process(a, &m);
1552 /* treat 'connection reset by peer' as clean exit condition */
1553 if (r == -ECONNRESET)
1556 log_error_errno(r, "Failed to process bus a: %m");
1562 bool processed = false;
1564 /* We officially got EOF, let's quit */
1565 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1570 k = synthesize_name_acquired(a, b, m);
1573 log_error_errno(r, "Failed to synthesize message: %m");
1580 k = process_policy(a, b, m, policy, &ucred, owned_names);
1583 log_error_errno(r, "Failed to process policy: %m");
1592 k = sd_bus_send(b, m, NULL);
1594 if (k == -ECONNRESET)
1598 log_error_errno(r, "Failed to send message to client: %m");
1611 /* Read messages from our client, to pass them on to the bus */
1612 r = sd_bus_process(b, &m);
1614 /* treat 'connection reset by peer' as clean exit condition */
1615 if (r == -ECONNRESET)
1618 log_error_errno(r, "Failed to process bus b: %m");
1624 bool processed = false;
1626 /* We officially got EOF, let's quit */
1627 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1632 k = process_hello(a, b, m, &got_hello);
1635 log_error_errno(r, "Failed to process HELLO: %m");
1643 k = process_driver(a, b, m, policy, &ucred, owned_names);
1646 log_error_errno(r, "Failed to process driver calls: %m");
1657 k = process_policy(b, a, m, policy, &ucred, owned_names);
1660 log_error_errno(r, "Failed to process policy: %m");
1669 k = sd_bus_send(a, m, NULL);
1672 /* The name database changed since the policy check, hence let's check again */
1674 else if (k == -ECONNRESET)
1678 log_error_errno(r, "Failed to send message to bus: %m");
1694 fd = sd_bus_get_fd(a);
1696 log_error_errno(r, "Failed to get fd: %m");
1700 events_a = sd_bus_get_events(a);
1702 log_error_errno(r, "Failed to get events mask: %m");
1706 r = sd_bus_get_timeout(a, &timeout_a);
1708 log_error_errno(r, "Failed to get timeout: %m");
1712 events_b = sd_bus_get_events(b);
1714 log_error_errno(r, "Failed to get events mask: %m");
1718 r = sd_bus_get_timeout(b, &timeout_b);
1720 log_error_errno(r, "Failed to get timeout: %m");
1725 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1728 if (t == (uint64_t) -1)
1733 nw = now(CLOCK_MONOTONIC);
1739 ts = timespec_store(&_ts, t);
1742 pollfd = (struct pollfd[3]) {
1743 {.fd = fd, .events = events_a, },
1744 {.fd = in_fd, .events = events_b & POLLIN, },
1745 {.fd = out_fd, .events = events_b & POLLOUT, }
1748 r = ppoll(pollfd, 3, ts, NULL);
1750 log_error_errno(errno, "ppoll() failed: %m");
1758 "STATUS=Shutting down.");
1760 policy_free(&policy_buffer);
1761 strv_free(arg_configuration);
1764 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;