console: Catch and handle password auth errors (bz 1151801)

This commit is contained in:
Cole Robinson 2015-04-12 13:04:32 -04:00
parent 4e47cc9061
commit 6ecf01a3bd
4 changed files with 48 additions and 33 deletions

View File

@ -487,9 +487,6 @@ class vmmConsolePages(vmmGObjectUI):
##########################
def _show_vm_status_unavailable(self):
self.widget("console-pages").set_current_page(
self.CONSOLE_PAGE_UNAVAILABLE)
if self.vm.is_crashed():
self._activate_unavailable_page(_("Guest has crashed"))
else:
@ -511,9 +508,9 @@ class vmmConsolePages(vmmGObjectUI):
for serial in self._serial_tabs:
serial.close()
def _update_widget_states(self, vm, status_ignore):
runable = vm.is_runable()
paused = vm.is_paused()
def _update_vm_widget_states(self):
runable = self.vm.is_runable()
paused = self.vm.is_paused()
pages = self.widget("console-pages")
page = pages.get_current_page()
@ -714,10 +711,23 @@ class vmmConsolePages(vmmGObjectUI):
else:
self._enable_modifiers()
def _viewer_auth_error(self, viewer, errmsg):
viewer.close()
def _viewer_auth_rejected(self, ignore, errmsg):
self._close_viewer()
self._activate_unavailable_page(errmsg)
def _viewer_auth_error(self, ignore, errmsg, viewer_will_disconnect):
errmsg = _("Viewer authentication error: %s") % errmsg
self.err.val_err(errmsg)
if viewer_will_disconnect:
# GtkVNC will disconnect after an auth error, so lets do it for
# them and re-init the viewer (which will be triggered by
# update_vm_widget_states if needed)
self._close_viewer()
self._activate_unavailable_page(errmsg)
self._update_vm_widget_states()
def _viewer_need_auth(self, ignore, withPassword, withUsername):
self._activate_auth_page(withPassword, withUsername)
@ -744,15 +754,14 @@ class vmmConsolePages(vmmGObjectUI):
if self.vm.is_runable():
# Exit was probably for legitimate reasons
self._show_vm_status_unavailable()
return
else:
error = _("Error: viewer connection to hypervisor host got "
"refused or disconnected!")
if errout:
logging.debug("Error output from closed console: %s", errout)
error += "\n\nError: %s" % errout
self._activate_unavailable_page(error)
error = _("Error: viewer connection to hypervisor host got refused "
"or disconnected!")
if errout:
logging.debug("Error output from closed console: %s", errout)
error += "\n\nError: %s" % errout
self._activate_unavailable_page(error)
self._refresh_resizeguest_from_settings()
def _viewer_connected(self, ignore):
@ -775,6 +784,7 @@ class vmmConsolePages(vmmGObjectUI):
self._viewer.connect("connected", self._viewer_connected)
self._viewer.connect("disconnected", self._viewer_disconnected)
self._viewer.connect("auth-error", self._viewer_auth_error)
self._viewer.connect("auth-rejected", self._viewer_auth_rejected)
self._viewer.connect("need-auth", self._viewer_need_auth)
self._viewer.connect("agent-connected", self._viewer_agent_connected)
self._viewer.connect("usb-redirect-error",
@ -947,8 +957,8 @@ class vmmConsolePages(vmmGObjectUI):
def details_activate_default_console_page(self):
return self._activate_default_console_page()
def details_update_widget_states(self, *args, **kwargs):
return self._update_widget_states(*args, **kwargs)
def details_update_widget_states(self):
return self._update_vm_widget_states()
def details_build_keycombo_menu(self, *args, **kwargs):
return self._build_keycombo_menu(*args, **kwargs)
@ -972,7 +982,4 @@ class vmmConsolePages(vmmGObjectUI):
self._change_fullscreen(do_fullscreen)
def details_auth_login(self, ignore):
self.widget("console-pages").set_current_page(
self.CONSOLE_PAGE_UNAVAILABLE)
self._set_credentials()
self._activate_viewer_page()

View File

@ -1336,7 +1336,7 @@ class vmmDetails(vmmGObjectUI):
for c in send_key.get_submenu().get_children():
c.set_sensitive(not (run or paused))
self.console.details_update_widget_states(vm, status)
self.console.details_update_widget_states()
if not run:
self.activate_default_console_page()

View File

@ -274,6 +274,7 @@ class SSHTunnels(object):
for l in self._tunnels:
l.close()
self._tunnels = []
self.unlock()
def get_err_output(self):
errout = ""

View File

@ -53,7 +53,8 @@ class Viewer(vmmGObject):
"pointer-ungrab": (GObject.SignalFlags.RUN_FIRST, None, []),
"connected": (GObject.SignalFlags.RUN_FIRST, None, []),
"disconnected": (GObject.SignalFlags.RUN_FIRST, None, []),
"auth-error": (GObject.SignalFlags.RUN_FIRST, None, [str]),
"auth-error": (GObject.SignalFlags.RUN_FIRST, None, [str, bool]),
"auth-rejected": (GObject.SignalFlags.RUN_FIRST, None, [str]),
"need-auth": (GObject.SignalFlags.RUN_FIRST, None, [bool, bool]),
"agent-connected": (GObject.SignalFlags.RUN_FIRST, None, []),
"usb-redirect-error": (GObject.SignalFlags.RUN_FIRST, None, [str]),
@ -80,9 +81,7 @@ class Viewer(vmmGObject):
self._display.destroy()
self._display = None
if self._tunnels:
self._tunnels.close_all()
self._tunnels = None
self._tunnels.close_all()
########################
@ -288,6 +287,7 @@ class VNCViewer(Viewer):
self._make_signal_proxy("pointer-ungrab"))
self._display.connect("vnc-auth-credential", self._auth_credential)
self._display.connect("vnc-auth-failure", self._auth_failure_cb)
self._display.connect("vnc-initialized", self._connected_cb)
self._display.connect("vnc-disconnected", self._disconnected_cb)
self._display.connect("vnc-desktop-resize", self._desktop_resize)
@ -307,6 +307,10 @@ class VNCViewer(Viewer):
# Queue a resize
self.emit("size-allocate", None)
def _auth_failure_cb(self, ignore, msg):
logging.debug("VNC auth failure. msg=%s", msg)
self.emit("auth-error", msg, True)
def _auth_credential(self, src_ignore, credList):
values = []
for idx in range(int(credList.n_values)):
@ -322,7 +326,8 @@ class VNCViewer(Viewer):
"server.\n The credential type %s is not supported") %
str(cred))
self.emit("auth-error", errmsg)
# XXX test this
self.emit("auth-rejected", errmsg)
return
withUsername = False
@ -349,7 +354,6 @@ class VNCViewer(Viewer):
if self._sockfd:
self._sockfd.close()
self._sockfd = None
self._tunnels.close_all()
def _is_open(self):
return self._display.is_open()
@ -519,10 +523,14 @@ class SpiceViewer(Viewer):
if event == SpiceClientGLib.ChannelEvent.CLOSED:
self.emit("disconnected")
elif event == SpiceClientGLib.ChannelEvent.ERROR_AUTH:
logging.debug("Spice channel received ERROR_AUTH, assuming "
"it needs credentials.")
self.emit("need-auth", True, False)
self._close_main_channel()
if not self._spice_session.get_property("password"):
logging.debug("Spice channel received ERROR_AUTH, but no "
"password set, assuming it wants credentials.")
self.emit("need-auth", True, False)
else:
logging.debug("Spice channel received ERROR_AUTH, but a "
"password is already set. Assuming authentication failed.")
self.emit("auth-error", channel.get_error().message, False)
elif event in [SpiceClientGLib.ChannelEvent.ERROR_CONNECT,
SpiceClientGLib.ChannelEvent.ERROR_IO,
SpiceClientGLib.ChannelEvent.ERROR_LINK,
@ -603,7 +611,6 @@ class SpiceViewer(Viewer):
self._close_main_channel()
self._usbdev_manager = None
self._tunnels.close_all()
def _is_open(self):
return self._spice_session is not None