diff options
author | Lennart Poettering <lennart@poettering.net> | 2020-01-22 11:39:22 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2020-01-22 12:34:10 +0100 |
commit | 269e4d2d6b75329ae39a71ebe2c14500e03cda95 (patch) | |
tree | 860e8b524831cc44c3d2e283fbaba3fa5eb4fae4 /src/shared/bus-util.c | |
parent | 1287740560164a18b0fd7f92df43640a3d2cb0d0 (diff) | |
download | systemd-269e4d2d6b75329ae39a71ebe2c14500e03cda95.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.
Diffstat (limited to 'src/shared/bus-util.c')
-rw-r--r-- | src/shared/bus-util.c | 357 |
1 files changed, 1 insertions, 356 deletions
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 10c05eba18..15bc0ed71b 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; |