summaryrefslogtreecommitdiffstats
path: root/debian/patches/shared-split-out-polkit-stuff-from-bus-util.c-bus-polkit..patch
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--debian/patches/shared-split-out-polkit-stuff-from-bus-util.c-bus-polkit..patch1190
1 files changed, 1190 insertions, 0 deletions
diff --git a/debian/patches/shared-split-out-polkit-stuff-from-bus-util.c-bus-polkit..patch b/debian/patches/shared-split-out-polkit-stuff-from-bus-util.c-bus-polkit..patch
new file mode 100644
index 0000000..3a14551
--- /dev/null
+++ b/debian/patches/shared-split-out-polkit-stuff-from-bus-util.c-bus-polkit..patch
@@ -0,0 +1,1190 @@
+From: Lennart Poettering <lennart@poettering.net>
+Date: Wed, 22 Jan 2020 11:39:22 +0100
+Subject: =?utf-8?q?shared=3A_split_out_polkit_stuff_from_bus-util=2Ec_?=
+ =?utf-8?q?=E2=86=92_bus-polkit=2Ec?=
+
+It's enough, complex stuff to warrant its own source file.
+
+No other changes, just splitting out.
+
+(cherry picked from commit 269e4d2d6b75329ae39a71ebe2c14500e03cda95)
+(cherry picked from commit 0a19ff7004e4a567566a0a7be6b050cf34c0bfe5)
+(cherry picked from commit 31a1d569db43af04669ec487f3e741ddc6d12969)
+(cherry picked from commit a4722a8df23f6612c47f1bb848a6a7c81dcbdccb)
+---
+ src/core/dbus-unit.c | 1 +
+ src/core/dbus.c | 2 +-
+ src/hostname/hostnamed.c | 2 +-
+ src/import/importd.c | 2 +-
+ src/locale/keymap-util.c | 2 +
+ src/locale/localed.c | 2 +-
+ src/login/logind-dbus.c | 1 +
+ src/login/logind-seat-dbus.c | 1 +
+ src/login/logind-session-dbus.c | 1 +
+ src/login/logind-user-dbus.c | 1 +
+ src/login/logind.c | 2 +-
+ src/machine/image-dbus.c | 1 +
+ src/machine/machine-dbus.c | 1 +
+ src/machine/machined-dbus.c | 1 +
+ src/machine/machined.c | 2 +-
+ src/network/networkd-link-bus.c | 2 +
+ src/network/networkd-manager-bus.c | 3 +
+ src/network/networkd-manager.c | 1 +
+ src/portable/portabled-bus.c | 2 +-
+ src/portable/portabled-image-bus.c | 1 +
+ src/portable/portabled.c | 2 +-
+ src/resolve/resolved-bus.c | 1 +
+ src/resolve/resolved-dnssd-bus.c | 5 +-
+ src/resolve/resolved-link-bus.c | 1 +
+ src/resolve/resolved-manager.c | 2 +-
+ src/shared/bus-polkit.c | 358 +++++++++++++++++++++++++++++++++++++
+ src/shared/bus-polkit.h | 11 ++
+ src/shared/bus-util.c | 357 +-----------------------------------
+ src/shared/bus-util.h | 7 +-
+ src/shared/meson.build | 2 +
+ src/timedate/timedated.c | 2 +-
+ 31 files changed, 406 insertions(+), 373 deletions(-)
+ create mode 100644 src/shared/bus-polkit.c
+ create mode 100644 src/shared/bus-polkit.h
+
+diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
+index 17c2003..ce0fbdb 100644
+--- a/src/core/dbus-unit.c
++++ b/src/core/dbus-unit.c
+@@ -5,6 +5,7 @@
+ #include "alloc-util.h"
+ #include "bpf-firewall.h"
+ #include "bus-common-errors.h"
++#include "bus-polkit.h"
+ #include "cgroup-util.h"
+ #include "condition.h"
+ #include "dbus-job.h"
+diff --git a/src/core/dbus.c b/src/core/dbus.c
+index 255b86e..91c06ce 100644
+--- a/src/core/dbus.c
++++ b/src/core/dbus.c
+@@ -10,7 +10,7 @@
+ #include "bus-common-errors.h"
+ #include "bus-error.h"
+ #include "bus-internal.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "dbus-automount.h"
+ #include "dbus-cgroup.h"
+ #include "dbus-device.h"
+diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
+index 7777450..9b98f32 100644
+--- a/src/hostname/hostnamed.c
++++ b/src/hostname/hostnamed.c
+@@ -7,7 +7,7 @@
+
+ #include "alloc-util.h"
+ #include "bus-common-errors.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "def.h"
+ #include "env-file-label.h"
+ #include "env-file.h"
+diff --git a/src/import/importd.c b/src/import/importd.c
+index 2426933..15430d8 100644
+--- a/src/import/importd.c
++++ b/src/import/importd.c
+@@ -7,7 +7,7 @@
+
+ #include "alloc-util.h"
+ #include "bus-common-errors.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "def.h"
+ #include "fd-util.h"
+ #include "float.h"
+diff --git a/src/locale/keymap-util.c b/src/locale/keymap-util.c
+index 6b6b32a..c203c7a 100644
+--- a/src/locale/keymap-util.c
++++ b/src/locale/keymap-util.c
+@@ -6,7 +6,9 @@
+ #include <unistd.h>
+
+ #include "bus-util.h"
++#include "bus-polkit.h"
+ #include "def.h"
++#include "env-file-label.h"
+ #include "env-file.h"
+ #include "env-file-label.h"
+ #include "env-util.h"
+diff --git a/src/locale/localed.c b/src/locale/localed.c
+index f851d35..0bc02a0 100644
+--- a/src/locale/localed.c
++++ b/src/locale/localed.c
+@@ -14,7 +14,7 @@
+ #include "alloc-util.h"
+ #include "bus-error.h"
+ #include "bus-message.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "def.h"
+ #include "keymap-util.h"
+ #include "locale-util.h"
+diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
+index b9ea370..91350fd 100644
+--- a/src/login/logind-dbus.c
++++ b/src/login/logind-dbus.c
+@@ -12,6 +12,7 @@
+ #include "audit-util.h"
+ #include "bus-common-errors.h"
+ #include "bus-error.h"
++#include "bus-polkit.h"
+ #include "bus-unit-util.h"
+ #include "bus-util.h"
+ #include "cgroup-util.h"
+diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c
+index 6ee5a1c..28ea5b7 100644
+--- a/src/login/logind-seat-dbus.c
++++ b/src/login/logind-seat-dbus.c
+@@ -6,6 +6,7 @@
+ #include "alloc-util.h"
+ #include "bus-common-errors.h"
+ #include "bus-label.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "logind-seat.h"
+ #include "logind.h"
+diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
+index df5bfba..bd5c1fe 100644
+--- a/src/login/logind-session-dbus.c
++++ b/src/login/logind-session-dbus.c
+@@ -6,6 +6,7 @@
+ #include "alloc-util.h"
+ #include "bus-common-errors.h"
+ #include "bus-label.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "fd-util.h"
+ #include "logind-session-device.h"
+diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c
+index fcaeba1..129696e 100644
+--- a/src/login/logind-user-dbus.c
++++ b/src/login/logind-user-dbus.c
+@@ -4,6 +4,7 @@
+ #include <string.h>
+
+ #include "alloc-util.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "format-util.h"
+ #include "logind-user.h"
+diff --git a/src/login/logind.c b/src/login/logind.c
+index 95ec0a5..171b898 100644
+--- a/src/login/logind.c
++++ b/src/login/logind.c
+@@ -10,7 +10,7 @@
+
+ #include "alloc-util.h"
+ #include "bus-error.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "cgroup-util.h"
+ #include "def.h"
+ #include "device-util.h"
+diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c
+index 7e7f0d5..1322f3e 100644
+--- a/src/machine/image-dbus.c
++++ b/src/machine/image-dbus.c
+@@ -5,6 +5,7 @@
+
+ #include "alloc-util.h"
+ #include "bus-label.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "copy.h"
+ #include "dissect-image.h"
+diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
+index 7a558df..39905e5 100644
+--- a/src/machine/machine-dbus.c
++++ b/src/machine/machine-dbus.c
+@@ -15,6 +15,7 @@
+ #include "bus-common-errors.h"
+ #include "bus-internal.h"
+ #include "bus-label.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "copy.h"
+ #include "env-file.h"
+diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c
+index fea9cc2..f00be23 100644
+--- a/src/machine/machined-dbus.c
++++ b/src/machine/machined-dbus.c
+@@ -9,6 +9,7 @@
+ #include "alloc-util.h"
+ #include "btrfs-util.h"
+ #include "bus-common-errors.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "cgroup-util.h"
+ #include "fd-util.h"
+diff --git a/src/machine/machined.c b/src/machine/machined.c
+index 0b92b1c..e3456d8 100644
+--- a/src/machine/machined.c
++++ b/src/machine/machined.c
+@@ -8,7 +8,7 @@
+
+ #include "alloc-util.h"
+ #include "bus-error.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "cgroup-util.h"
+ #include "dirent-util.h"
+ #include "fd-util.h"
+diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c
+index 0dbcd86..beee910 100644
+--- a/src/network/networkd-link-bus.c
++++ b/src/network/networkd-link-bus.c
+@@ -1,6 +1,8 @@
+ /* SPDX-License-Identifier: LGPL-2.1+ */
+
+ #include "alloc-util.h"
++#include "bus-common-errors.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "networkd-link.h"
+ #include "networkd-manager.h"
+diff --git a/src/network/networkd-manager-bus.c b/src/network/networkd-manager-bus.c
+index 8c52783..7628878 100644
+--- a/src/network/networkd-manager-bus.c
++++ b/src/network/networkd-manager-bus.c
+@@ -1,7 +1,10 @@
+ /* SPDX-License-Identifier: LGPL-2.1+ */
+
+ #include "alloc-util.h"
++#include "bus-common-errors.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
++#include "networkd-link.h"
+ #include "networkd-manager.h"
+ #include "strv.h"
+
+diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
+index acb9a75..bd29fd0 100644
+--- a/src/network/networkd-manager.c
++++ b/src/network/networkd-manager.c
+@@ -9,6 +9,7 @@
+ #include "sd-netlink.h"
+
+ #include "alloc-util.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "conf-parser.h"
+ #include "def.h"
+diff --git a/src/portable/portabled-bus.c b/src/portable/portabled-bus.c
+index 3cbdb0b..708ec94 100644
+--- a/src/portable/portabled-bus.c
++++ b/src/portable/portabled-bus.c
+@@ -3,7 +3,7 @@
+ #include "alloc-util.h"
+ #include "btrfs-util.h"
+ #include "bus-common-errors.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "fd-util.h"
+ #include "io-util.h"
+ #include "machine-image.h"
+diff --git a/src/portable/portabled-image-bus.c b/src/portable/portabled-image-bus.c
+index 3605598..beebcf8 100644
+--- a/src/portable/portabled-image-bus.c
++++ b/src/portable/portabled-image-bus.c
+@@ -3,6 +3,7 @@
+ #include "alloc-util.h"
+ #include "bus-common-errors.h"
+ #include "bus-label.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "fd-util.h"
+ #include "fileio.h"
+diff --git a/src/portable/portabled.c b/src/portable/portabled.c
+index 49a359f..f5a34ff 100644
+--- a/src/portable/portabled.c
++++ b/src/portable/portabled.c
+@@ -4,7 +4,7 @@
+ #include "sd-daemon.h"
+
+ #include "alloc-util.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "def.h"
+ #include "main-func.h"
+ #include "portabled-bus.h"
+diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c
+index 5b547ba..1638d3b 100644
+--- a/src/resolve/resolved-bus.c
++++ b/src/resolve/resolved-bus.c
+@@ -2,6 +2,7 @@
+
+ #include "alloc-util.h"
+ #include "bus-common-errors.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "dns-domain.h"
+ #include "missing_capability.h"
+diff --git a/src/resolve/resolved-dnssd-bus.c b/src/resolve/resolved-dnssd-bus.c
+index 24bb37b..f7dcb3b 100644
+--- a/src/resolve/resolved-dnssd-bus.c
++++ b/src/resolve/resolved-dnssd-bus.c
+@@ -1,9 +1,10 @@
++/* SPDX-License-Identifier: LGPL-2.1+ */
+
+ #include "alloc-util.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "missing_capability.h"
+-#include "resolved-dnssd.h"
+ #include "resolved-dnssd-bus.h"
++#include "resolved-dnssd.h"
+ #include "resolved-link.h"
+ #include "strv.h"
+ #include "user-util.h"
+diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c
+index 96093ff..53f017c 100644
+--- a/src/resolve/resolved-link-bus.c
++++ b/src/resolve/resolved-link-bus.c
+@@ -2,6 +2,7 @@
+
+ #include "alloc-util.h"
+ #include "bus-common-errors.h"
++#include "bus-polkit.h"
+ #include "bus-util.h"
+ #include "parse-util.h"
+ #include "resolve-util.h"
+diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
+index 2017b0e..422ec23 100644
+--- a/src/resolve/resolved-manager.c
++++ b/src/resolve/resolved-manager.c
+@@ -11,7 +11,7 @@
+
+ #include "af-list.h"
+ #include "alloc-util.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "dirent-util.h"
+ #include "dns-domain.h"
+ #include "fd-util.h"
+diff --git a/src/shared/bus-polkit.c b/src/shared/bus-polkit.c
+new file mode 100644
+index 0000000..da4aee5
+--- /dev/null
++++ b/src/shared/bus-polkit.c
+@@ -0,0 +1,358 @@
++/* SPDX-License-Identifier: LGPL-2.1+ */
++
++#include "bus-internal.h"
++#include "bus-message.h"
++#include "bus-polkit.h"
++#include "strv.h"
++#include "user-util.h"
++
++static int check_good_user(sd_bus_message *m, uid_t good_user) {
++ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
++ uid_t sender_uid;
++ int r;
++
++ assert(m);
++
++ if (good_user == UID_INVALID)
++ return 0;
++
++ r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
++ if (r < 0)
++ return r;
++
++ /* Don't trust augmented credentials for authorization */
++ assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM);
++
++ r = sd_bus_creds_get_euid(creds, &sender_uid);
++ if (r < 0)
++ return r;
++
++ return sender_uid == good_user;
++}
++
++int bus_test_polkit(
++ sd_bus_message *call,
++ int capability,
++ const char *action,
++ const char **details,
++ uid_t good_user,
++ bool *_challenge,
++ sd_bus_error *e) {
++
++ int r;
++
++ assert(call);
++ assert(action);
++
++ /* Tests non-interactively! */
++
++ r = check_good_user(call, good_user);
++ if (r != 0)
++ return r;
++
++ r = sd_bus_query_sender_privilege(call, capability);
++ if (r < 0)
++ return r;
++ else if (r > 0)
++ return 1;
++#if ENABLE_POLKIT
++ else {
++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL;
++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
++ int authorized = false, challenge = false;
++ const char *sender, **k, **v;
++
++ sender = sd_bus_message_get_sender(call);
++ if (!sender)
++ return -EBADMSG;
++
++ r = sd_bus_message_new_method_call(
++ call->bus,
++ &request,
++ "org.freedesktop.PolicyKit1",
++ "/org/freedesktop/PolicyKit1/Authority",
++ "org.freedesktop.PolicyKit1.Authority",
++ "CheckAuthorization");
++ if (r < 0)
++ return r;
++
++ r = sd_bus_message_append(
++ request,
++ "(sa{sv})s",
++ "system-bus-name", 1, "name", "s", sender,
++ action);
++ if (r < 0)
++ return r;
++
++ r = sd_bus_message_open_container(request, 'a', "{ss}");
++ if (r < 0)
++ return r;
++
++ STRV_FOREACH_PAIR(k, v, details) {
++ r = sd_bus_message_append(request, "{ss}", *k, *v);
++ if (r < 0)
++ return r;
++ }
++
++ r = sd_bus_message_close_container(request);
++ if (r < 0)
++ return r;
++
++ r = sd_bus_message_append(request, "us", 0, NULL);
++ if (r < 0)
++ return r;
++
++ r = sd_bus_call(call->bus, request, 0, e, &reply);
++ if (r < 0) {
++ /* Treat no PK available as access denied */
++ if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
++ sd_bus_error_free(e);
++ return -EACCES;
++ }
++
++ return r;
++ }
++
++ r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
++ if (r < 0)
++ return r;
++
++ r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
++ if (r < 0)
++ return r;
++
++ if (authorized)
++ return 1;
++
++ if (_challenge) {
++ *_challenge = challenge;
++ return 0;
++ }
++ }
++#endif
++
++ return -EACCES;
++}
++
++#if ENABLE_POLKIT
++
++typedef struct AsyncPolkitQuery {
++ sd_bus_message *request, *reply;
++ sd_bus_message_handler_t callback;
++ void *userdata;
++ sd_bus_slot *slot;
++ Hashmap *registry;
++} AsyncPolkitQuery;
++
++static void async_polkit_query_free(AsyncPolkitQuery *q) {
++
++ if (!q)
++ return;
++
++ sd_bus_slot_unref(q->slot);
++
++ if (q->registry && q->request)
++ hashmap_remove(q->registry, q->request);
++
++ sd_bus_message_unref(q->request);
++ sd_bus_message_unref(q->reply);
++
++ free(q);
++}
++
++static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
++ _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
++ AsyncPolkitQuery *q = userdata;
++ int r;
++
++ assert(reply);
++ assert(q);
++
++ q->slot = sd_bus_slot_unref(q->slot);
++ q->reply = sd_bus_message_ref(reply);
++
++ r = sd_bus_message_rewind(q->request, true);
++ if (r < 0) {
++ r = sd_bus_reply_method_errno(q->request, r, NULL);
++ goto finish;
++ }
++
++ r = q->callback(q->request, q->userdata, &error_buffer);
++ r = bus_maybe_reply_error(q->request, r, &error_buffer);
++
++finish:
++ async_polkit_query_free(q);
++
++ return r;
++}
++
++#endif
++
++int bus_verify_polkit_async(
++ sd_bus_message *call,
++ int capability,
++ const char *action,
++ const char **details,
++ bool interactive,
++ uid_t good_user,
++ Hashmap **registry,
++ sd_bus_error *error) {
++
++#if ENABLE_POLKIT
++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
++ AsyncPolkitQuery *q;
++ const char *sender, **k, **v;
++ sd_bus_message_handler_t callback;
++ void *userdata;
++ int c;
++#endif
++ int r;
++
++ assert(call);
++ assert(action);
++ assert(registry);
++
++ r = check_good_user(call, good_user);
++ if (r != 0)
++ return r;
++
++#if ENABLE_POLKIT
++ q = hashmap_get(*registry, call);
++ if (q) {
++ int authorized, challenge;
++
++ /* This is the second invocation of this function, and
++ * there's already a response from polkit, let's
++ * process it */
++ assert(q->reply);
++
++ if (sd_bus_message_is_method_error(q->reply, NULL)) {
++ const sd_bus_error *e;
++
++ e = sd_bus_message_get_error(q->reply);
++
++ /* Treat no PK available as access denied */
++ if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN) ||
++ sd_bus_error_has_name(e, SD_BUS_ERROR_NAME_HAS_NO_OWNER))
++ return -EACCES;
++
++ /* Copy error from polkit reply */
++ sd_bus_error_copy(error, e);
++ return -sd_bus_error_get_errno(e);
++ }
++
++ r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
++ if (r >= 0)
++ r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
++ if (r < 0)
++ return r;
++
++ if (authorized)
++ return 1;
++
++ if (challenge)
++ return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
++
++ return -EACCES;
++ }
++#endif
++
++ r = sd_bus_query_sender_privilege(call, capability);
++ if (r < 0)
++ return r;
++ else if (r > 0)
++ return 1;
++
++#if ENABLE_POLKIT
++ if (sd_bus_get_current_message(call->bus) != call)
++ return -EINVAL;
++
++ callback = sd_bus_get_current_handler(call->bus);
++ if (!callback)
++ return -EINVAL;
++
++ userdata = sd_bus_get_current_userdata(call->bus);
++
++ sender = sd_bus_message_get_sender(call);
++ if (!sender)
++ return -EBADMSG;
++
++ c = sd_bus_message_get_allow_interactive_authorization(call);
++ if (c < 0)
++ return c;
++ if (c > 0)
++ interactive = true;
++
++ r = hashmap_ensure_allocated(registry, NULL);
++ if (r < 0)
++ return r;
++
++ r = sd_bus_message_new_method_call(
++ call->bus,
++ &pk,
++ "org.freedesktop.PolicyKit1",
++ "/org/freedesktop/PolicyKit1/Authority",
++ "org.freedesktop.PolicyKit1.Authority",
++ "CheckAuthorization");
++ if (r < 0)
++ return r;
++
++ r = sd_bus_message_append(
++ pk,
++ "(sa{sv})s",
++ "system-bus-name", 1, "name", "s", sender,
++ action);
++ if (r < 0)
++ return r;
++
++ r = sd_bus_message_open_container(pk, 'a', "{ss}");
++ if (r < 0)
++ return r;
++
++ STRV_FOREACH_PAIR(k, v, details) {
++ r = sd_bus_message_append(pk, "{ss}", *k, *v);
++ if (r < 0)
++ return r;
++ }
++
++ r = sd_bus_message_close_container(pk);
++ if (r < 0)
++ return r;
++
++ r = sd_bus_message_append(pk, "us", interactive, NULL);
++ if (r < 0)
++ return r;
++
++ q = new0(AsyncPolkitQuery, 1);
++ if (!q)
++ return -ENOMEM;
++
++ q->request = sd_bus_message_ref(call);
++ q->callback = callback;
++ q->userdata = userdata;
++
++ r = hashmap_put(*registry, call, q);
++ if (r < 0) {
++ async_polkit_query_free(q);
++ return r;
++ }
++
++ q->registry = *registry;
++
++ r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
++ if (r < 0) {
++ async_polkit_query_free(q);
++ return r;
++ }
++
++ return 0;
++#endif
++
++ return -EACCES;
++}
++
++void bus_verify_polkit_async_registry_free(Hashmap *registry) {
++#if ENABLE_POLKIT
++ hashmap_free_with_destructor(registry, async_polkit_query_free);
++#endif
++}
+diff --git a/src/shared/bus-polkit.h b/src/shared/bus-polkit.h
+new file mode 100644
+index 0000000..29b3923
+--- /dev/null
++++ b/src/shared/bus-polkit.h
+@@ -0,0 +1,11 @@
++/* SPDX-License-Identifier: LGPL-2.1+ */
++#pragma once
++
++#include "sd-bus.h"
++
++#include "hashmap.h"
++
++int bus_test_polkit(sd_bus_message *call, int capability, const char *action, const char **details, uid_t good_user, bool *_challenge, sd_bus_error *e);
++
++int bus_verify_polkit_async(sd_bus_message *call, int capability, const char *action, const char **details, bool interactive, uid_t good_user, Hashmap **registry, sd_bus_error *error);
++void bus_verify_polkit_async_registry_free(Hashmap *registry);
+diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
+index a406dd8..c9d7e76 100644
+--- a/src/shared/bus-util.c
++++ b/src/shared/bus-util.c
+@@ -11,7 +11,6 @@
+ #include <sys/socket.h>
+ #include <unistd.h>
+
+-#include "sd-bus-protocol.h"
+ #include "sd-bus.h"
+ #include "sd-daemon.h"
+ #include "sd-event.h"
+@@ -24,15 +23,14 @@
+ #include "bus-util.h"
+ #include "cap-list.h"
+ #include "cgroup-util.h"
+-#include "def.h"
+-#include "escape.h"
+-#include "fd-util.h"
+ #include "missing.h"
+ #include "mountpoint-util.h"
+ #include "nsflags.h"
+ #include "parse-util.h"
+ #include "proc-cmdline.h"
++#include "path-util.h"
+ #include "rlimit-util.h"
++#include "socket-util.h"
+ #include "stdio-util.h"
+ #include "strv.h"
+ #include "user-util.h"
+@@ -187,357 +185,6 @@ int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
+ return has_owner;
+ }
+
+-static int check_good_user(sd_bus_message *m, uid_t good_user) {
+- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+- uid_t sender_uid;
+- int r;
+-
+- assert(m);
+-
+- if (good_user == UID_INVALID)
+- return 0;
+-
+- r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
+- if (r < 0)
+- return r;
+-
+- /* Don't trust augmented credentials for authorization */
+- assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM);
+-
+- r = sd_bus_creds_get_euid(creds, &sender_uid);
+- if (r < 0)
+- return r;
+-
+- return sender_uid == good_user;
+-}
+-
+-int bus_test_polkit(
+- sd_bus_message *call,
+- int capability,
+- const char *action,
+- const char **details,
+- uid_t good_user,
+- bool *_challenge,
+- sd_bus_error *e) {
+-
+- int r;
+-
+- assert(call);
+- assert(action);
+-
+- /* Tests non-interactively! */
+-
+- r = check_good_user(call, good_user);
+- if (r != 0)
+- return r;
+-
+- r = sd_bus_query_sender_privilege(call, capability);
+- if (r < 0)
+- return r;
+- else if (r > 0)
+- return 1;
+-#if ENABLE_POLKIT
+- else {
+- _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL;
+- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+- int authorized = false, challenge = false;
+- const char *sender, **k, **v;
+-
+- sender = sd_bus_message_get_sender(call);
+- if (!sender)
+- return -EBADMSG;
+-
+- r = sd_bus_message_new_method_call(
+- call->bus,
+- &request,
+- "org.freedesktop.PolicyKit1",
+- "/org/freedesktop/PolicyKit1/Authority",
+- "org.freedesktop.PolicyKit1.Authority",
+- "CheckAuthorization");
+- if (r < 0)
+- return r;
+-
+- r = sd_bus_message_append(
+- request,
+- "(sa{sv})s",
+- "system-bus-name", 1, "name", "s", sender,
+- action);
+- if (r < 0)
+- return r;
+-
+- r = sd_bus_message_open_container(request, 'a', "{ss}");
+- if (r < 0)
+- return r;
+-
+- STRV_FOREACH_PAIR(k, v, details) {
+- r = sd_bus_message_append(request, "{ss}", *k, *v);
+- if (r < 0)
+- return r;
+- }
+-
+- r = sd_bus_message_close_container(request);
+- if (r < 0)
+- return r;
+-
+- r = sd_bus_message_append(request, "us", 0, NULL);
+- if (r < 0)
+- return r;
+-
+- r = sd_bus_call(call->bus, request, 0, e, &reply);
+- if (r < 0) {
+- /* Treat no PK available as access denied */
+- if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
+- sd_bus_error_free(e);
+- return -EACCES;
+- }
+-
+- return r;
+- }
+-
+- r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
+- if (r < 0)
+- return r;
+-
+- r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
+- if (r < 0)
+- return r;
+-
+- if (authorized)
+- return 1;
+-
+- if (_challenge) {
+- *_challenge = challenge;
+- return 0;
+- }
+- }
+-#endif
+-
+- return -EACCES;
+-}
+-
+-#if ENABLE_POLKIT
+-
+-typedef struct AsyncPolkitQuery {
+- sd_bus_message *request, *reply;
+- sd_bus_message_handler_t callback;
+- void *userdata;
+- sd_bus_slot *slot;
+- Hashmap *registry;
+-} AsyncPolkitQuery;
+-
+-static void async_polkit_query_free(AsyncPolkitQuery *q) {
+-
+- if (!q)
+- return;
+-
+- sd_bus_slot_unref(q->slot);
+-
+- if (q->registry && q->request)
+- hashmap_remove(q->registry, q->request);
+-
+- sd_bus_message_unref(q->request);
+- sd_bus_message_unref(q->reply);
+-
+- free(q);
+-}
+-
+-static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
+- _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
+- AsyncPolkitQuery *q = userdata;
+- int r;
+-
+- assert(reply);
+- assert(q);
+-
+- q->slot = sd_bus_slot_unref(q->slot);
+- q->reply = sd_bus_message_ref(reply);
+-
+- r = sd_bus_message_rewind(q->request, true);
+- if (r < 0) {
+- r = sd_bus_reply_method_errno(q->request, r, NULL);
+- goto finish;
+- }
+-
+- r = q->callback(q->request, q->userdata, &error_buffer);
+- r = bus_maybe_reply_error(q->request, r, &error_buffer);
+-
+-finish:
+- async_polkit_query_free(q);
+-
+- return r;
+-}
+-
+-#endif
+-
+-int bus_verify_polkit_async(
+- sd_bus_message *call,
+- int capability,
+- const char *action,
+- const char **details,
+- bool interactive,
+- uid_t good_user,
+- Hashmap **registry,
+- sd_bus_error *error) {
+-
+-#if ENABLE_POLKIT
+- _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
+- AsyncPolkitQuery *q;
+- const char *sender, **k, **v;
+- sd_bus_message_handler_t callback;
+- void *userdata;
+- int c;
+-#endif
+- int r;
+-
+- assert(call);
+- assert(action);
+- assert(registry);
+-
+- r = check_good_user(call, good_user);
+- if (r != 0)
+- return r;
+-
+-#if ENABLE_POLKIT
+- q = hashmap_get(*registry, call);
+- if (q) {
+- int authorized, challenge;
+-
+- /* This is the second invocation of this function, and
+- * there's already a response from polkit, let's
+- * process it */
+- assert(q->reply);
+-
+- if (sd_bus_message_is_method_error(q->reply, NULL)) {
+- const sd_bus_error *e;
+-
+- e = sd_bus_message_get_error(q->reply);
+-
+- /* Treat no PK available as access denied */
+- if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
+- return -EACCES;
+-
+- /* Copy error from polkit reply */
+- sd_bus_error_copy(error, e);
+- return -sd_bus_error_get_errno(e);
+- }
+-
+- r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
+- if (r >= 0)
+- r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
+-
+- if (r < 0)
+- return r;
+-
+- if (authorized)
+- return 1;
+-
+- if (challenge)
+- return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
+-
+- return -EACCES;
+- }
+-#endif
+-
+- r = sd_bus_query_sender_privilege(call, capability);
+- if (r < 0)
+- return r;
+- else if (r > 0)
+- return 1;
+-
+-#if ENABLE_POLKIT
+- if (sd_bus_get_current_message(call->bus) != call)
+- return -EINVAL;
+-
+- callback = sd_bus_get_current_handler(call->bus);
+- if (!callback)
+- return -EINVAL;
+-
+- userdata = sd_bus_get_current_userdata(call->bus);
+-
+- sender = sd_bus_message_get_sender(call);
+- if (!sender)
+- return -EBADMSG;
+-
+- c = sd_bus_message_get_allow_interactive_authorization(call);
+- if (c < 0)
+- return c;
+- if (c > 0)
+- interactive = true;
+-
+- r = hashmap_ensure_allocated(registry, NULL);
+- if (r < 0)
+- return r;
+-
+- r = sd_bus_message_new_method_call(
+- call->bus,
+- &pk,
+- "org.freedesktop.PolicyKit1",
+- "/org/freedesktop/PolicyKit1/Authority",
+- "org.freedesktop.PolicyKit1.Authority",
+- "CheckAuthorization");
+- if (r < 0)
+- return r;
+-
+- r = sd_bus_message_append(
+- pk,
+- "(sa{sv})s",
+- "system-bus-name", 1, "name", "s", sender,
+- action);
+- if (r < 0)
+- return r;
+-
+- r = sd_bus_message_open_container(pk, 'a', "{ss}");
+- if (r < 0)
+- return r;
+-
+- STRV_FOREACH_PAIR(k, v, details) {
+- r = sd_bus_message_append(pk, "{ss}", *k, *v);
+- if (r < 0)
+- return r;
+- }
+-
+- r = sd_bus_message_close_container(pk);
+- if (r < 0)
+- return r;
+-
+- r = sd_bus_message_append(pk, "us", interactive, NULL);
+- if (r < 0)
+- return r;
+-
+- q = new0(AsyncPolkitQuery, 1);
+- if (!q)
+- return -ENOMEM;
+-
+- q->request = sd_bus_message_ref(call);
+- q->callback = callback;
+- q->userdata = userdata;
+-
+- r = hashmap_put(*registry, call, q);
+- if (r < 0) {
+- async_polkit_query_free(q);
+- return r;
+- }
+-
+- q->registry = *registry;
+-
+- r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
+- if (r < 0) {
+- async_polkit_query_free(q);
+- return r;
+- }
+-
+- return 0;
+-#endif
+-
+- return -EACCES;
+-}
+-
+-void bus_verify_polkit_async_registry_free(Hashmap *registry) {
+-#if ENABLE_POLKIT
+- hashmap_free_with_destructor(registry, async_polkit_query_free);
+-#endif
+-}
+-
+ int bus_check_peercred(sd_bus *c) {
+ struct ucred ucred;
+ int fd, r;
+diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h
+index 71c248f..c9cbf76 100644
+--- a/src/shared/bus-util.h
++++ b/src/shared/bus-util.h
+@@ -9,8 +9,8 @@
+ #include "sd-bus.h"
+ #include "sd-event.h"
+
+-#include "hashmap.h"
+ #include "macro.h"
++#include "set.h"
+ #include "string-util.h"
+
+ typedef enum BusTransport {
+@@ -51,11 +51,6 @@ int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error);
+
+ int bus_check_peercred(sd_bus *c);
+
+-int bus_test_polkit(sd_bus_message *call, int capability, const char *action, const char **details, uid_t good_user, bool *_challenge, sd_bus_error *e);
+-
+-int bus_verify_polkit_async(sd_bus_message *call, int capability, const char *action, const char **details, bool interactive, uid_t good_user, Hashmap **registry, sd_bus_error *error);
+-void bus_verify_polkit_async_registry_free(Hashmap *registry);
+-
+ int bus_connect_system_systemd(sd_bus **_bus);
+ int bus_connect_user_systemd(sd_bus **_bus);
+
+diff --git a/src/shared/meson.build b/src/shared/meson.build
+index 99d6ba1..f6d1092 100644
+--- a/src/shared/meson.build
++++ b/src/shared/meson.build
+@@ -25,6 +25,8 @@ shared_sources = files('''
+ bus-unit-util.h
+ bus-util.c
+ bus-util.h
++ bus-polkit.c
++ bus-polkit.h
+ calendarspec.c
+ calendarspec.h
+ cgroup-show.c
+diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
+index 324d4a4..398d4f4 100644
+--- a/src/timedate/timedated.c
++++ b/src/timedate/timedated.c
+@@ -11,7 +11,7 @@
+ #include "alloc-util.h"
+ #include "bus-common-errors.h"
+ #include "bus-error.h"
+-#include "bus-util.h"
++#include "bus-polkit.h"
+ #include "clock-util.h"
+ #include "def.h"
+ #include "fileio-label.h"