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