diff --git a/client/src/UDSClient.py b/client/src/UDSClient.py old mode 100644 new mode 100755 index f9124a2f..65ce3e8d --- a/client/src/UDSClient.py +++ b/client/src/UDSClient.py @@ -172,7 +172,8 @@ if __name__ == "__main__": QtCore.QCoreApplication.setOrganizationName('Virtual Cable S.L.U.') QtCore.QCoreApplication.setApplicationName('UDS Connector') - app.setStyle(QtGui.QStyleFactory.create('plastique')) + if 'darwin' not in sys.platform: + app.setStyle('plastique') if six.PY3 is False: import threading diff --git a/client/src/uds/tools.py b/client/src/uds/tools.py index 3c2c1714..77472b62 100644 --- a/client/src/uds/tools.py +++ b/client/src/uds/tools.py @@ -36,6 +36,7 @@ import tempfile import string import random import os +import stat _unlinkFiles = [] _tasksToWait = [] @@ -53,6 +54,16 @@ def saveTempFile(content, filename=None): return filename +def findApp(appName): + for path in os.environ['PATH'].split(os.pathsep): + fileName = os.path.join(path, appName) + if os.path.isfile(fileName) and (os.stat(fileName).st_mode & stat.S_IXUSR) != 0: + return fileName + return None + + +# Queing operations (to be executed before exit) + def addFileToUnlink(filename): ''' Adds a file to the wait-and-unlink list diff --git a/server/src/uds/REST/methods/client.py b/server/src/uds/REST/methods/client.py index afb437e7..8e21a640 100644 --- a/server/src/uds/REST/methods/client.py +++ b/server/src/uds/REST/methods/client.py @@ -97,6 +97,9 @@ class Client(Handler): 'downloadUrl': url }) + if len(self._args) == 1: + return Client.result(_('Correct')) + try: ticket, scrambler = self._args except Exception: @@ -121,7 +124,7 @@ class Client(Handler): logger.debug('Script:\n{}'.format(transportScript)) - return Client.result(transportScript.encode('bz2').encode('base64')) + return Client.result(result=transportScript.encode('bz2').encode('base64')) except Exception as e: logger.exception("Exception") return Client.result(error=six.text_type(e)) diff --git a/server/src/uds/core/util/tools.py b/server/src/uds/core/util/tools.py new file mode 100644 index 00000000..7a4982d9 --- /dev/null +++ b/server/src/uds/core/util/tools.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- + +# +# Copyright (c) 2012 Virtual Cable S.L. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * 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 +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +''' +@author: Adolfo Gómez, dkmaster at dkmon dot com +''' +from __future__ import unicode_literals + + +class DictAsObj(object): + def __init__(self, dct=None, **kwargs): + if dct is not None: + self.__dict__.update(dct) + self.__dict__.update(kwargs) + diff --git a/server/src/uds/core/workers/AssignedAndUnused.py b/server/src/uds/core/workers/AssignedAndUnused.py index 3a5b4140..f913e117 100644 --- a/server/src/uds/core/workers/AssignedAndUnused.py +++ b/server/src/uds/core/workers/AssignedAndUnused.py @@ -69,5 +69,5 @@ class AssignedAndUnused(Job): osm.processUnused(us) else: # No os manager, simply remove unused services in specified time for us in ds.assignedUserServices().filter(in_use=False, state_date__lt=since_state, state=State.USABLE, os_state=State.USABLE): - logger.debug('Found unused assigned service {0}'.format(us)) + logger.debug('Found unused assigned service with no OS Manager {0}'.format(us)) us.remove() diff --git a/server/src/uds/static/client/.gitignore b/server/src/uds/static/client/.gitignore new file mode 100644 index 00000000..61643f7e --- /dev/null +++ b/server/src/uds/static/client/.gitignore @@ -0,0 +1,2 @@ +UDSClient.dmg +UDSClientSetup.exe diff --git a/server/src/uds/static/client/.placeholder b/server/src/uds/static/client/.placeholder new file mode 100644 index 00000000..e69de29b diff --git a/server/src/uds/templates/uds/html5/download_client.html b/server/src/uds/templates/uds/html5/download_client.html index 65225ec5..fdff0fb7 100644 --- a/server/src/uds/templates/uds/html5/download_client.html +++ b/server/src/uds/templates/uds/html5/download_client.html @@ -8,10 +8,11 @@ {% block body %}
-

