From e642b2ac34cdec2264416f7e86140e42a49c0f1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20G=C3=B3mez=20Garc=C3=ADa?= Date: Thu, 24 Aug 2023 15:56:37 +0200 Subject: [PATCH] Added support for Teams optimizations on direct transport --- server/src/uds/transports/RDP/rdp.py | 7 +++- server/src/uds/transports/RDP/rdp_base.py | 11 +++++ server/src/uds/transports/RDP/rdp_file.py | 5 ++- .../transports/RDP/scripts/windows/direct.py | 40 +++++++++++++------ .../RDP/scripts/windows/direct.py.signature | 2 +- 5 files changed, 48 insertions(+), 17 deletions(-) diff --git a/server/src/uds/transports/RDP/rdp.py b/server/src/uds/transports/RDP/rdp.py index 54f3a1fe3..aa9ea1ee1 100644 --- a/server/src/uds/transports/RDP/rdp.py +++ b/server/src/uds/transports/RDP/rdp.py @@ -12,7 +12,7 @@ # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. -# * Neither the name of Virtual Cable S.L. nor the names of its contributors +# * Neither the name of Virtual Cable S.L.U. nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # @@ -54,6 +54,8 @@ class RDPTransport(BaseRDPTransport): This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password ''' + isBase = False + typeName = _('RDP') typeType = 'RDPTransport' typeDescription = _('RDP Protocol. Direct connection.') @@ -92,6 +94,7 @@ class RDPTransport(BaseRDPTransport): customParameters = BaseRDPTransport.customParameters customParametersMAC = BaseRDPTransport.customParametersMAC customParametersWindows = BaseRDPTransport.customParametersWindows + optimizeTeams = BaseRDPTransport.optimizeTeams def getUDSTransportScript( # pylint: disable=too-many-locals self, @@ -144,6 +147,7 @@ class RDPTransport(BaseRDPTransport): r.printerString = self.printerString.value r.enforcedShares = self.enforceDrives.value r.redirectUSB = self.usbRedirection.value + r.optimizeTeams = self.optimizeTeams.isTrue() osName = { OsDetector.KnownOS.Windows: 'windows', @@ -175,6 +179,7 @@ class RDPTransport(BaseRDPTransport): sp.update( { 'as_file': r.as_file, + 'optimize_teams': self.optimizeTeams.isTrue(), } ) elif osName == 'linux': diff --git a/server/src/uds/transports/RDP/rdp_base.py b/server/src/uds/transports/RDP/rdp_base.py index eb28de4b8..eaf23a496 100644 --- a/server/src/uds/transports/RDP/rdp_base.py +++ b/server/src/uds/transports/RDP/rdp_base.py @@ -62,6 +62,8 @@ class BaseRDPTransport(transports.Transport): This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password """ + isBase = True + iconFile = 'rdp.png' protocol = transports.protocols.RDP @@ -346,6 +348,12 @@ class BaseRDPTransport(transports.Transport): tab='Windows Client', ) + optimizeTeams = gui.CheckBoxField( + label=_('Optimize Teams'), + order=46, + tooltip=_('If checked, Teams will be optimized (only works on Windows clients)'), + tab='Windows Client', + ) def isAvailableFor(self, userService: 'models.UserService', ip: str) -> bool: """ @@ -422,6 +430,9 @@ class BaseRDPTransport(transports.Transport): if azureAd: username = 'AzureAD\\' + username + if self.optimizeTeams.isTrue(): + password = '' # nosec + return { 'protocol': self.protocol, 'username': username, diff --git a/server/src/uds/transports/RDP/rdp_file.py b/server/src/uds/transports/RDP/rdp_file.py index bbc77967b..4abfcf806 100644 --- a/server/src/uds/transports/RDP/rdp_file.py +++ b/server/src/uds/transports/RDP/rdp_file.py @@ -12,7 +12,7 @@ # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. -# * Neither the name of Virtual Cable S.L. nor the names of its contributors +# * Neither the name of Virtual Cable S.L.U. nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # @@ -71,6 +71,7 @@ class RDPFile: enableClipboard = False customParameters: typing.Optional[str] = None enforcedShares: typing.Optional[str] = None + optimizeTeams = False def __init__( self, @@ -233,7 +234,7 @@ class RDPFile: if self.username: res += 'username:s:' + self.username + '\n' res += 'domain:s:' + self.domain + '\n' - if self.target == OsDetector.KnownOS.Windows: + if self.target == OsDetector.KnownOS.Windows and not self.optimizeTeams: res += 'password 51:b:' + password + '\n' res += 'alternate shell:s:' + '\n' diff --git a/server/src/uds/transports/RDP/scripts/windows/direct.py b/server/src/uds/transports/RDP/scripts/windows/direct.py index fb5722688..88c373782 100644 --- a/server/src/uds/transports/RDP/scripts/windows/direct.py +++ b/server/src/uds/transports/RDP/scripts/windows/direct.py @@ -1,4 +1,5 @@ -import subprocess +import os +import subprocess # nosec: B404 import win32crypt # type: ignore import codecs @@ -23,27 +24,40 @@ except Exception: ).decode() try: - key = wreg.OpenKey( - wreg.HKEY_CURRENT_USER, + key = wreg.OpenKey( # type: ignore + wreg.HKEY_CURRENT_USER, # type: ignore 'Software\\Microsoft\\Terminal Server Client\\LocalDevices', 0, - wreg.KEY_SET_VALUE, + wreg.KEY_SET_VALUE, # type: ignore ) wreg.SetValueEx(key, sp['ip'], 0, wreg.REG_DWORD, 255) # type: ignore - wreg.CloseKey(key) -except Exception as e: + wreg.CloseKey(key) # type: ignore +except Exception as e: # nosec: Not really interested in the exception # logger.warn('Exception fixing redirection dialog: %s', e) pass # Key does not exists, ok... # The password must be encoded, to be included in a .rdp file, as 'UTF-16LE' before protecting (CtrpyProtectData) it in order to work with mstsc theFile = sp['as_file'].format(password=password) # type: ignore filename = tools.saveTempFile(theFile) -executable = tools.findApp('mstsc.exe') -if executable is None: - raise Exception( - 'Unable to find mstsc.exe. Check that path points to your SYSTEM32 folder' - ) +if sp['optimize_teams'] == True: # type: ignore + try: + # Very basic check for RDP client from Microsoft Store + h = wreg.OpenKey(wreg.HKEY_CLASSES_ROOT, '.rdp\\OpenWithProgids', 0, wreg.KEY_READ) # type: ignore + h.Close() + except Exception: + raise Exception('Required Microsoft Remote Desktop Application is not found. Please, install it from Microsoft store.') + # Add .rdp to filename for open with + os.rename(filename, filename + '.rdp') + filename = filename + '.rdp' + os.startfile(filename) # type: ignore # nosec +else: + executable = tools.findApp('mstsc.exe') + if executable is None: + raise Exception( + 'Unable to find mstsc.exe. Check that path points to your SYSTEM32 folder' + ) -subprocess.Popen([executable, filename]) -tools.addFileToUnlink(filename) + subprocess.Popen([executable, filename]) # nosec + +# tools.addFileToUnlink(filename) diff --git a/server/src/uds/transports/RDP/scripts/windows/direct.py.signature b/server/src/uds/transports/RDP/scripts/windows/direct.py.signature index db8bc119a..cff0af817 100644 --- a/server/src/uds/transports/RDP/scripts/windows/direct.py.signature +++ b/server/src/uds/transports/RDP/scripts/windows/direct.py.signature @@ -1 +1 @@ -qKyGy2EIPrAzb4VsZ4fTAjMDyGb82LJXm+u04ro6IzddOyhEuPz1NleV3x8acIgPlx1K0A128voYabD78nQBfJ5Xm/TzPcwuN2qtjGtTTkc04urpsMwxVXjl4gsFAhY3G9KDqkg5Ik3wkskBDq1ahZI95uVufUejefl+r1J94g5VjhRUMVM3hctvPQFM4/6LY8VQrnGx19LGbHf4T1yUXrZMUeodReqkDBfWnJOqQOQ+9+USRxWlglgLNb/9zYbIn/Ca6qVyCsuYS1L9Gms/ioDVUd8R0jWxCCzmvHsVw9q0Lq3BZAqmFA8xonjpP+dVR53O2R/76/XY82f3vWQaL1oC5DJf5R29x6FFi9CbhRnmxfYZRjedNLYhUBeXL59SKYh83ZEqkzMmUha9j7lThVtidhk9PUPDaV8KlVJnoQwOTXrG/hfok181nvoPTt4QfADoxne4JeTWqrfDgNwLWhcpryY/yXfnUYEZChZOUqm5MF7raHsF5P3lZRazq1Zaces630pPgOfw8Zb/J2deUd0vf5BZnBgug5h6clibPude70iepv7Gt/9ks82hl7gFAYguY5AzeQFsQ9RVngmFoyQjYaAv+BSb9Z4Qbf+DB/gTCGZx7rn7YsZgD5PFaVAlRq0J6ZR3fRn88YSBliXh9HcD5CD/yRW6koXm3tTvLKo= \ No newline at end of file +YQydMk/zRSySwTUxo4uqfLzKOXIoKY8Vj8ahb2NYtd/IQgNrZgSeH9ziQ9M+wWY9XwntiGgkpZ/6nOQVUDhQUJO3+gkLnyJITpvlrgioZMHF8QLVjWN43ZY+aK5VXWwi70X/ubEy1JStGct8a1ZBe58MangeKxVGPo2a7WABo49qA6N2siEcKCrp3Z4wCBqS2a1ACAPAG5VRpnP1By3Vnv1ocEQXu264z4HB2Iikswe4n6yi8C6aTkWrmltwKEEzsAmbTUQsv43SgaXRRseqy6kX6RBEa0aG+D4Q+87WeqS3RPnlnG6SJvDaqyHMauHKfu/VVgTcTGyJuJMfGTGlgNkzRG491vpn6RtvsStxtzinZ72lgwLkaj5iaO1395BZhS/YI3KMDiLHLzcmgSPJ0aRTOM3oF/zIa4Tiy/LzRckIfB3TGHHeXguT2ugmeRM/z+yqcigW1uUKLzIv8FmIDurFj3swGBgHeg/cPbVZ5gy+NQtGFkK1BlpNnm5J/RBUNRbGZ2tn912CoZNaNj+rgKKrNNU85REx4nzq9MJGQm09s3Jk2v0NTDvDbxEy4Y6rr5GLvCvip0ede19Fi/ASG7pFZ1Tasp26IGvcHXRsR4d3wj2bNbJ97RLNjvdT1+5jb5O9kTRcOfz7B3Gbfn9/3wW9sRCbju0CludlZK+cjqo= \ No newline at end of file