diff --git a/server/src/uds/services/PhysicalMachines/deployment.py b/server/src/uds/services/PhysicalMachines/deployment.py index 3d81fa2a..ac348943 100644 --- a/server/src/uds/services/PhysicalMachines/deployment.py +++ b/server/src/uds/services/PhysicalMachines/deployment.py @@ -85,7 +85,7 @@ class IPMachineDeployed(services.UserDeployment, AutoAttributes): # If single machine, ip is IP~counter, # If multiple and has a ';' on IP, the values is IP;MAC if ';' in self._ip: # Only try wakeup if mac is present - ip, mac = self._ip.split(';')[0:1] + ip, mac = self._ip.split('~')[0].split(';')[0:2] self.service().wakeup(ip, mac) self._state = State.FINISHED return self._state diff --git a/server/src/uds/services/PhysicalMachines/provider.py b/server/src/uds/services/PhysicalMachines/provider.py index eb66fa1f..5b37c083 100644 --- a/server/src/uds/services/PhysicalMachines/provider.py +++ b/server/src/uds/services/PhysicalMachines/provider.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # -# Copyright (c) 2012 Virtual Cable S.L. +# Copyright (c) 2012-2021 Virtual Cable S.L.U. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, @@ -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. # diff --git a/server/src/uds/services/PhysicalMachines/service_base.py b/server/src/uds/services/PhysicalMachines/service_base.py index daca703a..ebb2a861 100644 --- a/server/src/uds/services/PhysicalMachines/service_base.py +++ b/server/src/uds/services/PhysicalMachines/service_base.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # -# Copyright (c) 2019 Virtual Cable S.L. +# Copyright (c) 2019-2021 Virtual Cable S.L.U. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, @@ -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. # @@ -30,12 +30,41 @@ """ @author: Adolfo Gómez, dkmaster at dkmon dot com """ +import subprocess +import logging import typing from uds.core import services +logger = logging.getLogger(__name__) + +# We have included a "hidden testing" for adding ip+mac as static machines list. +# (This is done using IP;MAC as IP on the IP list) +# This is a test for WOL, and to be used at your risk. +# Example: +# WOLAPP = "/usr/sbin/etherwake {MAC} -i eth0 -b" +# Remember that you MUST setuid /usr/sbin/etherwake (chmod +s ....) and allow only for uds user, +# so it allows uds user to execute "privileged" etherwake program +# Note: +# {MAC} will be replaced with the MAC if it exists +# {IP} will be replaced with the IP of the machine +# If empty, no WOL will be tried NEVER, if not empty +WOLAPP = '' + + class IPServiceBase(services.Service): + @staticmethod + def getIp(ipData: str) -> str: + return ipData.split('~')[0].split(';')[0] + + @staticmethod + def getMac(ipData: str) -> typing.Optional[str]: + try: + return ipData.split('~')[0].split(';')[1] + except Exception: + return None + def getUnassignedMachine(self) -> typing.Optional[str]: raise NotADirectoryError('getUnassignedMachine') @@ -43,4 +72,11 @@ class IPServiceBase(services.Service): raise NotADirectoryError('unassignMachine') def wakeup(self, ip: str, mac: typing.Optional[str]) -> None: - pass + if WOLAPP and mac: + cmd = WOLAPP.replace('{MAC}', mac or '').replace('{IP}', ip or '') + logger.info('Launching WOL: %s', cmd) + try: + result = subprocess.run(cmd, shell=True, check=True) + # logger.debug('Result: %s', result) + except Exception as e: + logger.error('Error on WOL: %s', e) diff --git a/server/src/uds/services/PhysicalMachines/service_multi.py b/server/src/uds/services/PhysicalMachines/service_multi.py index 5377079b..065fa8d5 100644 --- a/server/src/uds/services/PhysicalMachines/service_multi.py +++ b/server/src/uds/services/PhysicalMachines/service_multi.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # -# Copyright (c) 2012 Virtual Cable S.L. +# Copyright (c) 2012-2021 Virtual Cable S.L.U. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, @@ -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,20 +54,6 @@ if typing.TYPE_CHECKING: logger = logging.getLogger(__name__) -# We have included a "hidden testing" for adding ip+mac as static machines list. -# (This is done using IP;MAC as IP on the IP list) -# This is a test for WOL, and to be used at your risk. -# Example: -# WOLAPP = "/usr/sbin/etherwake {MAC} -i eth0 -b" -# Remember that you MUST setuid /usr/sbin/etherwake (chmod +s ....) and allow only for uds user, -# so it allows uds user to execute "privileged" etherwake program -# Note: -# {MAC} will be replaced with the MAC if it exists -# {IP} will be replaced with the IP of the machine -# If empty, no WOL will be tried NEVER, if not empty -WOLAPP = '' - - class IPMachinesService(IPServiceBase): # Gui token = gui.TextField( @@ -133,27 +119,6 @@ class IPMachinesService(IPServiceBase): _port: int = 0 _skipTimeOnFailure: int = 0 - @staticmethod - def getIp(ipData: str) -> str: - return ipData.split('~')[0].split(';')[0] - - @staticmethod - def getMac(ipData: str) -> typing.Optional[str]: - try: - return ipData.split('~')[0].split(';')[1] - except Exception: - return None - - @staticmethod - def launchWOL(ip: str, mac: str) -> None: - if WOLAPP and mac: - cmd = WOLAPP.replace('{MAC}', mac) - logger.info('Launching WOL: %s', cmd) - try: - subprocess.run(cmd, shell=True) - except Exception as e: - logger.error('Error on WOL: %s', e) - def initialize(self, values: 'Module.ValuesType') -> None: if values is None: return @@ -166,7 +131,7 @@ class IPMachinesService(IPServiceBase): for i, ip in enumerate(values['ipList']) if str(ip).strip() ] # Allow duplicates right now - active = {IPMachinesService.getIp(v) for v in values['ipList']} + active = {IPServiceBase.getIp(v) for v in values['ipList']} # self._ips.sort() # Remove non existing "locked" ips from storage now skipKey = self.storage.getKey('ips') @@ -234,8 +199,8 @@ class IPMachinesService(IPServiceBase): # Search first unassigned machine try: for ip in self._ips: - theIP = IPMachinesService.getIp(ip) - theMAC = IPMachinesService.getMac(ip) + theIP = IPServiceBase.getIp(ip) + theMAC = IPServiceBase.getMac(ip) if self.storage.readData(theIP) is None: if self._port > 0 and self.cache.get('port{}'.format(theIP)): continue # The check failed not so long ago, skip it... @@ -274,10 +239,6 @@ class IPMachinesService(IPServiceBase): logger.exception("Exception at getUnassignedMachine") return None - def wakeup(self, ip: str, mac: typing.Optional[str]) -> None: - if mac: - IPMachinesService.launchWOL(ip, mac) - def unassignMachine(self, ip: str) -> None: try: if ';' in ip: @@ -302,7 +263,7 @@ class IPMachinesService(IPServiceBase): userServiceInstance: IPMachineDeployed = typing.cast( IPMachineDeployed, userDeployment ) - theIP = IPMachinesService.getIp(assignableId) + theIP = IPServiceBase.getIp(assignableId) if self.storage.readData(theIP) is None: self.storage.saveData(theIP, theIP) return userServiceInstance.assign(theIP) diff --git a/server/src/uds/services/PhysicalMachines/service_single.py b/server/src/uds/services/PhysicalMachines/service_single.py index 785358f4..e94d48b8 100644 --- a/server/src/uds/services/PhysicalMachines/service_single.py +++ b/server/src/uds/services/PhysicalMachines/service_single.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # -# Copyright (c) 2012 Virtual Cable S.L. +# Copyright (c) 2012-2021 Virtual Cable S.L.U. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, @@ -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. # diff --git a/server/src/uds/transports/RDP/rdp_file.py b/server/src/uds/transports/RDP/rdp_file.py index e5936632..29e68430 100644 --- a/server/src/uds/transports/RDP/rdp_file.py +++ b/server/src/uds/transports/RDP/rdp_file.py @@ -123,7 +123,7 @@ class RDPFile: params.append('/video') if self.redirectDrives != 'false': - if self.target == OsDetector.Linux: + if self.target in (OsDetector.Linux, OsDetector.Macintosh): params.append('/drive:home,$HOME') else: params.append('/drive:Users,/Users') diff --git a/server/src/uds/transports/RDP/scripts/macosx/direct.py b/server/src/uds/transports/RDP/scripts/macosx/direct.py index 036b4007..673442b6 100644 --- a/server/src/uds/transports/RDP/scripts/macosx/direct.py +++ b/server/src/uds/transports/RDP/scripts/macosx/direct.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals import subprocess import shutil import os +import os.path from uds import tools # type: ignore @@ -21,7 +22,7 @@ def fixResolution(): import subprocess results = str(subprocess.Popen(['system_profiler SPDisplaysDataType'],stdout=subprocess.PIPE, shell=True).communicate()[0]) res = re.search(r': \d* x \d*', results).group(0).split(' ') - width, height = str(int(res[1])-4), str(int(int(res[3])-128)) # Width and Height + width, height = str(int(res[1])-4), str(int(int(res[3])*90/100)) # Width and Height return list(map(lambda x: x.replace('#WIDTH#', width).replace('#HEIGHT#', height), sp['as_new_xfreerdp_params'])) # type: ignore # Check first xfreerdp, allow password redir @@ -77,6 +78,6 @@ elif executable == xfreerdp: except Exception as e: xfparms = list(map(lambda x: x.replace('#WIDTH#', '1400').replace('#HEIGHT#', '800'), sp['as_new_xfreerdp_params'])) # type: ignore - params = [executable] + xfparms + ['/v:{}'.format(sp['address'])] # type: ignore + params = [os.path.expandvars(i) for i in [executable] + xfparms + ['/v:{}'.format(sp['address'])]] # type: ignore subprocess.Popen(params) diff --git a/server/src/uds/transports/RDP/scripts/macosx/tunnel.py b/server/src/uds/transports/RDP/scripts/macosx/tunnel.py index d62e37d2..fe4ab8c1 100644 --- a/server/src/uds/transports/RDP/scripts/macosx/tunnel.py +++ b/server/src/uds/transports/RDP/scripts/macosx/tunnel.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals import subprocess import shutil import os +import os.path from uds.tunnel import forward # type: ignore @@ -19,7 +20,7 @@ def fixResolution(): import subprocess results = str(subprocess.Popen(['system_profiler SPDisplaysDataType'],stdout=subprocess.PIPE, shell=True).communicate()[0]) res = re.search(r': \d* x \d*', results).group(0).split(' ') - width, height = str(int(res[1])-4), str(int(int(res[3])-128)) # Width and Height + width, height = str(int(res[1])-4), str(int(int(res[3])*90/100)) # Width and Height return list(map(lambda x: x.replace('#WIDTH#', width).replace('#HEIGHT#', height), sp['as_new_xfreerdp_params'])) # type: ignore @@ -92,6 +93,6 @@ elif executable == xfreerdp: except Exception as e: xfparms = list(map(lambda x: x.replace('#WIDTH#', '1400').replace('#HEIGHT#', '800'), sp['as_new_xfreerdp_params'])) # type: ignore - params = [executable] + xfparms + ['/v:{}'.format(address)] + params = [os.path.expandvars(i) for i in [executable] + xfparms + ['/v:{}'.format(address)]] subprocess.Popen(params)