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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list