diff options
author | Lennart Poettering <lennart@poettering.net> | 2020-01-22 11:39:22 +0100 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2020-02-05 16:58:24 +0100 |
commit | 0a19ff7004e4a567566a0a7be6b050cf34c0bfe5 (patch) | |
tree | c1f6fa1a8512c64b68a6738767a9c195c7820268 | |
parent | 1325dfb5778dedd3ca5274d3383e7c27121fa60a (diff) | |
download | systemd-0a19ff7004e4a567566a0a7be6b050cf34c0bfe5.tar.gz |
shared: split out polkit stuff from bus-util.c → bus-polkit.c
It's enough, complex stuff to warrant its own source file.
No other changes, just splitting out.
(cherry picked from commit 269e4d2d6b75329ae39a71ebe2c14500e03cda95)
31 files changed, 402 insertions, 377 deletions
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 1c5fd2a23b..73d5b2ee1e 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 3c40f29694..78b30c5090 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 deecd9b8db..21f6471495 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -8,7 +8,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 a75ab6bc07..93e704ed61 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 519dd0d188..30669a9359 100644 --- a/src/locale/keymap-util.c +++ b/src/locale/keymap-util.c @@ -5,7 +5,7 @@ #include <sys/types.h> #include <unistd.h> -#include "bus-util.h" +#include "bus-polkit.h" #include "env-file-label.h" #include "env-file.h" #include "env-util.h" diff --git a/src/locale/localed.c b/src/locale/localed.c index 2031cd25ce..09f16d25f4 100644 --- a/src/locale/localed.c +++ b/src/locale/localed.c @@ -15,7 +15,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 69b5994878..ff731555d7 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -12,13 +12,14 @@ #include "bootspec.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" #include "device-util.h" #include "dirent-util.h" -#include "efivars.h" #include "efi-loader.h" +#include "efivars.h" #include "env-util.h" #include "escape.h" #include "fd-util.h" diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c index 34ac0350f2..5b41e60fd6 100644 --- a/src/login/logind-seat-dbus.c +++ b/src/login/logind-seat-dbus.c @@ -5,6 +5,7 @@ #include "alloc-util.h" #include "bus-common-errors.h" #include "bus-label.h" +#include "bus-polkit.h" #include "bus-util.h" #include "logind-dbus.h" #include "logind-seat-dbus.h" diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c index 32a64fff0c..03f470cf2a 100644 --- a/src/login/logind-session-dbus.c +++ b/src/login/logind-session-dbus.c @@ -5,6 +5,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-brightness.h" diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c index 1dc222f90e..d9f1dfe4a4 100644 --- a/src/login/logind-user-dbus.c +++ b/src/login/logind-user-dbus.c @@ -3,6 +3,7 @@ #include <errno.h> #include "alloc-util.h" +#include "bus-polkit.h" #include "bus-util.h" #include "format-util.h" #include "logind-dbus.h" diff --git a/src/login/logind.c b/src/login/logind.c index d8c1bbe15b..8f3708d2a4 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -9,7 +9,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 b45355d86f..294ef34932 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 3b2ac38298..a2990452af 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -14,6 +14,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 6fc3b93057..d0cc07678f 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -8,6 +8,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 "errno-util.h" diff --git a/src/machine/machined.c b/src/machine/machined.c index a3bed035dc..ace2131c2d 100644 --- a/src/machine/machined.c +++ b/src/machine/machined.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 "dirent-util.h" #include "fd-util.h" diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c index 356ceaf063..d25ab20a0f 100644 --- a/src/network/networkd-link-bus.c +++ b/src/network/networkd-link-bus.c @@ -6,6 +6,7 @@ #include "alloc-util.h" #include "bus-common-errors.h" +#include "bus-polkit.h" #include "bus-util.h" #include "dns-domain.h" #include "networkd-link-bus.h" diff --git a/src/network/networkd-manager-bus.c b/src/network/networkd-manager-bus.c index 773dcf0b4d..d97cc0ce24 100644 --- a/src/network/networkd-manager-bus.c +++ b/src/network/networkd-manager-bus.c @@ -6,7 +6,7 @@ #include "alloc-util.h" #include "bus-common-errors.h" -#include "bus-util.h" +#include "bus-polkit.h" #include "networkd-link-bus.h" #include "networkd-link.h" #include "networkd-manager-bus.h" diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 4a7e8dac0a..cbb3fa96f9 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -11,6 +11,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 89168c3c43..0fa05434ef 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 fd2b7c9994..2bd1c495e4 100644 --- a/src/portable/portabled-image-bus.c +++ b/src/portable/portabled-image-bus.c @@ -8,6 +8,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 c74ec42962..75b76926e5 100644 --- a/src/portable/portabled.c +++ b/src/portable/portabled.c @@ -7,7 +7,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 2c1aba911a..a2712610ce 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 "memory-util.h" diff --git a/src/resolve/resolved-dnssd-bus.c b/src/resolve/resolved-dnssd-bus.c index 24bb37b35e..f7dcb3bfa5 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 8a2768b1e2..8bbfbaacb8 100644 --- a/src/resolve/resolved-link-bus.c +++ b/src/resolve/resolved-link-bus.c @@ -6,6 +6,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 95f698ab06..2d5dbcc23d 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -14,7 +14,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 0000000000..da4aee5086 --- /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 0000000000..29b3923047 --- /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 aea46d3119..7bab94580f 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -9,7 +9,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" @@ -22,15 +21,12 @@ #include "bus-util.h" #include "cap-list.h" #include "cgroup-util.h" -#include "def.h" -#include "escape.h" -#include "fd-util.h" #include "mountpoint-util.h" #include "nsflags.h" #include "parse-util.h" #include "path-util.h" -#include "proc-cmdline.h" #include "rlimit-util.h" +#include "socket-util.h" #include "stdio-util.h" #include "strv.h" #include "user-util.h" @@ -185,357 +181,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) || - 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 -} - 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 1e2f04cc5d..db245a791e 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" #include "time-util.h" @@ -52,11 +52,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 b3ae259b22..063d15775a 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -27,6 +27,8 @@ shared_sources = files(''' bus-unit-util.h bus-util.c bus-util.h + bus-polkit.c + bus-polkit.h bus-wait-for-jobs.c bus-wait-for-jobs.h bus-wait-for-units.c diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 4ec3b50359..5e2fb50d83 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -12,7 +12,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 "conf-files.h" #include "def.h" |