The reason for this is twofold: - the polkit build option is documented for UNIX socket access checks - there is no server-side change or dbus call done when enabling this as it only starts a polkit agent on the client-side (actually only in virsh) and does not need any requirements (starting is skipped if pkttyagent is not installed) Also move the conditional implementation to the bottom of the file so that it does not look like the whole file is build conditionally and the common functions are at the top. Signed-off-by: Martin Kletzander <mkletzan@xxxxxxxxxx> --- src/util/virpolkit.c | 240 ++++++++++++++++++++----------------------- 1 file changed, 109 insertions(+), 131 deletions(-) diff --git a/src/util/virpolkit.c b/src/util/virpolkit.c index 7156adc10c0a..b51104100796 100644 --- a/src/util/virpolkit.c +++ b/src/util/virpolkit.c @@ -21,6 +21,7 @@ #include <config.h> #include <fcntl.h> +#include <poll.h> #include <unistd.h> #include "virpolkit.h" @@ -37,119 +38,10 @@ VIR_LOG_INIT("util.polkit"); -#if WITH_POLKIT -# include <poll.h> - struct _virPolkitAgent { virCommand *cmd; }; -/* - * virPolkitCheckAuth: - * @actionid: permission to check - * @pid: client process ID - * @startTime: process start time, or 0 - * @uid: client process user ID - * @details: NULL terminated (key, value) pair list - * @allowInteraction: true if auth prompts are allowed - * - * Check if a client is authenticated with polkit - * - * Returns 0 on success, -1 on failure, -2 on auth denied - */ -int virPolkitCheckAuth(const char *actionid, - pid_t pid, - unsigned long long startTime, - uid_t uid, - const char **details, - bool allowInteraction) -{ - GDBusConnection *sysbus; - GVariantBuilder builder; - GVariant *gprocess = NULL; - GVariant *gdetails = NULL; - g_autoptr(GVariant) message = NULL; - g_autoptr(GVariant) reply = NULL; - g_autoptr(GVariantIter) iter = NULL; - char *retkey; - char *retval; - gboolean is_authorized; - gboolean is_challenge; - bool is_dismissed = false; - const char **next; - - if (!(sysbus = virGDBusGetSystemBus())) - return -1; - - VIR_INFO("Checking PID %lld running as %d", - (long long) pid, uid); - - g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); - g_variant_builder_add(&builder, "{sv}", "pid", g_variant_new_uint32(pid)); - g_variant_builder_add(&builder, "{sv}", "start-time", g_variant_new_uint64(startTime)); - g_variant_builder_add(&builder, "{sv}", "uid", g_variant_new_int32(uid)); - gprocess = g_variant_builder_end(&builder); - - g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}")); - - if (details) { - for (next = details; *next; next++) { - const char *detail1 = *(next++); - const char *detail2 = *next; - g_variant_builder_add(&builder, "{ss}", detail1, detail2); - } - } - - gdetails = g_variant_builder_end(&builder); - - message = g_variant_new("((s@a{sv})s@a{ss}us)", - "unix-process", - gprocess, - actionid, - gdetails, - allowInteraction, - "" /* cancellation ID */); - - if (virGDBusCallMethod(sysbus, - &reply, - G_VARIANT_TYPE("((bba{ss}))"), - NULL, - "org.freedesktop.PolicyKit1", - "/org/freedesktop/PolicyKit1/Authority", - "org.freedesktop.PolicyKit1.Authority", - "CheckAuthorization", - message) < 0) - return -1; - - g_variant_get(reply, "((bba{ss}))", &is_authorized, &is_challenge, &iter); - - while (g_variant_iter_loop(iter, "{ss}", &retkey, &retval)) { - if (STREQ(retkey, "polkit.dismissed") && STREQ(retval, "true")) - is_dismissed = true; - } - - VIR_DEBUG("is auth %d is challenge %d", - is_authorized, is_challenge); - - if (is_authorized) - return 0; - - if (is_dismissed) { - virReportError(VIR_ERR_AUTH_CANCELLED, "%s", - _("user cancelled authentication process")); - } else if (is_challenge) { - virReportError(VIR_ERR_AUTH_UNAVAILABLE, - _("no polkit agent available to authenticate action '%s'"), - actionid); - } else { - virReportError(VIR_ERR_AUTH_FAILED, "%s", - _("access denied by policy")); - } - - return -2; -} - - /* virPolkitAgentDestroy: * @cmd: Pointer to the virCommand * created during virPolkitAgentCreate * @@ -260,6 +152,114 @@ virPolkitAgentAvailable(void) return true; } + +#if WITH_POLKIT + +/* + * virPolkitCheckAuth: + * @actionid: permission to check + * @pid: client process ID + * @startTime: process start time, or 0 + * @uid: client process user ID + * @details: NULL terminated (key, value) pair list + * @allowInteraction: true if auth prompts are allowed + * + * Check if a client is authenticated with polkit + * + * Returns 0 on success, -1 on failure, -2 on auth denied + */ +int virPolkitCheckAuth(const char *actionid, + pid_t pid, + unsigned long long startTime, + uid_t uid, + const char **details, + bool allowInteraction) +{ + GDBusConnection *sysbus; + GVariantBuilder builder; + GVariant *gprocess = NULL; + GVariant *gdetails = NULL; + g_autoptr(GVariant) message = NULL; + g_autoptr(GVariant) reply = NULL; + g_autoptr(GVariantIter) iter = NULL; + char *retkey; + char *retval; + gboolean is_authorized; + gboolean is_challenge; + bool is_dismissed = false; + const char **next; + + if (!(sysbus = virGDBusGetSystemBus())) + return -1; + + VIR_INFO("Checking PID %lld running as %d", + (long long) pid, uid); + + g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(&builder, "{sv}", "pid", g_variant_new_uint32(pid)); + g_variant_builder_add(&builder, "{sv}", "start-time", g_variant_new_uint64(startTime)); + g_variant_builder_add(&builder, "{sv}", "uid", g_variant_new_int32(uid)); + gprocess = g_variant_builder_end(&builder); + + g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}")); + + if (details) { + for (next = details; *next; next++) { + const char *detail1 = *(next++); + const char *detail2 = *next; + g_variant_builder_add(&builder, "{ss}", detail1, detail2); + } + } + + gdetails = g_variant_builder_end(&builder); + + message = g_variant_new("((s@a{sv})s@a{ss}us)", + "unix-process", + gprocess, + actionid, + gdetails, + allowInteraction, + "" /* cancellation ID */); + + if (virGDBusCallMethod(sysbus, + &reply, + G_VARIANT_TYPE("((bba{ss}))"), + NULL, + "org.freedesktop.PolicyKit1", + "/org/freedesktop/PolicyKit1/Authority", + "org.freedesktop.PolicyKit1.Authority", + "CheckAuthorization", + message) < 0) + return -1; + + g_variant_get(reply, "((bba{ss}))", &is_authorized, &is_challenge, &iter); + + while (g_variant_iter_loop(iter, "{ss}", &retkey, &retval)) { + if (STREQ(retkey, "polkit.dismissed") && STREQ(retval, "true")) + is_dismissed = true; + } + + VIR_DEBUG("is auth %d is challenge %d", + is_authorized, is_challenge); + + if (is_authorized) + return 0; + + if (is_dismissed) { + virReportError(VIR_ERR_AUTH_CANCELLED, "%s", + _("user cancelled authentication process")); + } else if (is_challenge) { + virReportError(VIR_ERR_AUTH_UNAVAILABLE, + _("no polkit agent available to authenticate action '%s'"), + actionid); + } else { + virReportError(VIR_ERR_AUTH_FAILED, "%s", + _("access denied by policy")); + } + + return -2; +} + #else /* ! WITH_POLKIT */ int virPolkitCheckAuth(const char *actionid G_GNUC_UNUSED, @@ -275,26 +275,4 @@ int virPolkitCheckAuth(const char *actionid G_GNUC_UNUSED, return -1; } - -void -virPolkitAgentDestroy(virPolkitAgent *agent G_GNUC_UNUSED) -{ - return; /* do nothing */ -} - - -virPolkitAgent * -virPolkitAgentCreate(void) -{ - virReportError(VIR_ERR_AUTH_FAILED, "%s", - _("polkit text authentication agent unavailable")); - return NULL; -} - -bool -virPolkitAgentAvailable(void) -{ - return false; -} - #endif /* WITH_POLKIT */ -- 2.34.0