{% trans 'Download UDS Plugin for' %} {{ os|osName }}

-

{% trans 'In order to be able to execute UDS services, you need to have uds plugin installed.' %}

-

{% trans 'Download UDS Plugin for' %} {{ os|osName }}

-

{% trans 'Or select another version' %}

+

{% trans 'Download UDS Plugin for' %} {{ os|osName }}

+

{% trans 'In order to be able to execute UDS services, you need to have UDS plugin installed.' %}

+

{{ os|pluginDownloadUrl|safe }}

+

{% trans 'Or download another version' %}

+

{% trans 'In case that your platform has been incorrectly detected, you can download manually the version required for your Operating System' %}

{% if os != 'linux' %}

@@ -31,15 +32,17 @@

{% if request.user %} -

{% trans 'If you already have UDS Plugin installed but this message persists to appear, you can disable it here' %}

+

{% trans 'If you already have UDS Plugin installed but this message persists to appear, you can disable automatic detection here' %}

+

{% trans "Please, note that disabling automatic detection will not trigger this page again in case you don't have the plugin installed." %}
+ {% trans "In this case, you will have to manually download the plugin by using the menu on upper right corner." %}

{% trans "Return" %}

diff --git a/server/src/uds/templatetags/html5.py b/server/src/uds/templatetags/html5.py index ff036e6b..3c82446c 100644 --- a/server/src/uds/templatetags/html5.py +++ b/server/src/uds/templatetags/html5.py @@ -33,6 +33,9 @@ from __future__ import unicode_literals from django import template +from django.utils.translation import ugettext as _ +from django.templatetags.static import static + from uds.core.util import html from uds.core.util.request import getRequest from uds.core.auths.auth import ROOT_ID @@ -213,9 +216,10 @@ def osName(os): @register.filter(name='pluginDownloadUrl') def pluginDownloadUrl(os): + tmpl = '' + _('Download UDS Plugin for') + ' {os}' if os == 'windows': - return '1' + return tmpl.format(url=static('client/UDSClientSetup.exe'), os='Windows') elif os == 'linux': return '2' else: - return '3' + return tmpl.format(url=static('client/UDSClient.dmg'), os='Mac OSX') diff --git a/server/src/uds/transports/RDP/RDPFile.py b/server/src/uds/transports/RDP/RDPFile.py index 0314ebcb..2c30319f 100644 --- a/server/src/uds/transports/RDP/RDPFile.py +++ b/server/src/uds/transports/RDP/RDPFile.py @@ -67,12 +67,61 @@ class RDPFile(object): self.target = target def get(self): - if self.target == OsDetector.Windows: - return self.getWindows() + if self.target in (OsDetector.Windows, OsDetector.Linux): + return self.getGeneric() elif self.target == OsDetector.Macintosh: return self.getMacOsX() + # Unknown target + return '' - def getWindows(self): + @property + def as_file(self): + return self.get() + + @property + def as_new_xfreerdp_params(self): + params = ['/clipboard', '/t:UDS Connection', '/cert-ignore'] + + if self.redirectSmartcards: + params.append('/smartcard') + + if self.redirectAudio: + params.append('/sound:sys:alsa') + params.append('/microphone:sys:alsa') + params.append('/multimedia:sys:alsa') + + if self.redirectDrives is True: + params.append('/drive:media,/media') + params.append('/home-drive') + + if self.redirectPrinters: + params.append('/printer') + + if self.compression: + params.append('/compression:on') + + if self.showWallpaper: + params.append('+themes') + params.append('+wallpaper') + + if self.multimon: + params.append('/multimon') + + if self.fullScreen: + params.append('/f') + else: + params.append('/w:{}'.format(self.width)) + params.append('/h:{}'.format(self.height)) + + params.append('/bpp:{}'.format(self.bpp)) + params.append('/u:{}'.format(self.username)) + params.append('/p:{}'.format(self.password)) + params.append('/d:{}'.format(self.domain)) + params.append('/v:{}'.format(self.address)) + + return params + + def getGeneric(self): password = "{password}" screenMode = self.fullScreen and "2" or "1" audioMode = self.redirectAudio and "0" or "2" @@ -105,7 +154,8 @@ class RDPFile(object): if len(self.username) != 0: res += 'username:s:' + self.username + '\n' res += 'domain:s:' + self.domain + '\n' - res += 'password 51:b:' + password + '\n' + if self.target == OsDetector.Windows: + res += 'password 51:b:' + password + '\n' res += 'alternate shell:s:' + '\n' res += 'shell working directory:s:' + '\n' diff --git a/server/src/uds/transports/RDP/RDPTransport.py b/server/src/uds/transports/RDP/RDPTransport.py index 9be6e8e4..5363b7a8 100644 --- a/server/src/uds/transports/RDP/RDPTransport.py +++ b/server/src/uds/transports/RDP/RDPTransport.py @@ -2,7 +2,7 @@ # # Copyright (c) 2012 Virtual Cable S.L. -# All rights reserved. +# All rights reservem. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -34,6 +34,7 @@ from django.utils.translation import ugettext_noop as _ from uds.core.managers.UserPrefsManager import CommonPrefs from uds.core.util import OsDetector +from uds.core.util import tools from .BaseRDPTransport import BaseRDPTransport from .RDPFile import RDPFile @@ -66,47 +67,15 @@ class RDPTransport(BaseRDPTransport): wallpaper = BaseRDPTransport.wallpaper multimon = BaseRDPTransport.multimon - def windowsScript(self, data): - r = RDPFile(data['fullScreen'], data['width'], data['height'], data['depth'], target=OsDetector.Windows) - r.address = '{}:{}'.format(data['ip'], 3389) - r.username = data['username'] - r.password = '{password}' - r.domain = data['domain'] - r.redirectPrinters = self.allowPrinters.isTrue() - r.redirectSmartcards = self.allowSmartcards.isTrue() - r.redirectDrives = self.allowDrives.isTrue() - r.redirectSerials = self.allowSerials.isTrue() - r.showWallpaper = self.wallpaper.isTrue() - r.multimon = self.multimon.isTrue() - + def windowsScript(self, m): # 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 - return self.getScript('scripts/windows/direct.py').format(os=data['os'], file=r.get(), password=data['password']) + return self.getScript('scripts/windows/direct.py').format(m=m) - def macOsXScript(self, data): - r = RDPFile(data['fullScreen'], data['width'], data['height'], data['depth'], target=OsDetector.Macintosh) - r.address = '{}:{}'.format(data['ip'], 3389) - r.username = data['username'] - r.domain = data['domain'] - r.redirectPrinters = self.allowPrinters.isTrue() - r.redirectSmartcards = self.allowSmartcards.isTrue() - r.redirectDrives = self.allowDrives.isTrue() - r.redirectSerials = self.allowSerials.isTrue() - r.showWallpaper = self.wallpaper.isTrue() - r.multimon = self.multimon.isTrue() + def macOsXScript(self, m): + return self.getScript('scripts/macosx/direct.py').format(m=m) - if data['domain'] != '': - username = '{}\\\\{}'.format(data['domain'], data['username']) - else: - username = data['username'] - - return self.getScript('scripts/macosx/direct.py').format(os=data['os'], - file=r.get(), - password=data['password'], - username=username, - ip=data['ip'], - this_server=data['this_server'], - r=r - ) + def getLinuxScript(self, m): + return self.getScript('scripts/linux/direct.py').format(m=m) def getUDSTransportScript(self, userService, transport, ip, os, user, password, request): # We use helper to keep this clean @@ -118,6 +87,18 @@ class RDPTransport(BaseRDPTransport): width, height = CommonPrefs.getWidthHeight(prefs) depth = CommonPrefs.getDepth(prefs) + r = RDPFile(width == -1 or height == -1, width, height, depth, target=os['OS']) + r.address = '{}:{}'.format(ip, 3389) + r.username = username + r.password = password + r.domain = domain + r.redirectPrinters = self.allowPrinters.isTrue() + r.redirectSmartcards = self.allowSmartcards.isTrue() + r.redirectDrives = self.allowDrives.isTrue() + r.redirectSerials = self.allowSerials.isTrue() + r.showWallpaper = self.wallpaper.isTrue() + r.multimon = self.multimon.isTrue() + # data data = { 'os': os['OS'], @@ -125,6 +106,7 @@ class RDPTransport(BaseRDPTransport): 'port': 3389, 'username': username, 'password': password, + 'hasCredentials': username != '' and password != '', 'domain': domain, 'width': width, 'height': height, @@ -137,14 +119,23 @@ class RDPTransport(BaseRDPTransport): 'wallpaper': self.wallpaper.isTrue(), 'multimon': self.multimon.isTrue(), 'fullScreen': width == -1 or height == -1, - 'this_server': request.build_absolute_uri('/') + 'this_server': request.build_absolute_uri('/'), + 'r': r, } - logger.debug('Detected os: {}'.format(data['os'])) + m = tools.DictAsObj(data) - if data['os'] == OsDetector.Windows: - return self.windowsScript(data) - elif data['os'] == OsDetector.Macintosh: - return self.macOsXScript(data) + if m.domain != '': + m.usernameWithDomain = '{}\\\\{}'.format(m.domain, m.username) + else: + m.usernameWithDomain = m.username + + if m.os == OsDetector.Windows: + m.r.password = '{password}' + return self.windowsScript(m) + if m.os == OsDetector.Macintosh: + return self.macOsXScript(m) + if m.os == OsDetector.Linux: + return self.getLinuxScript(m) return '' diff --git a/server/src/uds/transports/RDP/TSRDPTransport.py b/server/src/uds/transports/RDP/TSRDPTransport.py index 65709ab3..778a9049 100644 --- a/server/src/uds/transports/RDP/TSRDPTransport.py +++ b/server/src/uds/transports/RDP/TSRDPTransport.py @@ -38,6 +38,7 @@ from uds.core.transports.BaseTransport import Transport from uds.core.transports import protocols from uds.models import TicketStore from uds.core.util import OsDetector +from uds.core.util import tools from .BaseRDPTransport import BaseRDPTransport from .RDPFile import RDPFile @@ -84,61 +85,13 @@ class TSRDPTransport(BaseRDPTransport): if values['tunnelServer'].count(':') != 1: raise Transport.ValidationException(_('Must use HOST:PORT in Tunnel Server Field')) - def windowsScript(self, data): - r = RDPFile(data['fullScreen'], data['width'], data['height'], data['depth'], target=OsDetector.Windows) - r.address = '{address}' - r.username = data['username'] - r.password = '{password}' - r.domain = data['domain'] - r.redirectPrinters = self.allowPrinters.isTrue() - r.redirectSmartcards = self.allowSmartcards.isTrue() - r.redirectDrives = self.allowDrives.isTrue() - r.redirectSerials = self.allowSerials.isTrue() - r.showWallpaper = self.wallpaper.isTrue() - r.multimon = self.multimon.isTrue() + def windowsScript(self, m): # 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 - return self.getScript('scripts/windows/tunnel.py').format( - file=r.get(), password=data['password'], - server=data['ip'], - port=3389, - tunUser=data['tunUser'], - tunPass=data['tunPass'], - tunHost=data['tunHost'], - tunPort=data['tunPort'] - ) + return self.getScript('scripts/windows/tunnel.py').format(m=m) - def macOsXScript(self, data): - r = RDPFile(data['fullScreen'], data['width'], data['height'], data['depth'], target=OsDetector.Macintosh) - r.address = '{address}' - r.username = data['username'] - r.domain = data['domain'] - r.redirectPrinters = self.allowPrinters.isTrue() - r.redirectSmartcards = self.allowSmartcards.isTrue() - r.redirectDrives = self.allowDrives.isTrue() - r.redirectSerials = self.allowSerials.isTrue() - r.showWallpaper = self.wallpaper.isTrue() - r.multimon = self.multimon.isTrue() - - if data['domain'] != '': - username = '{}\\\\{}'.format(data['domain'], data['username']) - else: - username = data['username'] - - return self.getScript('scripts/macosx/tunnel.py').format( - os=data['os'], - file=r.get(), - password=data['password'], - username=username, - server=data['ip'], - this_server=data['this_server'], - r=r, - port=3389, - tunUser=data['tunUser'], - tunPass=data['tunPass'], - tunHost=data['tunHost'], - tunPort=data['tunPort'] - ) + def macOsXScript(self, m): + return self.getScript('scripts/macosx/tunnel.py').format(m=m) def getUDSTransportScript(self, userService, transport, ip, os, user, password, request): # We use helper to keep this clean @@ -157,6 +110,18 @@ class TSRDPTransport(BaseRDPTransport): logger.debug('Username generated: {0}, password: {1}'.format(tunuser, tunpass)) + r = RDPFile(width == -1 or height == -1, width, height, depth, target=os['OS']) + r.address = '{address}' + r.username = username + r.domain = domain + r.redirectPrinters = self.allowPrinters.isTrue() + r.redirectSmartcards = self.allowSmartcards.isTrue() + r.redirectDrives = self.allowDrives.isTrue() + r.redirectSerials = self.allowSerials.isTrue() + r.showWallpaper = self.wallpaper.isTrue() + r.multimon = self.multimon.isTrue() + + # data data = { 'os': os['OS'], @@ -167,6 +132,7 @@ class TSRDPTransport(BaseRDPTransport): 'tunPort': sshPort, 'username': username, 'password': password, + 'hasCredentials': username != '' and password != '', 'domain': domain, 'width': width, 'height': height, @@ -179,12 +145,21 @@ class TSRDPTransport(BaseRDPTransport): 'wallpaper': self.wallpaper.isTrue(), 'multimon': self.multimon.isTrue(), 'fullScreen': width == -1 or height == -1, - 'this_server': request.build_absolute_uri('/') + 'this_server': request.build_absolute_uri('/'), + 'r': r, } - if data['os'] == OsDetector.Windows: - return self.windowsScript(data) - elif data['os'] == OsDetector.Macintosh: - return self.macOsXScript(data) + m = tools.DictAsObj(data) + + if m.domain != '': + m.usernameWithDomain = '{}\\\\{}'.format(m.domain, m.username) + else: + m.usernameWithDomain = m.username + + if m.os == OsDetector.Windows: + r.password = '{password}' + return self.windowsScript(m) + if m.os == OsDetector.Macintosh: + return self.macOsXScript(m) return '' diff --git a/server/src/uds/transports/RDP/scripts/linux/direct.py b/server/src/uds/transports/RDP/scripts/linux/direct.py new file mode 100644 index 00000000..99146be7 --- /dev/null +++ b/server/src/uds/transports/RDP/scripts/linux/direct.py @@ -0,0 +1,49 @@ +# This is a template +# Saved as .py for easier editing +from __future__ import unicode_literals + +# pylint: disable=import-error, no-name-in-module, too-many-format-args, undefined-variable, invalid-sequence-index +from PyQt4 import QtCore, QtGui +import subprocess +import os +import re + +from uds import tools # @UnresolvedImport + +import six + + +def execOldXFreeRdp(parent, xfreerdp): + QtGui.QMessageBox.critical(parent, 'Notice', 'Old xfreerdp', QtGui.QMessageBox.Ok) # @UndefinedVariable + + +def execNewXFreeRdp(parent, xfreerdp): + import subprocess + params = [xfreerdp] + {m.r.as_new_xfreerdp_params} # @UndefinedVariable + tools.addTaskToWait(subprocess.Popen(params)) + + +def execRdesktop(parent, rdesktop): + return + +# Try to locate a "valid" version of xfreerdp as first option +xfreerdp = tools.findApp('xfreerdp') +if xfreerdp is not None: + # Check for nice version + try: + version = subprocess.check_output([xfreerdp, '--version']) + version = float(re.search(r'version ([0-9]*\.[0-9]*)', version).groups()[0]) + if version < 1.0: + raise Exception() + if version < 1.1: + execOldXFreeRdp(parent, xfreerdp) # @UndefinedVariable + else: + execNewXFreeRdp(parent, xfreerdp) # @UndefinedVariable + + except Exception as e: # Valid version not found, pass to check rdesktop + QtGui.QMessageBox.critical(parent, 'Notice', six.text_type(e), QtGui.QMessageBox.Ok) # @UndefinedVariable + pass +else: + rdesktop = tools.findApp('rdesktop') + if rdesktop is None: + raise Exception('You need to have installed xfreerdp or rdesktop to connect to theese UDS services.\nPlease, install apropiate package for your system.') diff --git a/server/src/uds/transports/RDP/scripts/macosx/direct.py b/server/src/uds/transports/RDP/scripts/macosx/direct.py index 4931d5ca..c6e32d6d 100644 --- a/server/src/uds/transports/RDP/scripts/macosx/direct.py +++ b/server/src/uds/transports/RDP/scripts/macosx/direct.py @@ -12,7 +12,7 @@ from uds import tools # @UnresolvedImport import six -theFile = '''{file}''' +theFile = '''{m.r.as_file}''' # First, try to locate Remote Desktop Connection (version 2, from Microsoft website, not the app store one) @@ -35,8 +35,8 @@ def onExit(): [ 'security', 'delete-generic-password', - '-a', '{username}', - '-s', 'Remote Desktop Connection 2 Password for {ip}', + '-a', '{m.usernameWithDomain}', + '-s', 'Remote Desktop Connection 2 Password for {m.ip}', ] ) @@ -52,7 +52,7 @@ if executable is None:
  • CoRD (A bit unstable from 10.7 onwards)

    -

    You can get it from this link

    +

    You can get it from this link

  • If both apps are installed, Remote Desktop Connection will be used as first option

    @@ -60,54 +60,52 @@ if executable is None: ''', QtGui.QMessageBox.Ok) elif executable == msrdc: try: - if '{username}' != '' and '{password}' != '': + if {m.hasCredentials}: # @UndefinedVariable subprocess.call( [ 'security', 'add-generic-password', - '-w', '{password}', + '-w', '{m.password}', '-U', - '-a', '{username}', - '-s', 'Remote Desktop Connection 2 Password for {ip}', + '-a', '{m.usernameWithDomain}', + '-s', 'Remote Desktop Connection 2 Password for {m.ip}', '-T', '/Applications/Remote Desktop Connection.app', ] ) + tools.addExecBeforeExit(onExit) # Call but do not wait for exit tools.addTaskToWait(subprocess.Popen([executable, filename])) - tools.addExecBeforeExit(onExit) tools.addFileToUnlink(filename) except Exception as e: QtGui.QMessageBox.critical(parent, 'Notice', six.text_type(e), QtGui.QMessageBox.Ok) # @UndefinedVariable else: # CoRD url = 'rdp://' - if '\\' in '{username}': - username, domain = '{username}'.split('\\') - else: - username, domain = '{username}', '' + + username, domain = '{m.username}', '{m.domain}' if username != '': url += username - if '{password}' != '': - url += ':' + urllib.quote('{password}') + if '{m.password}' != '': + url += ':' + urllib.quote('{m.password}') url += '@' - url += '{ip}/' + url += '{m.ip}/' if domain != '': url += domain - url += '?screenDepth={r.bpp}' + url += '?screenDepth={m.r.bpp}' - if {r.fullScreen}: # @UndefinedVariable + if {m.r.fullScreen}: # @UndefinedVariable url += '&fullscreen=true' else: - url += 'screenWidth={r.width}&screenHeight={r.height}' + url += 'screenWidth={m.r.width}&screenHeight={m.r.height}' - url += '&forwardAudio=' + '01'[{r.redirectAudio}] # @UndefinedVariable + url += '&forwardAudio=' + '01'[{m.r.redirectAudio}] # @UndefinedVariable - if {r.redirectDrives}: # @UndefinedVariable + if {m.r.redirectDrives}: # @UndefinedVariable url += '&forwardDisks=true' - if {r.redirectPrinters}: # @UndefinedVariable + if {m.r.redirectPrinters}: # @UndefinedVariable url += '&forwardPrinters=true' tools.addTaskToWait(subprocess.Popen(['open', url])) diff --git a/server/src/uds/transports/RDP/scripts/macosx/tunnel.py b/server/src/uds/transports/RDP/scripts/macosx/tunnel.py index 474eb2a3..0104cd2d 100644 --- a/server/src/uds/transports/RDP/scripts/macosx/tunnel.py +++ b/server/src/uds/transports/RDP/scripts/macosx/tunnel.py @@ -31,7 +31,7 @@ def onExit(): [ 'security', 'delete-generic-password', - '-a', '{username}', + '-a', '{m.username}', '-s', 'Remote Desktop Connection 2 Password for 127.0.0.1', ] ) @@ -48,7 +48,7 @@ if executable is None:
  • CoRD (A bit unstable from 10.7 onwards)

    -

    You can get it from this link

    +

    You can get it from this link

  • If both apps are installed, Remote Desktop Connection will be used as first option

    @@ -56,13 +56,13 @@ if executable is None: ''', QtGui.QMessageBox.Ok) -forwardThread, port = forward('{tunHost}', '{tunPort}', '{tunUser}', '{tunPass}', '{server}', '{port}') +forwardThread, port = forward('{m.tunHost}', '{m.tunPort}', '{m.tunUser}', '{m.tunPass}', '{m.ip}', 3389) if forwardThread.status == 2: QtGui.QMessageBox.critical(parent, 'Error', 'Unable to open tunnel', QtGui.QMessageBox.Ok) # @UndefinedVariable else: - theFile = '''{file}'''.format( + theFile = '''{m.r.as_file}'''.format( address='127.0.0.1:{{}}'.format(port) ) filename = tools.saveTempFile(theFile) @@ -70,54 +70,51 @@ else: if executable == msrdc: try: - if '{username}' != '' and '{password}' != '': + if {m.hasCredentials}: # @UndefinedVariable subprocess.call( [ 'security', 'add-generic-password', - '-w', '{password}', + '-w', '{m.password}', '-U', - '-a', '{username}', + '-a', '{m.username}', '-s', 'Remote Desktop Connection 2 Password for 127.0.0.1'.format(port), '-T', '/Applications/Remote Desktop Connection.app', ] ) + tools.addExecBeforeExit(onExit) # Call but do not wait for exit tools.addTaskToWait(subprocess.Popen([executable, filename])) - tools.addExecBeforeExit(onExit) tools.addFileToUnlink(filename) except Exception as e: QtGui.QMessageBox.critical(parent, 'Notice', six.text_type(e), QtGui.QMessageBox.Ok) # @UndefinedVariable else: # CoRD url = 'rdp://' - if '\\' in '{username}': - username, domain = '{username}'.split('\\') - else: - username, domain = '{username}', '' + username, domain = '{m.username}', '{m.domain}' if username != '': url += username - if '{password}' != '': - url += ':' + urllib.quote('{password}') + if '{m.password}' != '': + url += ':' + urllib.quote('{m.password}') url += '@' url += '127.0.0.1:3389/' if domain != '': url += domain - url += '?screenDepth={r.bpp}' + url += '?screenDepth={m.r.bpp}' - if {r.fullScreen}: # @UndefinedVariable + if {m.r.fullScreen}: # @UndefinedVariable url += '&fullscreen=true' else: - url += 'screenWidth={r.width}&screenHeight={r.height}' + url += 'screenWidth={m.r.width}&screenHeight={m.r.height}' - url += '&forwardAudio=' + '01'[{r.redirectAudio}] # @UndefinedVariable + url += '&forwardAudio=' + '01'[{m.r.redirectAudio}] # @UndefinedVariable - if {r.redirectDrives}: # @UndefinedVariable + if {m.r.redirectDrives}: # @UndefinedVariable url += '&forwardDisks=true' - if {r.redirectPrinters}: # @UndefinedVariable + if {m.r.redirectPrinters}: # @UndefinedVariable url += '&forwardPrinters=true' tools.addTaskToWait(subprocess.Popen(['open', url])) diff --git a/server/src/uds/transports/RDP/scripts/windows/direct.py b/server/src/uds/transports/RDP/scripts/windows/direct.py index 09fbea5a..c07e90e7 100644 --- a/server/src/uds/transports/RDP/scripts/windows/direct.py +++ b/server/src/uds/transports/RDP/scripts/windows/direct.py @@ -12,10 +12,10 @@ from uds import tools # @UnresolvedImport import six -theFile = '''{file}'''.format(password=win32crypt.CryptProtectData(six.binary_type('{password}'.encode('UTF-16LE')), None, None, None, None, 0x01).encode('hex')) +theFile = '''{m.r.as_file}'''.format(password=win32crypt.CryptProtectData(six.binary_type('{m.password}'.encode('UTF-16LE')), None, None, None, None, 0x01).encode('hex')) filename = tools.saveTempFile(theFile) -executable = os.path.join(os.path.join(os.environ['WINDIR'], 'system32'), 'mstsc.exe') +executable = tools.findApp('mstsc.exe') subprocess.call([executable, filename]) # tools.addFileToUnlink(filename) diff --git a/server/src/uds/transports/RDP/scripts/windows/tunnel.py b/server/src/uds/transports/RDP/scripts/windows/tunnel.py index 1c71c279..03cf97d1 100644 --- a/server/src/uds/transports/RDP/scripts/windows/tunnel.py +++ b/server/src/uds/transports/RDP/scripts/windows/tunnel.py @@ -14,22 +14,22 @@ from uds import tools # @UnresolvedImport import six -forwardThread, port = forward('{tunHost}', '{tunPort}', '{tunUser}', '{tunPass}', '{server}', '{port}') +forwardThread, port = forward('{m.tunHost}', '{m.tunPort}', '{m.tunUser}', '{m.tunPass}', '{m.ip}', 3389) if forwardThread.status == 2: - QtGui.QMessageBox.critical(parent, 'Error', 'Unable to open tunnel', QtGui.QMessageBox.Ok) # @UndefinedVariable + raise Exception('Unable to open file') -else: +theFile = '''{m.r.as_file}'''.format( + password=win32crypt.CryptProtectData(six.binary_type('{m.password}'.encode('UTF-16LE')), None, None, None, None, 0x01).encode('hex'), + address='127.0.0.1:{{}}'.format(port) +) - theFile = '''{file}'''.format( - password=win32crypt.CryptProtectData(six.binary_type('{password}'.encode('UTF-16LE')), None, None, None, None, 0x01).encode('hex'), - address='127.0.0.1:{{}}'.format(port) - ) +filename = tools.saveTempFile(theFile) +executable = tools.findApp('mstsc.exe') +if executable is None: + raise Exception('Unable to find mstsc.exe') - filename = tools.saveTempFile(theFile) - executable = os.path.join(os.path.join(os.environ['WINDIR'], 'system32'), 'mstsc.exe') - - subprocess.call([executable, filename]) - tools.addFileToUnlink(filename) +subprocess.call([executable, filename]) +tools.addFileToUnlink(filename) # QtGui.QMessageBox.critical(parent, 'Notice', filename + ", " + executable, QtGui.QMessageBox.Ok)