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 failed: no agent is available to authenticate -
no polkit agent for 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. It also has a check for a failure to start the text
polkit authentication agent as testing as shown the agent startup isn't
necessarily immediate.
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(a)redhat.com>
---
tools/virsh.c | 49 ++++++++++++++++++++++++++++++++++++++++++++-----
tools/virsh.h | 2 ++
2 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index b96dbda..c9da9f1 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -143,6 +143,9 @@ virshConnect(vshControl *ctl, const char *uri, bool readonly)
int interval = 5; /* Default */
int count = 6; /* Default */
bool keepalive_forced = false;
+ virCommandPtr pkagent = NULL;
+ int authfail = 0;
+ int agentstart = 0;
if (ctl->keepalive_interval >= 0) {
interval = ctl->keepalive_interval;
@@ -153,10 +156,43 @@ virshConnect(vshControl *ctl, const char *uri, bool readonly)
keepalive_forced = true;
}
- c = virConnectOpenAuth(uri, virConnectAuthPtrDefault,
- readonly ? VIR_CONNECT_RO : 0);
- if (!c)
- return NULL;
+ do {
+ virErrorPtr err;
+
+ if ((c = virConnectOpenAuth(uri, virConnectAuthPtrDefault,
+ readonly ? VIR_CONNECT_RO : 0)))
+ break;
+
+ if (readonly)
+ goto cleanup;
+
+ err = virGetLastError();
+ if (err && strstr(err->message,
+ _("no agent is available to authenticate"))) {
+ if (!pkagent) {
+ if (!(pkagent = virPolkitAgentCreate()))
+ goto cleanup;
+ }
+ agentstart++;
+ } else if (err && strstr(err->message, _("authentication
failed:"))) {
+ authfail++;
+ } else {
+ goto cleanup;
+ }
+ virResetLastError();
+ /* If we fail to authenticate 5 times or we fail to successfully
+ * connect with the agent after 10 attempts, then fail out.
+ * No sense prolonging the agony
+ */
+ } while (authfail < 5 && agentstart < 10);
+
+ if (!c) {
+ /* If we failed because we couldn't start the agent, give a reason */
+ if (agentstart == 10)
+ vshError(ctl, "%s",
+ _("Cannot setup a polkit text authentication agent"));
+ goto cleanup;
+ }
if (interval > 0 &&
virConnectSetKeepAlive(c, interval, count) != 0) {
@@ -165,12 +201,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..a6c7289 100644
--- a/tools/virsh.h
+++ b/tools/virsh.h
@@ -36,6 +36,8 @@
# include "internal.h"
# include "virerror.h"
# include "virthread.h"
+# include "vircommand.h"
+# include "virpolkit.h"
# include "vsh.h"
# define VIRSH_PROMPT_RW "virsh # "
--
2.5.0