From f957b9fe091aeaf4febf7dee4dda17f31566fe6e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Jan 2020 11:39:22 +0100 Subject: [PATCH] =?utf8?q?shared:=20split=20out=20polkit=20stuff=20from=20?= =?utf8?q?bus-util.c=20=E2=86=92=20bus-polkit.c?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 --- 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 17c2003c..ce0fbdbd 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 255b86e7..91c06ce3 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 7777450c..9b98f32a 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 24269335..15430d82 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 6b6b32a5..c203c7a9 100644 --- a/src/locale/keymap-util.c +++ b/src/locale/keymap-util.c @@ -6,7 +6,9 @@ #include #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 f851d35a..0bc02a0b 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 b9ea370e..91350fd1 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 6ee5a1c9..28ea5b78 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 df5bfba9..bd5c1fe8 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 fcaeba13..129696e9 100644 --- a/src/login/logind-user-dbus.c +++ b/src/login/logind-user-dbus.c @@ -4,6 +4,7 @@ #include #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 95ec0a57..171b898a 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 7e7f0d51..1322f3ec 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 7a558df8..39905e5c 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 fea9cc26..f00be230 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 0b92b1c6..e3456d8e 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 0dbcd86d..beee9105 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 8c527837..76288788 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 acb9a754..bd29fd03 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 3cbdb0b0..708ec948 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 36055981..beebcf8f 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 49a359fd..f5a34ff1 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 5b547ba7..1638d3b9 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 24bb37b3..f7dcb3bf 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 96093fff..53f017c7 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 2017b0e4..422ec23a 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 00000000..da4aee50 --- /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 00000000..29b39230 --- /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 a406dd84..c9d7e769 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -11,7 +11,6 @@ #include #include -#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 71c248fe..c9cbf769 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 99d6ba14..f6d1092b 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 324d4a41..398d4f4f 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" -- 2.30.2