From 9e4a9cc2fd66ead323343c1c0be0ad7408f8286c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20G=C3=B3mez=20Garc=C3=ADa?= Date: Thu, 17 Jun 2021 14:21:40 +0200 Subject: [PATCH] * Added deadline "disabling" on osmanagers, so if we dont want to close sessions for expired users, we can do it --- actor/src/udsactor/client.py | 2 +- server/src/uds/REST/methods/actor_v3.py | 10 ++++++- server/src/uds/core/osmanagers/osmanager.py | 3 +++ .../LinuxOsManager/linux_osmanager.py | 26 ++++++++++++++++--- .../linux_randompass_osmanager.py | 1 + .../osmanagers/WindowsOsManager/windows.py | 26 ++++++++++++++++--- .../WindowsOsManager/windows_domain.py | 1 + .../WindowsOsManager/windows_random.py | 1 + server/src/uds/web/util/services.py | 19 ++++++++------ 9 files changed, 72 insertions(+), 17 deletions(-) diff --git a/actor/src/udsactor/client.py b/actor/src/udsactor/client.py index d8795b6ea..2678a57bd 100644 --- a/actor/src/udsactor/client.py +++ b/actor/src/udsactor/client.py @@ -232,7 +232,7 @@ class UDSActorClient(threading.Thread): # pylint: disable=too-many-instance-att On windows, an RDP session with minimized screen will render "black screen" So only when user is using RDP connection will return an "actual" screenshot ''' - pixmap: 'QPixmap' = self._qApp.primaryScreen().grabWindow(0) + pixmap: 'QPixmap' = self._qApp.primaryScreen().grabWindow(0) # type: ignore ba = QByteArray() buffer = QBuffer(ba) buffer.open(QIODevice.WriteOnly) diff --git a/server/src/uds/REST/methods/actor_v3.py b/server/src/uds/REST/methods/actor_v3.py index b80af774d..1d818bfa3 100644 --- a/server/src/uds/REST/methods/actor_v3.py +++ b/server/src/uds/REST/methods/actor_v3.py @@ -447,7 +447,15 @@ class Login(LoginLogout): logger.debug('Max idle: %s', maxIdle) ip, hostname = userService.getConnectionSource() - deadLine = userService.deployed_service.getDeadline() + + if osManager: # For os managed services, let's check if we honor deadline + if osManager.ignoreDeadLine(): + deadLine = userService.deployed_service.getDeadline() + else: + deadLine = None + else: # For non os manager machines, process deadline as always + deadLine = userService.deployed_service.getDeadline() + except Exception: # If unamanaged host, lest do a bit more work looking for a service with the provided parameters... if isManaged: raise diff --git a/server/src/uds/core/osmanagers/osmanager.py b/server/src/uds/core/osmanagers/osmanager.py index f991c0fe3..98afdeb94 100644 --- a/server/src/uds/core/osmanagers/osmanager.py +++ b/server/src/uds/core/osmanagers/osmanager.py @@ -171,6 +171,9 @@ class OSManager(Module): """ return None + def ignoreDeadLine(self) -> bool: + return False + @classmethod def transformsUserOrPasswordForService(cls: typing.Type['OSManager']) -> bool: """ diff --git a/server/src/uds/osmanagers/LinuxOsManager/linux_osmanager.py b/server/src/uds/osmanagers/LinuxOsManager/linux_osmanager.py index 9ff37358b..c93d3de27 100644 --- a/server/src/uds/osmanagers/LinuxOsManager/linux_osmanager.py +++ b/server/src/uds/osmanagers/LinuxOsManager/linux_osmanager.py @@ -77,6 +77,16 @@ class LinuxOsManager(osmanagers.OSManager): tooltip=_('Maximum idle time (in seconds) before session is automatically closed to the user (<= 0 means no max idle time).'), required=True) + deadLine = gui.CheckBoxField( + label=_('Calendar logout'), + order=90, + tooltip=_( + 'If checked, UDS will try to logout user when the calendar for his current access expires' + ), + tab=gui.ADVANCED_TAB, + defvalue=gui.TRUE, + ) + def __setProcessUnusedMachines(self): self.processUnusedMachines = self._onLogout == 'remove' @@ -85,15 +95,20 @@ class LinuxOsManager(osmanagers.OSManager): if values is not None: self._onLogout = values['onLogout'] self._idle = int(values['idle']) + self._deadLine = gui.strToBool(values['deadLine']) else: self._onLogout = '' self._idle = -1 + self._deadLine = True self.__setProcessUnusedMachines() def release(self, userService: 'UserService') -> None: pass + def ignoreDeadLine(self) -> bool: + return not self._deadLine + def isRemovableOnLogout(self, userService: 'UserService') -> bool: ''' Says if a machine is removable on logout @@ -254,17 +269,20 @@ class LinuxOsManager(osmanagers.OSManager): """ Serializes the os manager data so we can store it in database """ - return '\t'.join(['v2', self._onLogout, str(self._idle)]).encode('utf8') + return '\t'.join(['v3', self._onLogout, str(self._idle), gui.boolToStr(self._deadLine)]).encode('utf8') def unmarshal(self, data: bytes): values = data.decode('utf8').split('\t') + self._idle = -1 + self._deadLine = True if values[0] == 'v1': self._onLogout = values[1] - self._idle = -1 elif values[0] == 'v2': self._onLogout, self._idle = values[1], int(values[2]) + elif values[0] == 'v3': + self._onLogout, self._idle, self._deadLine = values[1], int(values[2]), gui.strToBool(values[3]) self.__setProcessUnusedMachines() - def valuesDict(self): - return {'onLogout': self._onLogout, 'idle': self._idle} + def valuesDict(self) -> gui.ValuesDictType: + return {'onLogout': self._onLogout, 'idle': str(self._idle), 'deadLine': gui.boolToStr(self._deadLine) } diff --git a/server/src/uds/osmanagers/LinuxOsManager/linux_randompass_osmanager.py b/server/src/uds/osmanagers/LinuxOsManager/linux_randompass_osmanager.py index fc171faa6..95c83b54f 100644 --- a/server/src/uds/osmanagers/LinuxOsManager/linux_randompass_osmanager.py +++ b/server/src/uds/osmanagers/LinuxOsManager/linux_randompass_osmanager.py @@ -60,6 +60,7 @@ class LinuxRandomPassManager(LinuxOsManager): # Inherits base "onLogout" onLogout = LinuxOsManager.onLogout idle = LinuxOsManager.idle + deadLine = LinuxOsManager.deadLine _userAccount: str diff --git a/server/src/uds/osmanagers/WindowsOsManager/windows.py b/server/src/uds/osmanagers/WindowsOsManager/windows.py index 875faa589..4917e7b9e 100644 --- a/server/src/uds/osmanagers/WindowsOsManager/windows.py +++ b/server/src/uds/osmanagers/WindowsOsManager/windows.py @@ -75,8 +75,20 @@ class WindowsOsManager(osmanagers.OSManager): ), required=True, ) + + deadLine = gui.CheckBoxField( + label=_('Calendar logout'), + order=90, + tooltip=_( + 'If checked, UDS will try to logout user when the calendar for his current access expires' + ), + tab=gui.ADVANCED_TAB, + defvalue=gui.TRUE, + ) + _onLogout: str _idle: int + _deadLine: bool @staticmethod def validateLen(length): @@ -100,9 +112,11 @@ class WindowsOsManager(osmanagers.OSManager): if values is not None: self._onLogout = values['onLogout'] self._idle = int(values['idle']) + self._deadLine = gui.strToBool(values['deadLine']) else: self._onLogout = '' self._idle = -1 + self._deadLine = True self.__setProcessUnusedMachines() @@ -121,6 +135,9 @@ class WindowsOsManager(osmanagers.OSManager): def release(self, userService: 'UserService') -> None: pass + def ignoreDeadLine(self) -> bool: + return not self._deadLine + def getName(self, userService: 'UserService') -> str: return userService.getName() @@ -333,16 +350,19 @@ class WindowsOsManager(osmanagers.OSManager): """ Serializes the os manager data so we can store it in database """ - return '\t'.join(['v2', self._onLogout, str(self._idle)]).encode('utf8') + return '\t'.join(['v3', self._onLogout, str(self._idle), gui.boolToStr(self._deadLine)]).encode('utf8') def unmarshal(self, data: bytes) -> None: vals = data.decode('utf8').split('\t') + self._idle = -1 + self._deadLine = True try: if vals[0] == 'v1': self._onLogout = vals[1] - self._idle = -1 elif vals[0] == 'v2': self._onLogout, self._idle = vals[1], int(vals[2]) + elif vals[0] == 'v3': + self._onLogout, self._idle, self._deadLine = vals[1], int(vals[2]), gui.strToBool(vals[3]) except Exception: logger.exception( 'Exception unmarshalling. Some values left as default ones' @@ -351,4 +371,4 @@ class WindowsOsManager(osmanagers.OSManager): self.__setProcessUnusedMachines() def valuesDict(self) -> gui.ValuesDictType: - return {'onLogout': self._onLogout, 'idle': str(self._idle)} + return {'onLogout': self._onLogout, 'idle': str(self._idle), 'deadLine': gui.boolToStr(self._deadLine) } diff --git a/server/src/uds/osmanagers/WindowsOsManager/windows_domain.py b/server/src/uds/osmanagers/WindowsOsManager/windows_domain.py index 786fad6ca..9059539d1 100644 --- a/server/src/uds/osmanagers/WindowsOsManager/windows_domain.py +++ b/server/src/uds/osmanagers/WindowsOsManager/windows_domain.py @@ -131,6 +131,7 @@ class WinDomainOsManager(WindowsOsManager): # Inherits base "onLogout" onLogout = WindowsOsManager.onLogout idle = WindowsOsManager.idle + deadLine = WindowsOsManager.deadLine _domain: str _ou: str diff --git a/server/src/uds/osmanagers/WindowsOsManager/windows_random.py b/server/src/uds/osmanagers/WindowsOsManager/windows_random.py index 96696c600..b634bf99b 100644 --- a/server/src/uds/osmanagers/WindowsOsManager/windows_random.py +++ b/server/src/uds/osmanagers/WindowsOsManager/windows_random.py @@ -68,6 +68,7 @@ class WinRandomPassManager(WindowsOsManager): # Inherits base "onLogout" onLogout = WindowsOsManager.onLogout idle = WindowsOsManager.idle + deadLine = WindowsOsManager.deadLine def __init__(self, environment: 'Environment', values: 'Module.ValuesType'): super().__init__(environment, values) diff --git a/server/src/uds/web/util/services.py b/server/src/uds/web/util/services.py index 8fafa566e..7f1e26550 100644 --- a/server/src/uds/web/util/services.py +++ b/server/src/uds/web/util/services.py @@ -115,14 +115,17 @@ def getServicesData( # Metapool helpers def transportIterator(member) -> typing.Iterable[Transport]: for t in member.pool.transports.all().order_by('priority'): - typeTrans = t.getType() - if ( - typeTrans - and t.validForIp(request.ip) - and typeTrans.supportsOs(osName) - and t.validForOs(osName) - ): - yield t + try: + typeTrans = t.getType() + if ( + typeTrans + and t.validForIp(request.ip) + and typeTrans.supportsOs(osName) + and t.validForOs(osName) + ): + yield t + except Exception as e: + logger.warning('Transport %s of %s not found. Ignoring. (%s)', t, member.pool, e) def buildMetaTransports( transports: typing.Iterable[Transport],