summaryrefslogtreecommitdiffstats
path: root/src/creds/creds.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2023-11-23 22:22:27 +0100
committerLuca Boccassi <bluca@debian.org>2024-01-03 11:53:52 +0100
commitcaef0bc3dcd3b7d6883043529baac02cdb6b898c (patch)
treeb89e3f5dc8a14dd40b36f18eb48b9f2bbfb5aece /src/creds/creds.c
parentbus-polkit: port polkit_registry to use value destructors in hash_ops (diff)
downloadsystemd-caef0bc3dcd3b7d6883043529baac02cdb6b898c.tar.xz
systemd-caef0bc3dcd3b7d6883043529baac02cdb6b898c.zip
creds: open up access to clients via Polkit
Use auth_admin_keep, so that users don't have to re-auth interactively again and again when encrypting/decrypting batches of credentials.
Diffstat (limited to 'src/creds/creds.c')
-rw-r--r--src/creds/creds.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/src/creds/creds.c b/src/creds/creds.c
index ed39ffe51e..5586baff9a 100644
--- a/src/creds/creds.c
+++ b/src/creds/creds.c
@@ -4,6 +4,7 @@
#include <unistd.h>
#include "build.h"
+#include "bus-polkit.h"
#include "creds-util.h"
#include "dirent-util.h"
#include "escape.h"
@@ -983,6 +984,7 @@ static int vl_method_encrypt(Varlink *link, JsonVariant *parameters, VarlinkMeth
{ "data", JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(MethodEncryptParameters, data), 0 },
{ "timestamp", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(MethodEncryptParameters, timestamp), 0 },
{ "notAfter", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(MethodEncryptParameters, not_after), 0 },
+ VARLINK_DISPATCH_POLKIT_FIELD,
{}
};
_cleanup_(method_encrypt_parameters_done) MethodEncryptParameters p = {
@@ -990,6 +992,7 @@ static int vl_method_encrypt(Varlink *link, JsonVariant *parameters, VarlinkMeth
.not_after = UINT64_MAX,
};
_cleanup_(iovec_done) struct iovec output = {};
+ Hashmap **polkit_registry = ASSERT_PTR(userdata);
int r;
assert(link);
@@ -1010,6 +1013,16 @@ static int vl_method_encrypt(Varlink *link, JsonVariant *parameters, VarlinkMeth
if (p.not_after != UINT64_MAX && p.not_after < p.timestamp)
return varlink_error_invalid_parameter_name(link, "notAfter");
+ r = varlink_verify_polkit_async(
+ link,
+ /* bus= */ NULL,
+ "io.systemd.credentials.encrypt",
+ /* details= */ NULL,
+ /* good_user= */ UID_INVALID,
+ polkit_registry);
+ if (r <= 0)
+ return r;
+
r = encrypt_credential_and_warn(
arg_with_key,
p.name,
@@ -1051,15 +1064,17 @@ static void method_decrypt_parameters_done(MethodDecryptParameters *p) {
static int vl_method_decrypt(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
static const JsonDispatch dispatch_table[] = {
- { "name", JSON_VARIANT_STRING, json_dispatch_const_string, offsetof(MethodDecryptParameters, name), 0 },
- { "blob", JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(MethodDecryptParameters, blob), 0 },
- { "timestamp", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(MethodDecryptParameters, timestamp), 0 },
+ { "name", JSON_VARIANT_STRING, json_dispatch_const_string, offsetof(MethodDecryptParameters, name), 0 },
+ { "blob", JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, offsetof(MethodDecryptParameters, blob), JSON_MANDATORY },
+ { "timestamp", _JSON_VARIANT_TYPE_INVALID, json_dispatch_uint64, offsetof(MethodDecryptParameters, timestamp), 0 },
+ VARLINK_DISPATCH_POLKIT_FIELD,
{}
};
_cleanup_(method_decrypt_parameters_done) MethodDecryptParameters p = {
.timestamp = UINT64_MAX,
};
_cleanup_(iovec_done_erase) struct iovec output = {};
+ Hashmap **polkit_registry = ASSERT_PTR(userdata);
int r;
assert(link);
@@ -1073,11 +1088,19 @@ static int vl_method_decrypt(Varlink *link, JsonVariant *parameters, VarlinkMeth
if (p.name && !credential_name_valid(p.name))
return varlink_error_invalid_parameter_name(link, "name");
- if (!p.blob.iov_base)
- return varlink_error_invalid_parameter_name(link, "blob");
if (p.timestamp == UINT64_MAX)
p.timestamp = now(CLOCK_REALTIME);
+ r = varlink_verify_polkit_async(
+ link,
+ /* bus= */ NULL,
+ "io.systemd.credentials.decrypt",
+ /* details= */ NULL,
+ /* good_user= */ UID_INVALID,
+ polkit_registry);
+ if (r <= 0)
+ return r;
+
r = decrypt_credential_and_warn(
p.name,
p.timestamp,
@@ -1116,10 +1139,11 @@ static int run(int argc, char *argv[]) {
if (arg_varlink) {
_cleanup_(varlink_server_unrefp) VarlinkServer *varlink_server = NULL;
+ _cleanup_(hashmap_freep) Hashmap *polkit_registry = NULL;
/* Invocation as Varlink service */
- r = varlink_server_new(&varlink_server, VARLINK_SERVER_ROOT_ONLY|VARLINK_SERVER_INHERIT_USERDATA);
+ r = varlink_server_new(&varlink_server, VARLINK_SERVER_ACCOUNT_UID|VARLINK_SERVER_INHERIT_USERDATA);
if (r < 0)
return log_error_errno(r, "Failed to allocate Varlink server: %m");
@@ -1134,6 +1158,8 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return log_error_errno(r, "Failed to bind Varlink methods: %m");
+ varlink_server_set_userdata(varlink_server, &polkit_registry);
+
r = varlink_server_loop_auto(varlink_server);
if (r < 0)
return log_error_errno(r, "Failed to run Varlink event loop: %m");