[libvirt] [PATCH v4 3/3] virsh: Add support for text based polkit authentication

John Ferlan jferlan at redhat.com
Thu Feb 25 17:01:59 UTC 2016


https://bugzilla.redhat.com/show_bug.cgi?id=872166

When the login session doesn't have an ssh -X type display agent in
order for libvirtd to run the polkit session authentication, attempts
to run 'virsh -c qemu:///system list' from an unauthorized user (or one
that isn't part of the libvirt /etc/group) will fail with the following
error from libvirtd:

error: authentication unavailable: no polkit agent available to
       authenticate action 'org.libvirt.unix.manage'

In order to handle the local authentication, we will use the new
virPolkitAgentCreate API in order to create a text based authentication
agent for our non readonly session to authenticate with.

The new code will execute in a loop allowing 5 failures to authenticate
before failing out.

With this patch in place, the following occurs:

$ virsh -c qemu:///system list
==== AUTHENTICATING FOR org.libvirt.unix.manage ===
System policy prevents management of local virtualized systems
Authenticating as: Some User (SUser)
Password:
==== AUTHENTICATION COMPLETE ===
 Id    Name                           State
 ----------------------------------------------------
  1     somedomain                     running

$

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 tools/virsh.c | 38 ++++++++++++++++++++++++++++++++++----
 tools/virsh.h |  1 +
 2 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/tools/virsh.c b/tools/virsh.c
index eb84dd0..72446be 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -143,6 +143,8 @@ virshConnect(vshControl *ctl, const char *uri, bool readonly)
     int interval = 5; /* Default */
     int count = 6;    /* Default */
     bool keepalive_forced = false;
+    virPolkitAgentPtr pkagent = NULL;
+    int authfail = 0;
 
     if (ctl->keepalive_interval >= 0) {
         interval = ctl->keepalive_interval;
@@ -153,10 +155,35 @@ virshConnect(vshControl *ctl, const char *uri, bool readonly)
         keepalive_forced = true;
     }
 
-    c = virConnectOpenAuth(uri, virConnectAuthPtrDefault,
-                           readonly ? VIR_CONNECT_RO : 0);
+    do {
+        virErrorPtr err;
+
+        if ((c = virConnectOpenAuth(uri, virConnectAuthPtrDefault,
+                                    readonly ? VIR_CONNECT_RO : 0)))
+            break;
+
+        if (readonly)
+            goto cleanup;
+
+        err = virGetLastError();
+        if (err && err->domain == VIR_FROM_POLKIT &&
+            err->code == VIR_ERR_AUTH_UNAVAILABLE) {
+            if (!(pkagent = virPolkitAgentCreate()))
+                goto cleanup;
+        } else if (err && err->domain == VIR_FROM_POLKIT &&
+                   err->code == VIR_ERR_AUTH_FAILED) {
+            authfail++;
+        } else {
+            goto cleanup;
+        }
+        virResetLastError();
+        /* Failure to authenticate 5 times should be enough.
+         * No sense prolonging the agony.
+         */
+    } while (authfail < 5);
+
     if (!c)
-        return NULL;
+        goto cleanup;
 
     if (interval > 0 &&
         virConnectSetKeepAlive(c, interval, count) != 0) {
@@ -165,12 +192,15 @@ virshConnect(vshControl *ctl, const char *uri, bool readonly)
                      _("Cannot setup keepalive on connection "
                        "as requested, disconnecting"));
             virConnectClose(c);
-            return NULL;
+            c = NULL;
+            goto cleanup;
         }
         vshDebug(ctl, VSH_ERR_INFO, "%s",
                  _("Failed to setup keepalive on connection\n"));
     }
 
+ cleanup:
+    virPolkitAgentDestroy(pkagent);
     return c;
 }
 
diff --git a/tools/virsh.h b/tools/virsh.h
index 8b5e5ba..fd552bb 100644
--- a/tools/virsh.h
+++ b/tools/virsh.h
@@ -36,6 +36,7 @@
 # include "internal.h"
 # include "virerror.h"
 # include "virthread.h"
+# include "virpolkit.h"
 # include "vsh.h"
 
 # define VIRSH_PROMPT_RW    "virsh # "
-- 
2.5.0




More information about the libvir-list mailing list