[PATCH 7/7] util: Make client-side polkit work even with polkit disabled

Martin Kletzander mkletzan at redhat.com
Sat Nov 20 23:10:08 UTC 2021


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 at redhat.com>
---
 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 at a{sv})s at 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 at a{sv})s at 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




More information about the libvir-list mailing list