shared: split out polkit stuff from bus-util.c → bus-polkit.c
authorLennart Poettering <lennart@poettering.net>
Wed, 22 Jan 2020 10:39:22 +0000 (11:39 +0100)
committerMichael Biebl <biebl@debian.org>
Thu, 18 Mar 2021 19:59:14 +0000 (19:59 +0000)
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)

Gbp-Pq: Name shared-split-out-polkit-stuff-from-bus-util.c-bus-polkit..patch

31 files changed:
src/core/dbus-unit.c
src/core/dbus.c
src/hostname/hostnamed.c
src/import/importd.c
src/locale/keymap-util.c
src/locale/localed.c
src/login/logind-dbus.c
src/login/logind-seat-dbus.c
src/login/logind-session-dbus.c
src/login/logind-user-dbus.c
src/login/logind.c
src/machine/image-dbus.c
src/machine/machine-dbus.c
src/machine/machined-dbus.c
src/machine/machined.c
src/network/networkd-link-bus.c
src/network/networkd-manager-bus.c
src/network/networkd-manager.c
src/portable/portabled-bus.c
src/portable/portabled-image-bus.c
src/portable/portabled.c
src/resolve/resolved-bus.c
src/resolve/resolved-dnssd-bus.c
src/resolve/resolved-link-bus.c
src/resolve/resolved-manager.c
src/shared/bus-polkit.c [new file with mode: 0644]
src/shared/bus-polkit.h [new file with mode: 0644]
src/shared/bus-util.c
src/shared/bus-util.h
src/shared/meson.build
src/timedate/timedated.c

index 17c2003c8fbb50c1763c2becd286916453c317f3..ce0fbdbdd0bea5b01043eb163b34effb02d10dd2 100644 (file)
@@ -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"
index 255b86e7a41930eaa098675e840a483755253c6c..91c06ce376e66f93f0d83f6686d0dff7f43a414d 100644 (file)
@@ -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"
index 7777450c35401db8aaacc2950f814ba34ac886ea..9b98f32a1df74e64cf838a4f9c71ece30f9e031c 100644 (file)
@@ -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"
index 2426933558f3737e1192e9556b4d4da75f302b36..15430d82f19c513e6a3e8cc01a44a4d3bfd99900 100644 (file)
@@ -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"
index 6b6b32a5910cdd4d504f47a36492ddf0cbcd9fc9..c203c7a955ca4fb6ad3431077c580efbb73dae05 100644 (file)
@@ -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"
index f851d35a08e412868cc447d0a7812975538bb0aa..0bc02a0b61edac2f3d0468d1f651d496e9eb040b 100644 (file)
@@ -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"
index b9ea370ec009ab9ccdf95c4440ddc2a8b9e93d9e..91350fd1b62e8a08d13813e172b3f44521c0ad36 100644 (file)
@@ -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"
index 6ee5a1c95d27ce94ee30c1a85a1ee1cd3a83af2f..28ea5b78e03835d68703511524ef679c685e4401 100644 (file)
@@ -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"
index df5bfba98213bd9f601fec8c5d60a256cc5de945..bd5c1fe8395b0e1ca870272ac154327ba6784210 100644 (file)
@@ -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"
index fcaeba13f6b2c20c5e6248415cef82e40d1ec7bd..129696e980aad75990d43ae208f1cdb37e7921ce 100644 (file)
@@ -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"
index 95ec0a57c600c10214840f68c234495c4b6b39cf..171b898a6c56055b2ff0b626c938f1d549e284f3 100644 (file)
@@ -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"
index 7e7f0d51bfb0db5ea8a2adaf82b9d626788a6442..1322f3ec8196289825e34868f73358f76b3e26f2 100644 (file)
@@ -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"
index 7a558df8983c0267f73bf6017536e86d0e38394a..39905e5c9cc5ddeea50093c84c1a31be9dca8f3a 100644 (file)
@@ -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"
index fea9cc2633d7e50f7ca37dc0e35042672f13c793..f00be230333b5cf91c5df8d980927f43c5d10298 100644 (file)
@@ -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"
index 0b92b1c6ee238bd822587aeef8ba8519cdc4c72a..e3456d8efb0b41a6cd7194d2084075f6a4d0b2a6 100644 (file)
@@ -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"
index 0dbcd86d9e963ffb99958e0e8331f0c1a73b1f2e..beee91056ffb1746b77cdafcc4eb7f03bbbeaf42 100644 (file)
@@ -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"
index 8c527837f8e6eb17e336077a0f50e2643d4091c1..76288788c5d6d2562b545d03e2b98027306c6030 100644 (file)
@@ -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"
 
index acb9a7540502fc0cff2e2f67ca4ecd49367c50b0..bd29fd03f2b1ee92a27748c6ce77606f416e9153 100644 (file)
@@ -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"
index 3cbdb0b0cc22ded9660717fa1776ba851453e51f..708ec94879f35ad5d51a24c1edc3e6627332d005 100644 (file)
@@ -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"
index 360559811fa72393215f9f70ba2255897541333c..beebcf8f7d625dd7597b05264efa52c6a15165dd 100644 (file)
@@ -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"
index 49a359fd3150c3a0f538a2d4555b597d127e7b1c..f5a34ff14cdc5efa709006bbb77327176d70624d 100644 (file)
@@ -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"
index 5b547ba7eee95ea24c275dead7d996ebb70895ad..1638d3b99ad9f7167e7e57889347f354e8b8ce72 100644 (file)
@@ -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"
index 24bb37b35e848eaaf59195267ad887046f94b508..f7dcb3bfa56f8fb4afc035e9ab165d3211129b21 100644 (file)
@@ -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"
index 96093fff53fe2bfd8290b5d04750aa854195569f..53f017c79135df7d7bc5a232b3a7638a73879a50 100644 (file)
@@ -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"
index 2017b0e45b9ec3fe43fcafe84bdd6ab4bda2912a..422ec23a0856c1890fe2f689a866261ae6253bd6 100644 (file)
@@ -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 (file)
index 0000000..da4aee5
--- /dev/null
@@ -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 (file)
index 0000000..29b3923
--- /dev/null
@@ -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);
index a406dd84236e2d115ad8b1bedb55cefe7dee6738..c9d7e7692bf4a11208dac58d5a1b1fe3a900265e 100644 (file)
@@ -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"
 #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;
index 71c248fe3c7106ded9f3fd587b80e48deedf9854..c9cbf769a67ecbee955fac36d2ee23b3c45158cb 100644 (file)
@@ -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);
 
index 99d6ba14f19c44847b9a01dbffee2c6375db8319..f6d1092bd123587632d7524c0f9168a588255184 100644 (file)
@@ -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
index 324d4a41c76634f89138b2896066ba17eecec95c..398d4f4fbfe2680998af0480b016ec34fd0fb3d8 100644 (file)
@@ -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"