From: Lennart Poettering Date: Thu, 23 Nov 2023 21:22:27 +0000 (+0100) Subject: creds: open up access to clients via Polkit X-Git-Tag: v256-rc1~1307^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=caef0bc3dcd3b7d6883043529baac02cdb6b898c;p=thirdparty%2Fsystemd.git 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. --- diff --git a/src/creds/creds.c b/src/creds/creds.c index ed39ffe51e1..5586baff9a4 100644 --- a/src/creds/creds.c +++ b/src/creds/creds.c @@ -4,6 +4,7 @@ #include #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"); diff --git a/src/creds/io.systemd.credentials.policy b/src/creds/io.systemd.credentials.policy new file mode 100644 index 00000000000..f94571b215b --- /dev/null +++ b/src/creds/io.systemd.credentials.policy @@ -0,0 +1,40 @@ + + + + + + + + The systemd Project + https://systemd.io + + + Allow encryption and signing of system credentials. + Authentication is required for an application to encrypt and sign a system credential. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + Allow decryption of system credentials. + Authentication is required for an application to decrypto a system credential. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + diff --git a/src/creds/meson.build b/src/creds/meson.build index 85572568f6c..24833110d53 100644 --- a/src/creds/meson.build +++ b/src/creds/meson.build @@ -23,3 +23,6 @@ if install_sysconfdir install_emptydir(sysconfdir / 'credstore.encrypted', install_mode : 'rwx------') endif + +install_data('io.systemd.credentials.policy', + install_dir : polkitpolicydir) diff --git a/units/systemd-creds.socket b/units/systemd-creds.socket index 794fac19a84..ac72ccc82f1 100644 --- a/units/systemd-creds.socket +++ b/units/systemd-creds.socket @@ -16,7 +16,7 @@ Before=sockets.target [Socket] ListenStream=/run/systemd/io.systemd.Credentials FileDescriptorName=varlink -SocketMode=0600 +SocketMode=0666 Accept=yes [Install]