Formating and type fixing all transports

This commit is contained in:
Adolfo Gómez García 2021-08-24 11:51:56 +02:00
parent c72bcf4200
commit 3934f2b88d
29 changed files with 557 additions and 272 deletions

View File

@ -60,6 +60,7 @@ class HTML5VNCTransport(transports.Transport):
Provides access via VNC to service.
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
"""
typeName = _('HTML5 VNC Experimental')
typeType = 'HTML5VNCTransport'
typeDescription = _('VNC protocol using HTML5 client (EXPERIMENTAL)')
@ -70,10 +71,30 @@ class HTML5VNCTransport(transports.Transport):
protocol = transports.protocols.VNC
group = transports.TUNNELED_GROUP
guacamoleServer = gui.TextField(label=_('Tunnel Server'), order=1, tooltip=_('Host of the tunnel server (use http/https & port if needed) as accesible from users'), defvalue='https://', length=64, required=True, tab=gui.TUNNEL_TAB)
guacamoleServer = gui.TextField(
label=_('Tunnel Server'),
order=1,
tooltip=_(
'Host of the tunnel server (use http/https & port if needed) as accesible from users'
),
defvalue='https://',
length=64,
required=True,
tab=gui.TUNNEL_TAB,
)
username = gui.TextField(label=_('Username'), order=20, tooltip=_('Username for VNC connection authentication.'), tab=gui.PARAMETERS_TAB)
password = gui.PasswordField(label=_('Password'), order=21, tooltip=_('Password for VNC connection authentication'), tab=gui.PARAMETERS_TAB)
username = gui.TextField(
label=_('Username'),
order=20,
tooltip=_('Username for VNC connection authentication.'),
tab=gui.PARAMETERS_TAB,
)
password = gui.PasswordField(
label=_('Password'),
order=21,
tooltip=_('Password for VNC connection authentication'),
tab=gui.PARAMETERS_TAB,
)
vncPort = gui.NumericField(
length=22,
@ -82,7 +103,7 @@ class HTML5VNCTransport(transports.Transport):
order=2,
tooltip=_('Port of the VNC server.'),
required=True,
tab=gui.PARAMETERS_TAB
tab=gui.PARAMETERS_TAB,
)
colorDepth = gui.ChoiceField(
@ -98,21 +119,40 @@ class HTML5VNCTransport(transports.Transport):
gui.choiceItem('32', '33 bits'),
],
defvalue='-',
tab=gui.PARAMETERS_TAB
tab=gui.PARAMETERS_TAB,
)
swapRedBlue = gui.CheckBoxField(label=_('Swap red/blue'), order=27, tooltip=_('Use this if your colours seems incorrect (blue appears red, ..) to swap them.'), tab=gui.PARAMETERS_TAB)
cursor = gui.CheckBoxField(label=_('Remote cursor'), order=28, tooltip=_('If set, force to show remote cursor'), tab=gui.PARAMETERS_TAB)
readOnly = gui.CheckBoxField(label=_('Read only'), order=29, tooltip=_('If set, the connection will be read only'), tab=gui.PARAMETERS_TAB)
swapRedBlue = gui.CheckBoxField(
label=_('Swap red/blue'),
order=27,
tooltip=_(
'Use this if your colours seems incorrect (blue appears red, ..) to swap them.'
),
tab=gui.PARAMETERS_TAB,
)
cursor = gui.CheckBoxField(
label=_('Remote cursor'),
order=28,
tooltip=_('If set, force to show remote cursor'),
tab=gui.PARAMETERS_TAB,
)
readOnly = gui.CheckBoxField(
label=_('Read only'),
order=29,
tooltip=_('If set, the connection will be read only'),
tab=gui.PARAMETERS_TAB,
)
ticketValidity = gui.NumericField(
length=3,
label=_('Ticket Validity'),
defvalue='60',
order=90,
tooltip=_('Allowed time, in seconds, for HTML5 client to reload data from UDS Broker. The default value of 60 is recommended.'),
tooltip=_(
'Allowed time, in seconds, for HTML5 client to reload data from UDS Broker. The default value of 60 is recommended.'
),
required=True,
minValue=60,
tab=gui.ADVANCED_TAB
tab=gui.ADVANCED_TAB,
)
forceNewWindow = gui.ChoiceField(
order=91,
@ -120,12 +160,20 @@ class HTML5VNCTransport(transports.Transport):
tooltip=_('Select windows behavior for new connections on HTML5'),
required=True,
values=[
gui.choiceItem(gui.FALSE, _('Open every connection on the same window, but keeps UDS window.')),
gui.choiceItem(gui.TRUE, _('Force every connection to be opened on a new window.')),
gui.choiceItem('overwrite', _('Override UDS window and replace it with the connection.')),
gui.choiceItem(
gui.FALSE,
_('Open every connection on the same window, but keeps UDS window.'),
),
gui.choiceItem(
gui.TRUE, _('Force every connection to be opened on a new window.')
),
gui.choiceItem(
'overwrite',
_('Override UDS window and replace it with the connection.'),
),
],
defvalue=gui.FALSE,
tab=gui.ADVANCED_TAB
tab=gui.ADVANCED_TAB,
)
def initialize(self, values: 'Module.ValuesType'):
@ -134,7 +182,9 @@ class HTML5VNCTransport(transports.Transport):
# Strip spaces
self.guacamoleServer.value = self.guacamoleServer.value.strip()
if self.guacamoleServer.value[0:4] != 'http':
raise transports.Transport.ValidationException(_('The server must be http or https'))
raise transports.Transport.ValidationException(
_('The server must be http or https')
)
def isAvailableFor(self, userService: 'models.UserService', ip: str) -> bool:
"""
@ -152,15 +202,15 @@ class HTML5VNCTransport(transports.Transport):
return ready == 'Y'
def getLink( # pylint: disable=too-many-locals
self,
userService: 'models.UserService',
transport: 'models.Transport',
ip: str,
os: typing.Dict[str, str],
user: 'models.User',
password: str,
request: 'HttpRequest'
) -> str:
self,
userService: 'models.UserService',
transport: 'models.Transport',
ip: str,
os: typing.Dict[str, str],
user: 'models.User',
password: str,
request: 'HttpRequest',
) -> str:
# Build params dict
params = {
'protocol': 'vnc',
@ -200,9 +250,6 @@ class HTML5VNCTransport(transports.Transport):
return str(
"{}/guacamole/#/?data={}.{}{}".format(
self.guacamoleServer.value,
ticket,
scrambler,
onw
self.guacamoleServer.value, ticket, scrambler, onw
)
)

View File

@ -53,6 +53,7 @@ class RDPTransport(BaseRDPTransport):
Provides access via RDP to service.
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
'''
typeName = _('RDP')
typeType = 'RDPTransport'
typeDescription = _('RDP Protocol. Direct connection.')
@ -91,15 +92,15 @@ class RDPTransport(BaseRDPTransport):
customParametersMAC = BaseRDPTransport.customParametersMAC
def getUDSTransportScript( # pylint: disable=too-many-locals
self,
userService: 'models.UserService',
transport: 'models.Transport',
ip: str,
os: typing.Dict[str, str],
user: 'models.User',
password: str,
request: 'HttpRequest'
) -> typing.Tuple[str, str, typing.Mapping[str, typing.Any]]:
self,
userService: 'models.UserService',
transport: 'models.Transport',
ip: str,
os: typing.Dict[str, str],
user: 'models.User',
password: str,
request: 'HttpRequest',
) -> typing.Tuple[str, str, typing.Mapping[str, typing.Any]]:
# We use helper to keep this clean
# prefs = user.prefs('rdp')
@ -114,7 +115,9 @@ class RDPTransport(BaseRDPTransport):
width, height = self.screenSize.value.split('x')
depth = self.colorDepth.value
r = RDPFile(width == '-1' or height == '-1', width, height, depth, target=os['OS'])
r = RDPFile(
width == '-1' or height == '-1', width, height, depth, target=os['OS']
)
r.enablecredsspsupport = ci.get('sso') == 'True' or self.credssp.isTrue()
r.address = '{}:{}'.format(ip, self.rdpPort.value)
r.username = username
@ -143,13 +146,17 @@ class RDPTransport(BaseRDPTransport):
osName = {
OsDetector.Windows: 'windows',
OsDetector.Linux: 'linux',
OsDetector.Macintosh: 'macosx'
OsDetector.Macintosh: 'macosx',
}.get(os['OS'])
if osName is None:
logger.error('Os not detected for RDP Transport: %s', request.META.get('HTTP_USER_AGENT', 'Unknown'))
return super().getUDSTransportScript(userService, transport, ip, os, user, password, request)
logger.error(
'Os not detected for RDP Transport: %s',
request.META.get('HTTP_USER_AGENT', 'Unknown'),
)
return super().getUDSTransportScript(
userService, transport, ip, os, user, password, request
)
sp: typing.MutableMapping[str, typing.Any] = {
'password': password,
@ -162,21 +169,27 @@ class RDPTransport(BaseRDPTransport):
if osName == 'windows':
if password != '':
r.password = '{password}'
sp.update({
'as_file': r.as_file,
})
sp.update(
{
'as_file': r.as_file,
}
)
elif osName == 'linux':
sp.update({
'as_new_xfreerdp_params': r.as_new_xfreerdp_params,
'address': r.address,
})
sp.update(
{
'as_new_xfreerdp_params': r.as_new_xfreerdp_params,
'address': r.address,
}
)
else: # Mac
r.linuxCustomParameters = self.customParametersMAC.value
sp.update({
'as_new_xfreerdp_params': r.as_new_xfreerdp_params,
'as_rdp_url': r.as_rdp_url if self.allowMacMSRDC.isTrue() else '',
'as_file': r.as_file if self.allowMacMSRDC.isTrue() else '',
'address': r.address,
})
sp.update(
{
'as_new_xfreerdp_params': r.as_new_xfreerdp_params,
'as_rdp_url': r.as_rdp_url if self.allowMacMSRDC.isTrue() else '',
'as_file': r.as_file if self.allowMacMSRDC.isTrue() else '',
'address': r.address,
}
)
return self.getScript('scripts/{}/direct.py', osName, sp)

View File

@ -167,16 +167,16 @@ class BaseRDPTransport(transports.Transport):
tab=gui.PARAMETERS_TAB,
defvalue=gui.TRUE,
)
rdpPort = gui.NumericField(order = 29,
length = 5, # That is, max allowed value is 65535
rdpPort = gui.NumericField(
order=29,
length=5, # That is, max allowed value is 65535
label=_('RDP Port'),
tooltip=_('Use this port as RDP port. Defaults to 3389.'),
tab=gui.PARAMETERS_TAB,
required = True, #: Numeric fields have always a value, so this not really needed
defvalue = '3389',
required=True, #: Numeric fields have always a value, so this not really needed
defvalue='3389',
)
screenSize = gui.ChoiceField(
label=_('Screen Size'),
order=30,
@ -359,7 +359,7 @@ class BaseRDPTransport(transports.Transport):
if self.fixedPassword.value:
password = self.fixedPassword.value
azureAd = False
if self.fixedDomain.value != '':
if self.fixedDomain.value.lower() == 'azuread':
@ -391,7 +391,7 @@ class BaseRDPTransport(transports.Transport):
'protocol': self.protocol,
'username': username,
'password': password,
'domain': domain
'domain': domain,
}
def getConnectionInfo(
@ -408,7 +408,10 @@ class BaseRDPTransport(transports.Transport):
_, username, password = cdata # Host is unused
return self.processUserPassword(
typing.cast('models.UserService', userService), user, password, altUsername=username
typing.cast('models.UserService', userService),
user,
password,
altUsername=username,
)
def getScript(

View File

@ -39,6 +39,7 @@ import typing
from uds.core.util import os_detector as OsDetector
class RDPFile:
fullScreen = False
width = '800'
@ -71,13 +72,13 @@ class RDPFile:
enforcedShares: typing.Optional[str] = None
def __init__(
self,
fullScreen: bool,
width: typing.Union[str, int],
height: typing.Union[str, int],
bpp: str,
target: str = OsDetector.Windows
):
self,
fullScreen: bool,
width: typing.Union[str, int],
height: typing.Union[str, int],
bpp: str,
target: str = OsDetector.Windows,
):
self.width = str(width)
self.height = str(height)
self.bpp = str(bpp)
@ -95,7 +96,9 @@ class RDPFile:
return self.get()
@property
def as_new_xfreerdp_params(self): # pylint: disable=too-many-statements,too-many-branches
def as_new_xfreerdp_params(
self,
): # pylint: disable=too-many-statements,too-many-branches
"""
Parameters for xfreerdp >= 1.1.0 with self rdp description
Note that server is not added
@ -188,7 +191,7 @@ class RDPFile:
def getGeneric(self): # pylint: disable=too-many-statements
password = '{password}'
screenMode = '2' if self.fullScreen else '1'
audioMode = '0' if self.redirectAudio else '2'
audioMode = '0' if self.redirectAudio else '2'
serials = '1' if self.redirectSerials else '0'
scards = '1' if self.redirectSmartcards else '0'
printers = '1' if self.redirectPrinters else '0'
@ -250,7 +253,11 @@ class RDPFile:
if self.redirectWebcam:
res += 'camerastoredirect:s:*\n'
enforcedSharesStr = ';'.join(self.enforcedShares.replace(' ', '').upper().split(',')) + ';' if self.enforcedShares else ''
enforcedSharesStr = (
';'.join(self.enforcedShares.replace(' ', '').upper().split(',')) + ';'
if self.enforcedShares
else ''
)
if self.redirectDrives != 'false':
if self.redirectDrives == 'true':
@ -259,7 +266,9 @@ class RDPFile:
res += 'drivestoredirect:s:{}DynamicDrives\n'.format(enforcedSharesStr)
res += 'devicestoredirect:s:*\n'
res += 'enablecredsspsupport:i:{}\n'.format(0 if self.enablecredsspsupport is False else 1)
res += 'enablecredsspsupport:i:{}\n'.format(
0 if self.enablecredsspsupport is False else 1
)
# DirectX?
res += 'redirectdirectx:i:1\n'
@ -273,12 +282,11 @@ class RDPFile:
def as_rdp_url(self) -> str:
# Some parameters
screenMode = '2' if self.fullScreen else '1'
audioMode = '0' if self.redirectAudio else '2'
audioMode = '0' if self.redirectAudio else '2'
useMultimon = '1' if self.multimon else '0'
disableWallpaper = '0' if self.showWallpaper else '1'
printers = '1' if self.redirectPrinters else '0'
credsspsupport = '1' if self.enablecredsspsupport else '0'
parameters = [
('full address', f's:{self.address}'),
@ -295,7 +303,7 @@ class RDPFile:
('disable full window drag', 'i:1'),
('authentication level', f'i:0'),
# Not listed, but maybe usable?
('enablecredsspsupport', f'i:{credsspsupport}')
('enablecredsspsupport', f'i:{credsspsupport}'),
]
if self.username:
parameters.append(('username', f's:{urllib.parse.quote(self.username)}'))
@ -311,5 +319,6 @@ class RDPFile:
if self.redirectDrives != 'false': # Only "all drives" is supported
parameters.append(('drivestoredirect', 's:*'))
return 'rdp://' + '&'.join((urllib.parse.quote(i[0]) + '=' + i[1] for i in parameters))
return 'rdp://' + '&'.join(
(urllib.parse.quote(i[0]) + '=' + i[1] for i in parameters)
)

View File

@ -1,17 +1,15 @@
# This is a template
# Saved as .py for easier editing
from __future__ import unicode_literals
import subprocess
import subprocess # noqa
from uds import tools # type: ignore
# Inject local passed sp into globals for inner functions
globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable
def execUdsRdp(udsrdp):
import subprocess # @Reimport
import os.path
params = [os.path.expandvars(i) for i in [udsrdp] + sp['as_new_xfreerdp_params'] + ['/v:{}'.format(sp['address'])]] # type: ignore
tools.addTaskToWait(subprocess.Popen(params))
@ -19,9 +17,11 @@ def execUdsRdp(udsrdp):
def execNewXFreeRdp(xfreerdp):
import subprocess # @Reimport
import os.path
params = [os.path.expandvars(i) for i in [xfreerdp] + sp['as_new_xfreerdp_params'] + ['/v:{}'.format(sp['address'])]] # type: ignore
tools.addTaskToWait(subprocess.Popen(params))
# Try to locate a "valid" version of xfreerdp as first option (<1.1 does not allows drive redirections, so it will not be used if found)
xfreerdp = tools.findApp('xfreerdp')
udsrdp = tools.findApp('udsrdp')
@ -34,9 +34,11 @@ if udsrdp is not None:
fnc, app = execUdsRdp, udsrdp
if app is None or fnc is None:
raise Exception('''<p>You need to have installed xfreerdp (>= 1.1) or rdesktop, and have them in your PATH in order to connect to this UDS service.</p>
raise Exception(
'''<p>You need to have installed xfreerdp (>= 1.1) or rdesktop, and have them in your PATH in order to connect to this UDS service.</p>
<p>Please, install the proper package for your system.</p>
<p>Also note that xfreerdp prior to version 1.1 will not be taken into consideration.</p>
''')
'''
)
else:
fnc(app) # @UndefinedVariable

View File

@ -1,8 +1,5 @@
# This is a template
# Saved as .py for easier editing
from __future__ import unicode_literals
import subprocess # noqa
import subprocess
from uds.tunnel import forward # type: ignore
from uds import tools # type: ignore
@ -10,9 +7,11 @@ from uds import tools # type: ignore
# Inject local passed sp into globals for functions
globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable
def execUdsRdp(udsrdp, port):
import subprocess # @Reimport
import os.path
params = [os.path.expandvars(i) for i in [udsrdp] + sp['as_new_xfreerdp_params'] + ['/v:127.0.0.1:{}'.format(port)]] # type: ignore
tools.addTaskToWait(subprocess.Popen(params))
@ -20,9 +19,11 @@ def execUdsRdp(udsrdp, port):
def execNewXFreeRdp(xfreerdp, port):
import subprocess # @Reimport
import os.path
params = [os.path.expandvars(i) for i in [xfreerdp] + sp['as_new_xfreerdp_params'] + ['/v:127.0.0.1:{}'.format(port)]] # type: ignore
tools.addTaskToWait(subprocess.Popen(params))
# Try to locate a "valid" version of xfreerdp as first option (<1.1 does not allows drive redirections, so it will not be used if found)
xfreerdp = tools.findApp('xfreerdp')
udsrdp = tools.findApp('udsrdp')
@ -35,16 +36,20 @@ if udsrdp:
fnc, app = execUdsRdp, udsrdp
if app is None or fnc is None:
raise Exception('''<p>You need to have installed xfreerdp (>= 1.1) or rdesktop, and have them in your PATH in order to connect to this UDS service.</p>
raise Exception(
'''<p>You need to have installed xfreerdp (>= 1.1) or rdesktop, and have them in your PATH in order to connect to this UDS service.</p>
<p>Please, install apropiate package for your system.</p>
<p>Also note that xfreerdp prior to version 1.1 will not be taken into consideration.</p>
''')
'''
)
else:
# Open tunnel
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) # type: ignore
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) # type: ignore
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
raise Exception(
'<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>'
)
fnc(app, fs.server_address[1])

View File

@ -1,7 +1,3 @@
# 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
import subprocess
import shutil
@ -13,21 +9,32 @@ from uds import tools # type: ignore
# Inject local passed sp into globals for functions
globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable
msrdc = '/Applications/Microsoft Remote Desktop.app/Contents/MacOS/Microsoft Remote Desktop'
msrdc = (
'/Applications/Microsoft Remote Desktop.app/Contents/MacOS/Microsoft Remote Desktop'
)
xfreerdp = tools.findApp('xfreerdp')
executable = None
def fixResolution():
import re
import subprocess
results = str(subprocess.Popen(['system_profiler SPDisplaysDataType'],stdout=subprocess.PIPE, shell=True).communicate()[0])
results = str(
subprocess.Popen(
['system_profiler SPDisplaysDataType'], stdout=subprocess.PIPE, shell=True
).communicate()[0]
)
groups = re.search(r': \d* x \d*', results)
width, height = '1024', '768' # Safe default values
if groups:
res = groups.group(0).split(' ')
width, height = str(int(res[1])-4), str(int(int(res[3])*90/100)) # 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
if xfreerdp and os.path.isfile(xfreerdp):
executable = xfreerdp
@ -36,7 +43,8 @@ elif msrdc and os.path.isfile(msrdc) and sp['as_file']: # type: ignore
if executable is None:
if sp['as_file']: # type: ignore
raise Exception('''<p><b>Microsoft Remote Desktop or xfreerdp not found</b></p>
raise Exception(
'''<p><b>Microsoft Remote Desktop or xfreerdp not found</b></p>
<p>In order to connect to UDS RDP Sessions, you need to have a<p>
<ul>
<li>
@ -46,9 +54,11 @@ if executable is None:
<p><b>Xfreerdp</b> from homebrew</p>
</li>
</ul>
''')
'''
)
else:
raise Exception('''<p><b>xfreerdp not found</b></p>
raise Exception(
'''<p><b>xfreerdp not found</b></p>
<p>In order to connect to UDS RDP Sessions, you need to have a<p>
<ul>
<li>
@ -65,16 +75,26 @@ if executable is None:
</p>
</li>
</ul>
''')
'''
)
elif executable == msrdc:
theFile = sp['as_file'] # type: ignore
filename = tools.saveTempFile(theFile)
# Rename as .rdp, so open recognizes it
shutil.move(filename, filename + '.rdp')
#tools.addTaskToWait(subprocess.Popen(['open', filename + '.rdp']))
# tools.addTaskToWait(subprocess.Popen(['open', filename + '.rdp']))
# Force MSRDP to be used with -a (thanks to Dani Torregrosa @danitorregrosa (https://github.com/danitorregrosa) )
tools.addTaskToWait(subprocess.Popen(['open', '-a', '/Applications/Microsoft Remote Desktop.app', filename + '.rdp']))
tools.addTaskToWait(
subprocess.Popen(
[
'open',
'-a',
'/Applications/Microsoft Remote Desktop.app',
filename + '.rdp',
]
)
)
tools.addFileToUnlink(filename + '.rdp')
elif executable == xfreerdp:
# Fix resolution...
@ -85,4 +105,3 @@ elif executable == xfreerdp:
params = [os.path.expandvars(i) for i in [executable] + xfparms + ['/v:{}'.format(sp['address'])]] # type: ignore
subprocess.Popen(params)

View File

@ -15,19 +15,29 @@ from uds import tools # type: ignore
# Inject local passed sp into globals for functions
globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable
def fixResolution():
import re
import subprocess
results = str(subprocess.Popen(['system_profiler SPDisplaysDataType'],stdout=subprocess.PIPE, shell=True).communicate()[0])
results = str(
subprocess.Popen(
['system_profiler SPDisplaysDataType'], stdout=subprocess.PIPE, shell=True
).communicate()[0]
)
groups = re.search(r': \d* x \d*', results)
width, height = '1024', '768' # Safe default values
if groups:
res = groups.group(0).split(' ')
width, height = str(int(res[1])-4), str(int(int(res[3])*90/100)) # 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
msrdc = '/Applications/Microsoft Remote Desktop.app/Contents/MacOS/Microsoft Remote Desktop'
msrdc = (
'/Applications/Microsoft Remote Desktop.app/Contents/MacOS/Microsoft Remote Desktop'
)
xfreerdp = tools.findApp('xfreerdp')
executable = None
@ -39,7 +49,8 @@ elif msrdc and os.path.isfile(msrdc) and sp['as_file']: # type: ignore
if executable is None:
if sp['as_rdp_url']: # type: ignore
raise Exception('''<p><b>Microsoft Remote Desktop or xfreerdp not found</b></p>
raise Exception(
'''<p><b>Microsoft Remote Desktop or xfreerdp not found</b></p>
<p>In order to connect to UDS RDP Sessions, you need to have a<p>
<ul>
<li>
@ -49,9 +60,11 @@ if executable is None:
<p><b>Xfreerdp</b> from homebrew</p>
</li>
</ul>
''')
'''
)
else:
raise Exception('''<p><b>xfreerdp not found</b></p>
raise Exception(
'''<p><b>xfreerdp not found</b></p>
<p>In order to connect to UDS RDP Sessions, you need to have a<p>
<ul>
<li>
@ -68,7 +81,8 @@ if executable is None:
</p>
</li>
</ul>
''')
'''
)
# Open tunnel
fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], timeout=sp['tunWait'], check_certificate=sp['tunChk']) # type: ignore
@ -76,12 +90,12 @@ address = '127.0.0.1:{}'.format(fs.server_address[1])
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
raise Exception(
'<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>'
)
if executable == msrdc:
theFile = theFile = sp['as_file'].format( # type: ignore
address=address
)
theFile = theFile = sp['as_file'].format(address=address) # type: ignore
filename = tools.saveTempFile(theFile)
# Rename as .rdp, so open recognizes it
@ -89,7 +103,16 @@ if executable == msrdc:
# tools.addTaskToWait(subprocess.Popen(['open', filename + '.rdp']))
# Force MSRDP to be used with -a (thanks to Dani Torregrosa @danitorregrosa (https://github.com/danitorregrosa) )
tools.addTaskToWait(subprocess.Popen(['open', '-a', '/Applications/Microsoft Remote Desktop.app', filename + '.rdp']))
tools.addTaskToWait(
subprocess.Popen(
[
'open',
'-a',
'/Applications/Microsoft Remote Desktop.app',
filename + '.rdp',
]
)
)
tools.addFileToUnlink(filename + '.rdp')
elif executable == xfreerdp:
# Fix resolution...
@ -98,6 +121,8 @@ 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 = [os.path.expandvars(i) for i in [executable] + xfparms + ['/v:{}'.format(address)]]
params = [
os.path.expandvars(i)
for i in [executable] + xfparms + ['/v:{}'.format(address)]
]
subprocess.Popen(params)

View File

@ -13,13 +13,22 @@ from uds import tools # type: ignore
thePass = sp['password'].encode('UTF-16LE') # type: ignore
try:
password = codecs.encode(win32crypt.CryptProtectData(thePass, None, None, None, None, 0x01), 'hex').decode()
password = codecs.encode(
win32crypt.CryptProtectData(thePass, None, None, None, None, 0x01), 'hex'
).decode()
except Exception:
# logger.info('Cannot encrypt for user, trying for machine')
password = codecs.encode(win32crypt.CryptProtectData(thePass, None, None, None, None, 0x05), 'hex').decode()
password = codecs.encode(
win32crypt.CryptProtectData(thePass, None, None, None, None, 0x05), 'hex'
).decode()
try:
key = wreg.OpenKey(wreg.HKEY_CURRENT_USER, 'Software\\Microsoft\\Terminal Server Client\\LocalDevices', 0, wreg.KEY_SET_VALUE)
key = wreg.OpenKey(
wreg.HKEY_CURRENT_USER,
'Software\\Microsoft\\Terminal Server Client\\LocalDevices',
0,
wreg.KEY_SET_VALUE,
)
wreg.SetValueEx(key, sp['ip'], 0, wreg.REG_DWORD, 255) # type: ignore
wreg.CloseKey(key)
except Exception as e:
@ -27,15 +36,14 @@ except Exception as 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( # type: ignore
password=password
)
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')
raise Exception(
'Unable to find mstsc.exe. Check that path points to your SYSTEM32 folder'
)
subprocess.Popen([executable, filename])
tools.addFileToUnlink(filename)

View File

@ -16,29 +16,41 @@ fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], ti
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
raise Exception(
'<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>'
)
thePass = sp['password'].encode('UTF-16LE') # type: ignore
try:
password = codecs.encode(win32crypt.CryptProtectData(thePass, None, None, None, None, 0x01), 'hex').decode()
password = codecs.encode(
win32crypt.CryptProtectData(thePass, None, None, None, None, 0x01), 'hex'
).decode()
except Exception:
# Cannot encrypt for user, trying for machine
password = codecs.encode(win32crypt.CryptProtectData(thePass, None, None, None, None, 0x05), 'hex').decode()
password = codecs.encode(
win32crypt.CryptProtectData(thePass, None, None, None, None, 0x05), 'hex'
).decode()
# 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( # type: ignore
password=password,
address='127.0.0.1:{}'.format(fs.server_address[1])
password=password, address='127.0.0.1:{}'.format(fs.server_address[1])
)
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')
raise Exception(
'Unable to find mstsc.exe. Check that path points to your SYSTEM32 folder'
)
try:
key = wreg.OpenKey(wreg.HKEY_CURRENT_USER, 'Software\\Microsoft\\Terminal Server Client\\LocalDevices', 0, wreg.KEY_SET_VALUE)
key = wreg.OpenKey(
wreg.HKEY_CURRENT_USER,
'Software\\Microsoft\\Terminal Server Client\\LocalDevices',
0,
wreg.KEY_SET_VALUE,
)
wreg.SetValueEx(key, '127.0.0.1', 0, wreg.REG_DWORD, 255) # type: ignore
wreg.CloseKey(key)
except Exception as e:

View File

@ -67,15 +67,15 @@ class RemoteViewerFile:
delete_file: bool = True
def __init__(
self,
host: str,
port: str,
tls_port: str,
password: str,
ca: str,
host_subject: str,
fullscreen: bool = False
):
self,
host: str,
port: str,
tls_port: str,
password: str,
ca: str,
host_subject: str,
fullscreen: bool = False,
):
self.host = host
self.port = port
self.tls_port = tls_port
@ -102,7 +102,9 @@ class RemoteViewerFile:
usb_auto_share = '01'[self.usb_auto_share]
new_usb_auto_share = '01'[self.new_usb_auto_share]
ca = self.ca.strip().replace('\n', '\\n') # So we get '\\n' and script works fine after replacement
ca = self.ca.strip().replace(
'\n', '\\n'
) # So we get '\\n' and script works fine after replacement
return TEMPLATE.format(
type=self.connectionType,
@ -118,5 +120,7 @@ class RemoteViewerFile:
delete_file=delete_file,
host_subject=self.host_subject if tls_port != '-1' else '',
ca=ca if tls_port != '-1' else '',
secure_channel='secure-channels=main;inputs;cursor;playback;record;display;usbredir;smartcard' if tls_port != '-1' else ''
secure_channel='secure-channels=main;inputs;cursor;playback;record;display;usbredir;smartcard'
if tls_port != '-1'
else '',
)

View File

@ -10,11 +10,13 @@ from uds import tools # type: ignore
executable = tools.findApp('remote-viewer')
if executable is None:
raise Exception('''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
raise Exception(
'''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
<p>
Please, install appropriate package for your Linux system. (probably named something like <b>remote-viewer</b>)
</p>
''')
'''
)
theFile = sp['as_file'] # type: ignore

View File

@ -11,14 +11,16 @@ from uds.tunnel import forward # type: ignore
executable = tools.findApp('remote-viewer')
if executable is None:
raise Exception('''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
raise Exception(
'''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
<p>
Please, install appropriate package for your system.
</p>
<p>
Please, install appropriate package for your Linux system. (probably named something like <b>virt-viewer</b>)
</p>
''')
'''
)
theFile = sp['as_file_ns'] # type: ignore
@ -29,7 +31,9 @@ if sp['ticket']: # type: ignore
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
raise Exception(
'<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>'
)
fss = None
if sp['ticket_secure']: # type: ignore
@ -38,11 +42,13 @@ if sp['ticket_secure']: # type: ignore
# Check that tunnel works..
if fss.check() is False:
raise Exception('<p>Could not connect to tunnel server 2.</p><p>Please, check your network settings.</p>')
raise Exception(
'<p>Could not connect to tunnel server 2.</p><p>Please, check your network settings.</p>'
)
theFile = theFile.format(
secure_port='-1' if not fss else fss.server_address[1],
port='-1' if not fs else fs.server_address[1]
port='-1' if not fs else fs.server_address[1],
)
filename = tools.saveTempFile(theFile)

View File

@ -11,7 +11,8 @@ from uds import tools # type: ignore
remoteViewer = '/Applications/RemoteViewer.app/Contents/MacOS/RemoteViewer'
if not os.path.isfile(remoteViewer):
raise Exception('''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
raise Exception(
'''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
<p>
Please, install appropriate package for your system.
</p>
@ -22,7 +23,8 @@ if not os.path.isfile(remoteViewer):
Please, note that in order to UDS Connector to work correctly, you must copy the Remote Viewer app to your Applications Folder.<br/>
Also remember, that in order to allow this app to run on your system, you must open it one time once it is copied to your App folder
</p>
''')
'''
)
theFile = sp['as_file'] # type: ignore

View File

@ -12,7 +12,8 @@ from uds.tunnel import forward # type: ignore
remoteViewer = '/Applications/RemoteViewer.app/Contents/MacOS/RemoteViewer'
if not os.path.isfile(remoteViewer):
raise Exception('''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
raise Exception(
'''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
<p>
Please, install appropriate package for your system.
</p>
@ -23,7 +24,8 @@ if not os.path.isfile(remoteViewer):
Please, note that in order to UDS Connector to work correctly, you must copy the Remote Viewer app to your Applications Folder.<br/>
Also remember, that in order to allow this app to run on your system, you must open it one time once it is copied to your App folder
</p>
''')
'''
)
theFile = sp['as_file_ns'] # type: ignore
fs = None
@ -33,7 +35,9 @@ if sp['ticket']: # type: ignore
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
raise Exception(
'<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>'
)
fss = None
if sp['ticket_secure']: # type: ignore
@ -42,11 +46,13 @@ if sp['ticket_secure']: # type: ignore
# Check that tunnel works..
if fss.check() is False:
raise Exception('<p>Could not connect to tunnel server 2.</p><p>Please, check your network settings.</p>')
raise Exception(
'<p>Could not connect to tunnel server 2.</p><p>Please, check your network settings.</p>'
)
theFile = theFile.format(
secure_port='-1' if not fss else fss.server_address[1],
port='-1' if not fs else fs.server_address[1]
port='-1' if not fs else fs.server_address[1],
)
filename = tools.saveTempFile(theFile)

View File

@ -19,14 +19,16 @@ for env in ('PROGRAMFILES', 'PROGRAMW6432'):
executable = tools.findApp('remote-viewer.exe', extraPaths)
if executable is None:
raise Exception('''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
raise Exception(
'''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
<p>
Please, install appropriate package for your system.
</p>
<p>
<a href="http://virt-manager.org/download/">Open download page</a>
</p>
''')
'''
)
theFile = sp['as_file'] # type: ignore

View File

@ -20,14 +20,16 @@ for env in ('PROGRAMFILES', 'PROGRAMW6432'):
executable = tools.findApp('remote-viewer.exe', extraPaths)
if executable is None:
raise Exception('''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
raise Exception(
'''<p>You need to have installed virt-viewer to connect to this UDS service.</p>
<p>
Please, install appropriate package for your system.
</p>
<p>
<a href="http://virt-manager.org/download/">Open download page</a>
</p>
''')
'''
)
theFile = sp['as_file_ns'] # type: ignore
fs = None
if sp['ticket']: # type: ignore
@ -36,7 +38,9 @@ if sp['ticket']: # type: ignore
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
raise Exception(
'<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>'
)
fss = None
if sp['ticket_secure']: # type: ignore
@ -45,11 +49,13 @@ if sp['ticket_secure']: # type: ignore
# Check that tunnel works..
if fss.check() is False:
raise Exception('<p>Could not connect to tunnel server 2.</p><p>Please, check your network settings.</p>')
raise Exception(
'<p>Could not connect to tunnel server 2.</p><p>Please, check your network settings.</p>'
)
theFile = theFile.format(
secure_port='-1' if not fss else fss.server_address[1],
port='-1' if not fs else fs.server_address[1]
port='-1' if not fs else fs.server_address[1],
)
filename = tools.saveTempFile(theFile)

View File

@ -51,6 +51,7 @@ class SPICETransport(BaseSpiceTransport):
Provides access via SPICE to service.
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
"""
typeName = _('SPICE')
typeType = 'SPICETransport'
typeDescription = _('SPICE Protocol. Direct connection.')
@ -65,15 +66,15 @@ class SPICETransport(BaseSpiceTransport):
smartCardRedirect = BaseSpiceTransport.smartCardRedirect
def getUDSTransportScript( # pylint: disable=too-many-locals
self,
userService: 'models.UserService',
transport: 'models.Transport',
ip: str,
os: typing.Dict[str, str],
user: 'models.User',
password: str,
request: 'HttpRequest'
) -> typing.Tuple[str, str, typing.Mapping[str, typing.Any]]:
self,
userService: 'models.UserService',
transport: 'models.Transport',
ip: str,
os: typing.Dict[str, str],
user: 'models.User',
password: str,
request: 'HttpRequest',
) -> typing.Tuple[str, str, typing.Mapping[str, typing.Any]]:
userServiceInstance: typing.Any = userService.getInstance()
con = userServiceInstance.getConsoleConnection()
@ -85,7 +86,15 @@ class SPICETransport(BaseSpiceTransport):
port: str = con['port'] or '-1'
secure_port: str = con['secure_port'] or '-1'
r = RemoteViewerFile(con['address'], port, secure_port, con['ticket']['value'], self.serverCertificate.value, con['cert_subject'], fullscreen=self.fullScreen.isTrue())
r = RemoteViewerFile(
con['address'],
port,
secure_port,
con['ticket']['value'],
self.serverCertificate.value,
con['cert_subject'],
fullscreen=self.fullScreen.isTrue(),
)
r.usb_auto_share = self.usbShare.isTrue()
r.new_usb_auto_share = self.autoNewUsbShare.isTrue()
r.smartcard = self.smartCardRedirect.isTrue()
@ -93,11 +102,13 @@ class SPICETransport(BaseSpiceTransport):
osName = {
OsDetector.Windows: 'windows',
OsDetector.Linux: 'linux',
OsDetector.Macintosh: 'macosx'
OsDetector.Macintosh: 'macosx',
}.get(os['OS'])
if osName is None:
return super().getUDSTransportScript(userService, transport, ip, os, user, password, request)
return super().getUDSTransportScript(
userService, transport, ip, os, user, password, request
)
# if sso: # If SSO requested, and when supported by platform
# userServiceInstance.desktopLogin(user, password, '')

View File

@ -54,6 +54,7 @@ class BaseSpiceTransport(transports.Transport):
Provides access via SPICE to service.
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
"""
iconFile = 'spice.png'
protocol = protocols.SPICE
@ -61,54 +62,56 @@ class BaseSpiceTransport(transports.Transport):
order=1,
label=_('Empty credentials'),
tooltip=_('If checked, the credentials used to connect will be emtpy'),
tab=gui.CREDENTIALS_TAB
tab=gui.CREDENTIALS_TAB,
)
fixedName = gui.TextField(
order=2,
label=_('Username'),
tooltip=_('If not empty, this username will be always used as credential'),
tab=gui.CREDENTIALS_TAB
tab=gui.CREDENTIALS_TAB,
)
fixedPassword = gui.PasswordField(
order=3,
label=_('Password'),
tooltip=_('If not empty, this password will be always used as credential'),
tab=gui.CREDENTIALS_TAB
tab=gui.CREDENTIALS_TAB,
)
serverCertificate = gui.TextField(
order=4,
length=4096,
multiline=4,
label=_('Certificate'),
tooltip=_('Server certificate (public), can be found on your ovirt engine, probably at /etc/pki/ovirt-engine/certs/ca.der (Use the contents of this file).'),
required=False
tooltip=_(
'Server certificate (public), can be found on your ovirt engine, probably at /etc/pki/ovirt-engine/certs/ca.der (Use the contents of this file).'
),
required=False,
)
fullScreen = gui.CheckBoxField(
order=5,
label=_('Fullscreen Mode'),
tooltip=_('If checked, viewer will be shown on fullscreen mode-'),
tab=gui.ADVANCED_TAB
tab=gui.ADVANCED_TAB,
)
smartCardRedirect = gui.CheckBoxField(
order=6,
label=_('Smartcard Redirect'),
tooltip=_('If checked, SPICE protocol will allow smartcard redirection.'),
defvalue=gui.FALSE,
tab=gui.ADVANCED_TAB
tab=gui.ADVANCED_TAB,
)
usbShare = gui.CheckBoxField(
order=7,
label=_('Enable USB'),
tooltip=_('If checked, USB redirection will be allowed.'),
defvalue=gui.FALSE,
tab=gui.ADVANCED_TAB
tab=gui.ADVANCED_TAB,
)
autoNewUsbShare = gui.CheckBoxField(
order=8,
label=_('New USB Auto Sharing'),
tooltip=_('Auto-redirect USB devices when plugged in.'),
defvalue=gui.FALSE,
tab=gui.ADVANCED_TAB
tab=gui.ADVANCED_TAB,
)
def isAvailableFor(self, userService: 'models.UserService', ip: str) -> bool:
@ -117,7 +120,9 @@ class BaseSpiceTransport(transports.Transport):
"""
ready = self.cache.get(ip)
if ready is None:
userServiceInstance: typing.Any = userService.getInstance() # Disable mypy checks on this
userServiceInstance: typing.Any = (
userService.getInstance()
) # Disable mypy checks on this
con = userServiceInstance.getConsoleConnection()
logger.debug('Connection data: %s', con)
@ -130,13 +135,19 @@ class BaseSpiceTransport(transports.Transport):
# test ANY of the ports
port_to_test = port if port != -1 else secure_port
if port_to_test == -1:
self.cache.put('cachedMsg', 'Could not find the PORT for connection', 120) # Write a message, that will be used from getCustom
self.cache.put(
'cachedMsg', 'Could not find the PORT for connection', 120
) # Write a message, that will be used from getCustom
logger.info('SPICE didn\'t find has any port: %s', con)
return False
self.cache.put('cachedMsg',
'Could not reach server "{}" on port "{}" from broker (prob. causes are name resolution & firewall rules)'.format(con['address'], port_to_test),
120)
self.cache.put(
'cachedMsg',
'Could not reach server "{}" on port "{}" from broker (prob. causes are name resolution & firewall rules)'.format(
con['address'], port_to_test
),
120,
)
if self.testServer(userService, con['address'], port_to_test) is True:
self.cache.put(ip, 'Y', READY_CACHE_TIMEOUT)
@ -144,17 +155,25 @@ class BaseSpiceTransport(transports.Transport):
return ready == 'Y'
def getCustomAvailableErrorMsg(self, userService: 'models.UserService', ip: str) -> str:
def getCustomAvailableErrorMsg(
self, userService: 'models.UserService', ip: str
) -> str:
msg = self.cache.get('cachedMsg')
if msg is None:
return transports.Transport.getCustomAvailableErrorMsg(self, userService, ip)
return transports.Transport.getCustomAvailableErrorMsg(
self, userService, ip
)
return msg
def processedUser(self, userService: 'models.UserService', user: 'models.User') -> str:
def processedUser(
self, userService: 'models.UserService', user: 'models.User'
) -> str:
v = self.processUserPassword(userService, user, '')
return v['username']
def processUserPassword(self, userService: 'models.UserService', user: 'models.User', password: str) -> typing.Dict[str, str]:
def processUserPassword(
self, userService: typing.Union['models.UserService', 'models.ServicePool'], user: 'models.User', password: str
) -> typing.Dict[str, str]:
username = user.getUsernameForAuth()
if self.fixedName.value:
@ -172,19 +191,23 @@ class BaseSpiceTransport(transports.Transport):
return {'protocol': self.protocol, 'username': username, 'password': password}
def getConnectionInfo(
self,
userService: typing.Union['models.UserService', 'models.ServicePool'],
user: 'models.User',
password: str
) -> typing.Dict[str, str]:
self,
userService: typing.Union['models.UserService', 'models.ServicePool'],
user: 'models.User',
password: str,
) -> typing.Dict[str, str]:
return self.processUserPassword(userService, user, password)
def getScript(self, scriptNameTemplate: str, osName: str, params: typing.Dict[str, typing.Any]) -> typing.Tuple[str, str, typing.Dict[str, typing.Any]]:
def getScript(
self, scriptNameTemplate: str, osName: str, params: typing.Dict[str, typing.Any]
) -> typing.Tuple[str, str, typing.Dict[str, typing.Any]]:
# Reads script
scriptNameTemplate = scriptNameTemplate.format(osName)
with open(os.path.join(os.path.dirname(__file__), scriptNameTemplate)) as f:
script = f.read()
# Reads signature
with open(os.path.join(os.path.dirname(__file__), scriptNameTemplate + '.signature')) as f:
with open(
os.path.join(os.path.dirname(__file__), scriptNameTemplate + '.signature')
) as f:
signature = f.read()
return script, signature, params

View File

@ -1,10 +1,10 @@
# may be executed on old python version
from __future__ import unicode_literals
import sys
import os
import errno
import pwd
import six
USER = '__USER__'
KEY = '__KEY__'

View File

@ -17,9 +17,21 @@ filename = tools.saveTempFile(theFile)
executable = tools.findApp('x2goclient')
if executable is None:
raise Exception('''<p>You must have installed latest X2GO Client in order to connect to this UDS service.</p>
<p>Please, install the required packages for your platform</p>''')
raise Exception(
'''<p>You must have installed latest X2GO Client in order to connect to this UDS service.</p>
<p>Please, install the required packages for your platform</p>'''
)
subprocess.Popen([executable, '--session-conf={}'.format(filename), '--session=UDS/connect', '--close-disconnect', '--hide', '--no-menu', '--add-to-known-hosts'])
subprocess.Popen(
[
executable,
'--session-conf={}'.format(filename),
'--session=UDS/connect',
'--close-disconnect',
'--hide',
'--no-menu',
'--add-to-known-hosts',
]
)
# tools.addFileToUnlink(filename)
# tools.addFileToUnlink(keyFile)

View File

@ -15,7 +15,9 @@ fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], ti
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
raise Exception(
'<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>'
)
home = expanduser('~') + ':1;/media:1;'
keyFile = tools.saveTempFile(sp['key']) # type: ignore
@ -26,7 +28,19 @@ filename = tools.saveTempFile(theFile)
executable = tools.findApp('x2goclient')
if executable is None:
raise Exception('''<p>You must have installed latest X2GO Client in order to connect to this UDS service.</p>
<p>Please, install the required packages for your platform</p>''')
raise Exception(
'''<p>You must have installed latest X2GO Client in order to connect to this UDS service.</p>
<p>Please, install the required packages for your platform</p>'''
)
subprocess.Popen([executable, '--session-conf={}'.format(filename), '--session=UDS/connect', '--close-disconnect', '--hide', '--no-menu', '--add-to-known-hosts'])
subprocess.Popen(
[
executable,
'--session-conf={}'.format(filename),
'--session=UDS/connect',
'--close-disconnect',
'--hide',
'--no-menu',
'--add-to-known-hosts',
]
)

View File

@ -18,11 +18,23 @@ filename = tools.saveTempFile(theFile)
x2goPath = os.environ['PROGRAMFILES(X86)'] + '\\x2goclient'
executable = tools.findApp('x2goclient.exe', [x2goPath])
if executable is None:
raise Exception('''<p>You must have installed latest X2GO Client in order to connect to this UDS service.</p>
<p>You can download it for windows from <a href="http://wiki.x2go.org/doku.php">X2Go Site</a>.</p>''')
raise Exception(
'''<p>You must have installed latest X2GO Client in order to connect to this UDS service.</p>
<p>You can download it for windows from <a href="http://wiki.x2go.org/doku.php">X2Go Site</a>.</p>'''
)
# C:\Program Files (x86)\\x2goclient>x2goclient.exe --session-conf=c:/temp/sessions --session=UDS/test-session --close-disconnect --hide --no-menu
subprocess.Popen([executable, '--session-conf={}'.format(filename), '--session=UDS/connect', '--close-disconnect', '--hide', '--no-menu', '--add-to-known-hosts'])
subprocess.Popen(
[
executable,
'--session-conf={}'.format(filename),
'--session=UDS/connect',
'--close-disconnect',
'--hide',
'--no-menu',
'--add-to-known-hosts',
]
)
# tools.addFileToUnlink(filename)
# tools.addFileToUnlink(keyFile)

View File

@ -1,6 +1,6 @@
# This is a template
# Saved as .py for easier editing
#from __future__ import unicode_literals
# from __future__ import unicode_literals
# pylint: disable=import-error, no-name-in-module, too-many-format-args, undefined-variable
@ -16,7 +16,9 @@ fs = forward(remote=(sp['tunHost'], int(sp['tunPort'])), ticket=sp['ticket'], ti
# Check that tunnel works..
if fs.check() is False:
raise Exception('<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>')
raise Exception(
'<p>Could not connect to tunnel server.</p><p>Please, check your network settings.</p>'
)
# Care, expanduser is encoding using "mcbs", so treat it as bytes on python 2.7
home = expanduser('~').replace('\\', '\\\\') + '#1;'
@ -27,7 +29,19 @@ filename = tools.saveTempFile(theFile)
x2goPath = os.environ['PROGRAMFILES(X86)'] + '\\x2goclient'
executable = tools.findApp('x2goclient.exe', [x2goPath])
if executable is None:
raise Exception('''<p>You must have installed latest X2GO Client in default program file folder in order to connect to this UDS service.</p>
<p>You can download it for windows from <a href="http://wiki.x2go.org/doku.php">X2Go Site</a>.</p>''')
raise Exception(
'''<p>You must have installed latest X2GO Client in default program file folder in order to connect to this UDS service.</p>
<p>You can download it for windows from <a href="http://wiki.x2go.org/doku.php">X2Go Site</a>.</p>'''
)
subprocess.Popen([executable, '--session-conf={}'.format(filename), '--session=UDS/connect', '--close-disconnect', '--hide', '--no-menu', '--add-to-known-hosts'])
subprocess.Popen(
[
executable,
'--session-conf={}'.format(filename),
'--session=UDS/connect',
'--close-disconnect',
'--hide',
'--no-menu',
'--add-to-known-hosts',
]
)

View File

@ -51,6 +51,7 @@ class X2GOTransport(BaseX2GOTransport):
Provides access via X2GO to service.
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
"""
typeName = _('X2Go')
typeType = 'X2GOTransport'
typeDescription = _('X2Go access (Experimental). Direct connection.')
@ -69,15 +70,15 @@ class X2GOTransport(BaseX2GOTransport):
quality = BaseX2GOTransport.quality
def getUDSTransportScript( # pylint: disable=too-many-locals
self,
userService: 'models.UserService',
transport: 'models.Transport',
ip: str,
os: typing.Dict[str, str],
user: 'models.User',
password: str,
request: 'HttpRequest'
) -> typing.Tuple[str, str, typing.Mapping[str, typing.Any]]:
self,
userService: 'models.UserService',
transport: 'models.Transport',
ip: str,
os: typing.Dict[str, str],
user: 'models.User',
password: str,
request: 'HttpRequest',
) -> typing.Tuple[str, str, typing.Mapping[str, typing.Any]]:
ci = self.getConnectionInfo(userService, user, password)
username = ci['username']
@ -101,7 +102,7 @@ class X2GOTransport(BaseX2GOTransport):
rootless=rootless,
width=width,
height=height,
user=username
user=username,
)
osName = {
@ -111,13 +112,10 @@ class X2GOTransport(BaseX2GOTransport):
}.get(os['OS'])
if osName is None:
return super().getUDSTransportScript(userService, transport, ip, os, user, password, request)
return super().getUDSTransportScript(
userService, transport, ip, os, user, password, request
)
sp = {
'ip': ip,
'port': '22',
'key': priv,
'xf': xf
}
sp = {'ip': ip, 'port': '22', 'key': priv, 'xf': xf}
return self.getScript('scripts/{}/direct.py', osName, sp)

View File

@ -60,6 +60,7 @@ class BaseX2GOTransport(transports.Transport):
Provides access via X2GO to service.
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
"""
iconFile = 'x2go.png'
protocol = transports.protocols.X2GO
supportedOss = (OsDetector.Linux, OsDetector.Windows)
@ -68,7 +69,7 @@ class BaseX2GOTransport(transports.Transport):
order=2,
label=_('Username'),
tooltip=_('If not empty, this username will be always used as credential'),
tab=gui.CREDENTIALS_TAB
tab=gui.CREDENTIALS_TAB,
)
screenSize = gui.ChoiceField(
@ -82,9 +83,9 @@ class BaseX2GOTransport(transports.Transport):
{'id': CommonPrefs.SZ_1024x768, 'text': '1024x768'},
{'id': CommonPrefs.SZ_1366x768, 'text': '1366x768'},
{'id': CommonPrefs.SZ_1920x1080, 'text': '1920x1080'},
{'id': CommonPrefs.SZ_FULLSCREEN, 'text': ugettext_lazy('Full Screen')}
{'id': CommonPrefs.SZ_FULLSCREEN, 'text': ugettext_lazy('Full Screen')},
],
tab=gui.PARAMETERS_TAB
tab=gui.PARAMETERS_TAB,
)
desktopType = gui.ChoiceField(
@ -102,14 +103,16 @@ class BaseX2GOTransport(transports.Transport):
{'id': 'gnome-session-cinnamon2d', 'text': 'Cinnamon 2.2 (see docs)'},
{'id': 'UDSVAPP', 'text': 'UDS vAPP'},
],
tab=gui.PARAMETERS_TAB
tab=gui.PARAMETERS_TAB,
)
customCmd = gui.TextField(
order=12,
label=_('vAPP'),
tooltip=_('If UDS vAPP is selected as "Desktop", the FULL PATH of the app to be executed. If UDS vAPP is not selected, this field will be ignored.'),
tab=gui.PARAMETERS_TAB
tooltip=_(
'If UDS vAPP is selected as "Desktop", the FULL PATH of the app to be executed. If UDS vAPP is not selected, this field will be ignored.'
),
tab=gui.PARAMETERS_TAB,
)
sound = gui.CheckBoxField(
@ -117,15 +120,17 @@ class BaseX2GOTransport(transports.Transport):
label=_('Enable sound'),
tooltip=_('If checked, sound will be available'),
defvalue=gui.TRUE,
tab=gui.PARAMETERS_TAB
tab=gui.PARAMETERS_TAB,
)
exports = gui.CheckBoxField(
order=14,
label=_('Redirect home folder'),
tooltip=_('If checked, user home folder will be redirected. (On linux, also redirects /media)'),
tooltip=_(
'If checked, user home folder will be redirected. (On linux, also redirects /media)'
),
defvalue=gui.FALSE,
tab=gui.PARAMETERS_TAB
tab=gui.PARAMETERS_TAB,
)
speed = gui.ChoiceField(
@ -140,7 +145,7 @@ class BaseX2GOTransport(transports.Transport):
{'id': '3', 'text': 'WAN'},
{'id': '4', 'text': 'LAN'},
],
tab=gui.PARAMETERS_TAB
tab=gui.PARAMETERS_TAB,
)
soundType = gui.ChoiceField(
@ -152,7 +157,7 @@ class BaseX2GOTransport(transports.Transport):
{'id': 'pulse', 'text': 'Pulse'},
{'id': 'esd', 'text': 'ESD'},
],
tab=gui.ADVANCED_TAB
tab=gui.ADVANCED_TAB,
)
keyboardLayout = gui.TextField(
@ -160,7 +165,7 @@ class BaseX2GOTransport(transports.Transport):
order=31,
tooltip=_('Keyboard layout (es, us, fr, ...). Empty value means autodetect.'),
defvalue='',
tab=gui.ADVANCED_TAB
tab=gui.ADVANCED_TAB,
)
# 'nopack', '8', '64', '256', '512', '4k', '32k', '64k', '256k', '2m', '16m'
# '256-rdp', '256-rdp-compressed', '32k-rdp', '32k-rdp-compressed', '64k-rdp'
@ -180,7 +185,7 @@ class BaseX2GOTransport(transports.Transport):
order=32,
tooltip=_('Pack format. Change with care!'),
defvalue='16m-jpeg',
tab=gui.ADVANCED_TAB
tab=gui.ADVANCED_TAB,
)
quality = gui.NumericField(
@ -192,7 +197,7 @@ class BaseX2GOTransport(transports.Transport):
minValue=1,
maxValue=9,
required=True,
tab=gui.ADVANCED_TAB
tab=gui.ADVANCED_TAB,
)
def isAvailableFor(self, userService: 'models.UserService', ip: str) -> bool:
@ -213,11 +218,18 @@ class BaseX2GOTransport(transports.Transport):
def getScreenSize(self) -> typing.Tuple[int, int]:
return CommonPrefs.getWidthHeight(self.screenSize.value)
def processedUser(self, userService: 'models.UserService', user: 'models.User') -> str:
def processedUser(
self, userService: 'models.UserService', user: 'models.User'
) -> str:
v = self.processUserPassword(userService, user, '')
return v['username']
def processUserPassword(self, userService: 'models.UserService', user: 'models.User', password: str) -> typing.Dict[str, str]:
def processUserPassword(
self,
userService: typing.Union['models.UserService', 'models.ServicePool'],
user: 'models.User',
password: str,
) -> typing.Dict[str, str]:
username = user.getUsernameForAuth()
if self.fixedName.value != '':
@ -229,11 +241,11 @@ class BaseX2GOTransport(transports.Transport):
return {'protocol': self.protocol, 'username': username, 'password': ''}
def getConnectionInfo(
self,
userService: typing.Union['models.UserService', 'models.ServicePool'],
user: 'models.User',
password: str
) -> typing.Dict[str, str]:
self,
userService: typing.Union['models.UserService', 'models.ServicePool'],
user: 'models.User',
password: str,
) -> typing.Dict[str, str]:
return self.processUserPassword(userService, user, password)
def genKeyPairForSsh(self) -> typing.Tuple[str, str]:
@ -264,18 +276,24 @@ class BaseX2GOTransport(transports.Transport):
return data.replace('__USER__', user).replace('__KEY__', pubKey)
def getAndPushKey(self, userName: str, userService: 'models.UserService') -> typing.Tuple[str, str]:
def getAndPushKey(
self, userName: str, userService: 'models.UserService'
) -> typing.Tuple[str, str]:
priv, pub = self.genKeyPairForSsh()
authScript = self.getAuthorizeScript(userName, pub)
userServiceManager().sendScript(userService, authScript)
return priv, pub
def getScript(self, scriptNameTemplate: str, osName: str, params: typing.Dict[str, typing.Any]) -> typing.Tuple[str, str, typing.Dict[str, typing.Any]]:
def getScript(
self, scriptNameTemplate: str, osName: str, params: typing.Dict[str, typing.Any]
) -> typing.Tuple[str, str, typing.Dict[str, typing.Any]]:
# Reads script
scriptNameTemplate = scriptNameTemplate.format(osName)
with open(os.path.join(os.path.dirname(__file__), scriptNameTemplate)) as f:
script = f.read()
# Reads signature
with open(os.path.join(os.path.dirname(__file__), scriptNameTemplate + '.signature')) as f:
with open(
os.path.join(os.path.dirname(__file__), scriptNameTemplate + '.signature')
) as f:
signature = f.read()
return script, signature, params

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2016-2019 Virtual Cable S.L.
# Copyright (c) 2016-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.
#
@ -95,7 +95,19 @@ sshproxykrblogin=false
'''
def getTemplate(speed, pack, quality, sound, soundSystem, windowManager, exports, rootless, width, height, user):
def getTemplate(
speed,
pack,
quality,
sound,
soundSystem,
windowManager,
exports,
rootless,
width,
height,
user,
):
trueFalse = lambda x: 'true' if x else 'false'
export = 'export="{export}"' if exports else ''
if width == -1 or height == -1:
@ -116,5 +128,5 @@ def getTemplate(speed, pack, quality, sound, soundSystem, windowManager, exports
width=width,
height=height,
fullscreen=fullscreen,
user=user
user=user,
)

View File

@ -96,7 +96,6 @@ class TX2GOTransport(BaseX2GOTransport):
tab=gui.TUNNEL_TAB,
)
fixedName = BaseX2GOTransport.fixedName
screenSize = BaseX2GOTransport.screenSize
desktopType = BaseX2GOTransport.desktopType

View File

@ -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.
#
@ -48,6 +48,7 @@ import sys
logger = logging.getLogger(__name__)
def __init__():
"""
This imports all packages that are descendant of this package, and, after that,
@ -60,7 +61,7 @@ def __init__():
for _, name, _ in pkgutil.iter_modules([pkgpath]):
# __import__(name, globals(), locals(), [], 1)
importlib.import_module('.' + name, __name__) # import module
importlib.invalidate_caches()
# This is marked as error in IDE, but it's not (__subclasses__)