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

View File

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

View File

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

View File

@ -39,6 +39,7 @@ import typing
from uds.core.util import os_detector as OsDetector from uds.core.util import os_detector as OsDetector
class RDPFile: class RDPFile:
fullScreen = False fullScreen = False
width = '800' width = '800'
@ -71,13 +72,13 @@ class RDPFile:
enforcedShares: typing.Optional[str] = None enforcedShares: typing.Optional[str] = None
def __init__( def __init__(
self, self,
fullScreen: bool, fullScreen: bool,
width: typing.Union[str, int], width: typing.Union[str, int],
height: typing.Union[str, int], height: typing.Union[str, int],
bpp: str, bpp: str,
target: str = OsDetector.Windows target: str = OsDetector.Windows,
): ):
self.width = str(width) self.width = str(width)
self.height = str(height) self.height = str(height)
self.bpp = str(bpp) self.bpp = str(bpp)
@ -95,7 +96,9 @@ class RDPFile:
return self.get() return self.get()
@property @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 Parameters for xfreerdp >= 1.1.0 with self rdp description
Note that server is not added Note that server is not added
@ -188,7 +191,7 @@ class RDPFile:
def getGeneric(self): # pylint: disable=too-many-statements def getGeneric(self): # pylint: disable=too-many-statements
password = '{password}' password = '{password}'
screenMode = '2' if self.fullScreen else '1' 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' serials = '1' if self.redirectSerials else '0'
scards = '1' if self.redirectSmartcards else '0' scards = '1' if self.redirectSmartcards else '0'
printers = '1' if self.redirectPrinters else '0' printers = '1' if self.redirectPrinters else '0'
@ -250,7 +253,11 @@ class RDPFile:
if self.redirectWebcam: if self.redirectWebcam:
res += 'camerastoredirect:s:*\n' 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 != 'false':
if self.redirectDrives == 'true': if self.redirectDrives == 'true':
@ -259,7 +266,9 @@ class RDPFile:
res += 'drivestoredirect:s:{}DynamicDrives\n'.format(enforcedSharesStr) res += 'drivestoredirect:s:{}DynamicDrives\n'.format(enforcedSharesStr)
res += 'devicestoredirect:s:*\n' 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? # DirectX?
res += 'redirectdirectx:i:1\n' res += 'redirectdirectx:i:1\n'
@ -273,12 +282,11 @@ class RDPFile:
def as_rdp_url(self) -> str: def as_rdp_url(self) -> str:
# Some parameters # Some parameters
screenMode = '2' if self.fullScreen else '1' 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' useMultimon = '1' if self.multimon else '0'
disableWallpaper = '0' if self.showWallpaper else '1' disableWallpaper = '0' if self.showWallpaper else '1'
printers = '1' if self.redirectPrinters else '0' printers = '1' if self.redirectPrinters else '0'
credsspsupport = '1' if self.enablecredsspsupport else '0' credsspsupport = '1' if self.enablecredsspsupport else '0'
parameters = [ parameters = [
('full address', f's:{self.address}'), ('full address', f's:{self.address}'),
@ -295,7 +303,7 @@ class RDPFile:
('disable full window drag', 'i:1'), ('disable full window drag', 'i:1'),
('authentication level', f'i:0'), ('authentication level', f'i:0'),
# Not listed, but maybe usable? # Not listed, but maybe usable?
('enablecredsspsupport', f'i:{credsspsupport}') ('enablecredsspsupport', f'i:{credsspsupport}'),
] ]
if self.username: if self.username:
parameters.append(('username', f's:{urllib.parse.quote(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 if self.redirectDrives != 'false': # Only "all drives" is supported
parameters.append(('drivestoredirect', 's:*')) 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 import subprocess # noqa
# Saved as .py for easier editing
from __future__ import unicode_literals
import subprocess
from uds import tools # type: ignore from uds import tools # type: ignore
# Inject local passed sp into globals for inner functions # Inject local passed sp into globals for inner functions
globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable
def execUdsRdp(udsrdp): def execUdsRdp(udsrdp):
import subprocess # @Reimport import subprocess # @Reimport
import os.path import os.path
params = [os.path.expandvars(i) for i in [udsrdp] + sp['as_new_xfreerdp_params'] + ['/v:{}'.format(sp['address'])]] # type: ignore 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)) tools.addTaskToWait(subprocess.Popen(params))
@ -19,9 +17,11 @@ def execUdsRdp(udsrdp):
def execNewXFreeRdp(xfreerdp): def execNewXFreeRdp(xfreerdp):
import subprocess # @Reimport import subprocess # @Reimport
import os.path import os.path
params = [os.path.expandvars(i) for i in [xfreerdp] + sp['as_new_xfreerdp_params'] + ['/v:{}'.format(sp['address'])]] # type: ignore 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)) 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) # 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') xfreerdp = tools.findApp('xfreerdp')
udsrdp = tools.findApp('udsrdp') udsrdp = tools.findApp('udsrdp')
@ -34,9 +34,11 @@ if udsrdp is not None:
fnc, app = execUdsRdp, udsrdp fnc, app = execUdsRdp, udsrdp
if app is None or fnc is None: 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>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> <p>Also note that xfreerdp prior to version 1.1 will not be taken into consideration.</p>
''') '''
)
else: else:
fnc(app) # @UndefinedVariable fnc(app) # @UndefinedVariable

View File

@ -1,8 +1,5 @@
# This is a template import subprocess # noqa
# Saved as .py for easier editing
from __future__ import unicode_literals
import subprocess
from uds.tunnel import forward # type: ignore from uds.tunnel import forward # type: ignore
from uds import tools # 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 # Inject local passed sp into globals for functions
globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable
def execUdsRdp(udsrdp, port): def execUdsRdp(udsrdp, port):
import subprocess # @Reimport import subprocess # @Reimport
import os.path 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 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)) tools.addTaskToWait(subprocess.Popen(params))
@ -20,9 +19,11 @@ def execUdsRdp(udsrdp, port):
def execNewXFreeRdp(xfreerdp, port): def execNewXFreeRdp(xfreerdp, port):
import subprocess # @Reimport import subprocess # @Reimport
import os.path 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 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)) 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) # 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') xfreerdp = tools.findApp('xfreerdp')
udsrdp = tools.findApp('udsrdp') udsrdp = tools.findApp('udsrdp')
@ -35,16 +36,20 @@ if udsrdp:
fnc, app = execUdsRdp, udsrdp fnc, app = execUdsRdp, udsrdp
if app is None or fnc is None: 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>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> <p>Also note that xfreerdp prior to version 1.1 will not be taken into consideration.</p>
''') '''
)
else: else:
# Open tunnel # 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.. # Check that tunnel works..
if fs.check() is False: 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]) 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 # pylint: disable=import-error, no-name-in-module, too-many-format-args, undefined-variable, invalid-sequence-index
import subprocess import subprocess
import shutil import shutil
@ -13,21 +9,32 @@ from uds import tools # type: ignore
# Inject local passed sp into globals for functions # Inject local passed sp into globals for functions
globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable 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') xfreerdp = tools.findApp('xfreerdp')
executable = None executable = None
def fixResolution(): def fixResolution():
import re import re
import subprocess 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) groups = re.search(r': \d* x \d*', results)
width, height = '1024', '768' # Safe default values width, height = '1024', '768' # Safe default values
if groups: if groups:
res = groups.group(0).split(' ') 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 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 # Check first xfreerdp, allow password redir
if xfreerdp and os.path.isfile(xfreerdp): if xfreerdp and os.path.isfile(xfreerdp):
executable = 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 executable is None:
if sp['as_file']: # type: ignore 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> <p>In order to connect to UDS RDP Sessions, you need to have a<p>
<ul> <ul>
<li> <li>
@ -46,9 +54,11 @@ if executable is None:
<p><b>Xfreerdp</b> from homebrew</p> <p><b>Xfreerdp</b> from homebrew</p>
</li> </li>
</ul> </ul>
''') '''
)
else: 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> <p>In order to connect to UDS RDP Sessions, you need to have a<p>
<ul> <ul>
<li> <li>
@ -65,16 +75,26 @@ if executable is None:
</p> </p>
</li> </li>
</ul> </ul>
''') '''
)
elif executable == msrdc: elif executable == msrdc:
theFile = sp['as_file'] # type: ignore theFile = sp['as_file'] # type: ignore
filename = tools.saveTempFile(theFile) filename = tools.saveTempFile(theFile)
# Rename as .rdp, so open recognizes it # Rename as .rdp, so open recognizes it
shutil.move(filename, filename + '.rdp') 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) ) # 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') tools.addFileToUnlink(filename + '.rdp')
elif executable == xfreerdp: elif executable == xfreerdp:
# Fix resolution... # 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 params = [os.path.expandvars(i) for i in [executable] + xfparms + ['/v:{}'.format(sp['address'])]] # type: ignore
subprocess.Popen(params) subprocess.Popen(params)

View File

@ -15,19 +15,29 @@ from uds import tools # type: ignore
# Inject local passed sp into globals for functions # Inject local passed sp into globals for functions
globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable
def fixResolution(): def fixResolution():
import re import re
import subprocess 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) groups = re.search(r': \d* x \d*', results)
width, height = '1024', '768' # Safe default values width, height = '1024', '768' # Safe default values
if groups: if groups:
res = groups.group(0).split(' ') 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 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') xfreerdp = tools.findApp('xfreerdp')
executable = None executable = None
@ -39,7 +49,8 @@ elif msrdc and os.path.isfile(msrdc) and sp['as_file']: # type: ignore
if executable is None: if executable is None:
if sp['as_rdp_url']: # type: ignore 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> <p>In order to connect to UDS RDP Sessions, you need to have a<p>
<ul> <ul>
<li> <li>
@ -49,9 +60,11 @@ if executable is None:
<p><b>Xfreerdp</b> from homebrew</p> <p><b>Xfreerdp</b> from homebrew</p>
</li> </li>
</ul> </ul>
''') '''
)
else: 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> <p>In order to connect to UDS RDP Sessions, you need to have a<p>
<ul> <ul>
<li> <li>
@ -68,7 +81,8 @@ if executable is None:
</p> </p>
</li> </li>
</ul> </ul>
''') '''
)
# Open tunnel # 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
@ -76,12 +90,12 @@ address = '127.0.0.1:{}'.format(fs.server_address[1])
# Check that tunnel works.. # Check that tunnel works..
if fs.check() is False: 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: if executable == msrdc:
theFile = theFile = sp['as_file'].format( # type: ignore theFile = theFile = sp['as_file'].format(address=address) # type: ignore
address=address
)
filename = tools.saveTempFile(theFile) filename = tools.saveTempFile(theFile)
# Rename as .rdp, so open recognizes it # Rename as .rdp, so open recognizes it
@ -89,7 +103,16 @@ if executable == msrdc:
# 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) ) # 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') tools.addFileToUnlink(filename + '.rdp')
elif executable == xfreerdp: elif executable == xfreerdp:
# Fix resolution... # Fix resolution...
@ -98,6 +121,8 @@ elif executable == xfreerdp:
except Exception as e: except Exception as e:
xfparms = list(map(lambda x: x.replace('#WIDTH#', '1400').replace('#HEIGHT#', '800'), sp['as_new_xfreerdp_params'])) # type: ignore 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) subprocess.Popen(params)

View File

@ -13,13 +13,22 @@ from uds import tools # type: ignore
thePass = sp['password'].encode('UTF-16LE') # type: ignore thePass = sp['password'].encode('UTF-16LE') # type: ignore
try: 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: except Exception:
# logger.info('Cannot encrypt for user, trying for machine') # 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: 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.SetValueEx(key, sp['ip'], 0, wreg.REG_DWORD, 255) # type: ignore
wreg.CloseKey(key) wreg.CloseKey(key)
except Exception as e: except Exception as e:
@ -27,15 +36,14 @@ except Exception as e:
pass # Key does not exists, ok... 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 # 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 theFile = sp['as_file'].format(password=password) # type: ignore
password=password
)
filename = tools.saveTempFile(theFile) filename = tools.saveTempFile(theFile)
executable = tools.findApp('mstsc.exe') executable = tools.findApp('mstsc.exe')
if executable is None: 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]) subprocess.Popen([executable, filename])
tools.addFileToUnlink(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.. # Check that tunnel works..
if fs.check() is False: 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 thePass = sp['password'].encode('UTF-16LE') # type: ignore
try: 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: except Exception:
# Cannot encrypt for user, trying for machine # 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 # 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 theFile = sp['as_file'].format( # type: ignore
password=password, password=password, address='127.0.0.1:{}'.format(fs.server_address[1])
address='127.0.0.1:{}'.format(fs.server_address[1])
) )
filename = tools.saveTempFile(theFile) filename = tools.saveTempFile(theFile)
executable = tools.findApp('mstsc.exe') executable = tools.findApp('mstsc.exe')
if executable is None: 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: 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.SetValueEx(key, '127.0.0.1', 0, wreg.REG_DWORD, 255) # type: ignore
wreg.CloseKey(key) wreg.CloseKey(key)
except Exception as e: except Exception as e:

View File

@ -67,15 +67,15 @@ class RemoteViewerFile:
delete_file: bool = True delete_file: bool = True
def __init__( def __init__(
self, self,
host: str, host: str,
port: str, port: str,
tls_port: str, tls_port: str,
password: str, password: str,
ca: str, ca: str,
host_subject: str, host_subject: str,
fullscreen: bool = False fullscreen: bool = False,
): ):
self.host = host self.host = host
self.port = port self.port = port
self.tls_port = tls_port self.tls_port = tls_port
@ -102,7 +102,9 @@ class RemoteViewerFile:
usb_auto_share = '01'[self.usb_auto_share] usb_auto_share = '01'[self.usb_auto_share]
new_usb_auto_share = '01'[self.new_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( return TEMPLATE.format(
type=self.connectionType, type=self.connectionType,
@ -118,5 +120,7 @@ class RemoteViewerFile:
delete_file=delete_file, delete_file=delete_file,
host_subject=self.host_subject if tls_port != '-1' else '', host_subject=self.host_subject if tls_port != '-1' else '',
ca=ca 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') executable = tools.findApp('remote-viewer')
if executable is None: 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> <p>
Please, install appropriate package for your Linux system. (probably named something like <b>remote-viewer</b>) Please, install appropriate package for your Linux system. (probably named something like <b>remote-viewer</b>)
</p> </p>
''') '''
)
theFile = sp['as_file'] # type: ignore theFile = sp['as_file'] # type: ignore

View File

@ -11,14 +11,16 @@ from uds.tunnel import forward # type: ignore
executable = tools.findApp('remote-viewer') executable = tools.findApp('remote-viewer')
if executable is None: 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> <p>
Please, install appropriate package for your system. Please, install appropriate package for your system.
</p> </p>
<p> <p>
Please, install appropriate package for your Linux system. (probably named something like <b>virt-viewer</b>) Please, install appropriate package for your Linux system. (probably named something like <b>virt-viewer</b>)
</p> </p>
''') '''
)
theFile = sp['as_file_ns'] # type: ignore theFile = sp['as_file_ns'] # type: ignore
@ -29,7 +31,9 @@ if sp['ticket']: # type: ignore
# Check that tunnel works.. # Check that tunnel works..
if fs.check() is False: 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 fss = None
if sp['ticket_secure']: # type: ignore if sp['ticket_secure']: # type: ignore
@ -38,11 +42,13 @@ if sp['ticket_secure']: # type: ignore
# Check that tunnel works.. # Check that tunnel works..
if fss.check() is False: 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( theFile = theFile.format(
secure_port='-1' if not fss else fss.server_address[1], 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) filename = tools.saveTempFile(theFile)

View File

@ -11,7 +11,8 @@ from uds import tools # type: ignore
remoteViewer = '/Applications/RemoteViewer.app/Contents/MacOS/RemoteViewer' remoteViewer = '/Applications/RemoteViewer.app/Contents/MacOS/RemoteViewer'
if not os.path.isfile(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> <p>
Please, install appropriate package for your system. Please, install appropriate package for your system.
</p> </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/> 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 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> </p>
''') '''
)
theFile = sp['as_file'] # type: ignore 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' remoteViewer = '/Applications/RemoteViewer.app/Contents/MacOS/RemoteViewer'
if not os.path.isfile(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> <p>
Please, install appropriate package for your system. Please, install appropriate package for your system.
</p> </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/> 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 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> </p>
''') '''
)
theFile = sp['as_file_ns'] # type: ignore theFile = sp['as_file_ns'] # type: ignore
fs = None fs = None
@ -33,7 +35,9 @@ if sp['ticket']: # type: ignore
# Check that tunnel works.. # Check that tunnel works..
if fs.check() is False: 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 fss = None
if sp['ticket_secure']: # type: ignore if sp['ticket_secure']: # type: ignore
@ -42,11 +46,13 @@ if sp['ticket_secure']: # type: ignore
# Check that tunnel works.. # Check that tunnel works..
if fss.check() is False: 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( theFile = theFile.format(
secure_port='-1' if not fss else fss.server_address[1], 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) filename = tools.saveTempFile(theFile)

View File

@ -19,14 +19,16 @@ for env in ('PROGRAMFILES', 'PROGRAMW6432'):
executable = tools.findApp('remote-viewer.exe', extraPaths) executable = tools.findApp('remote-viewer.exe', extraPaths)
if executable is None: 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> <p>
Please, install appropriate package for your system. Please, install appropriate package for your system.
</p> </p>
<p> <p>
<a href="http://virt-manager.org/download/">Open download page</a> <a href="http://virt-manager.org/download/">Open download page</a>
</p> </p>
''') '''
)
theFile = sp['as_file'] # type: ignore theFile = sp['as_file'] # type: ignore

View File

@ -20,14 +20,16 @@ for env in ('PROGRAMFILES', 'PROGRAMW6432'):
executable = tools.findApp('remote-viewer.exe', extraPaths) executable = tools.findApp('remote-viewer.exe', extraPaths)
if executable is None: 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> <p>
Please, install appropriate package for your system. Please, install appropriate package for your system.
</p> </p>
<p> <p>
<a href="http://virt-manager.org/download/">Open download page</a> <a href="http://virt-manager.org/download/">Open download page</a>
</p> </p>
''') '''
)
theFile = sp['as_file_ns'] # type: ignore theFile = sp['as_file_ns'] # type: ignore
fs = None fs = None
if sp['ticket']: # type: ignore if sp['ticket']: # type: ignore
@ -36,7 +38,9 @@ if sp['ticket']: # type: ignore
# Check that tunnel works.. # Check that tunnel works..
if fs.check() is False: 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 fss = None
if sp['ticket_secure']: # type: ignore if sp['ticket_secure']: # type: ignore
@ -45,11 +49,13 @@ if sp['ticket_secure']: # type: ignore
# Check that tunnel works.. # Check that tunnel works..
if fss.check() is False: 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( theFile = theFile.format(
secure_port='-1' if not fss else fss.server_address[1], 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) filename = tools.saveTempFile(theFile)

View File

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

View File

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

View File

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

View File

@ -17,9 +17,21 @@ filename = tools.saveTempFile(theFile)
executable = tools.findApp('x2goclient') executable = tools.findApp('x2goclient')
if executable is None: if executable is None:
raise Exception('''<p>You must have installed latest X2GO Client in order to connect to this UDS service.</p> raise Exception(
<p>Please, install the required packages for your platform</p>''') '''<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(filename)
# tools.addFileToUnlink(keyFile) # 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.. # Check that tunnel works..
if fs.check() is False: 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;' home = expanduser('~') + ':1;/media:1;'
keyFile = tools.saveTempFile(sp['key']) # type: ignore keyFile = tools.saveTempFile(sp['key']) # type: ignore
@ -26,7 +28,19 @@ filename = tools.saveTempFile(theFile)
executable = tools.findApp('x2goclient') executable = tools.findApp('x2goclient')
if executable is None: if executable is None:
raise Exception('''<p>You must have installed latest X2GO Client in order to connect to this UDS service.</p> raise Exception(
<p>Please, install the required packages for your platform</p>''') '''<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' x2goPath = os.environ['PROGRAMFILES(X86)'] + '\\x2goclient'
executable = tools.findApp('x2goclient.exe', [x2goPath]) executable = tools.findApp('x2goclient.exe', [x2goPath])
if executable is None: if executable is None:
raise Exception('''<p>You must have installed latest X2GO Client in order to connect to this UDS service.</p> raise Exception(
<p>You can download it for windows from <a href="http://wiki.x2go.org/doku.php">X2Go Site</a>.</p>''') '''<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 # 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(filename)
# tools.addFileToUnlink(keyFile) # tools.addFileToUnlink(keyFile)

View File

@ -1,6 +1,6 @@
# This is a template # This is a template
# Saved as .py for easier editing # 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 # 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.. # Check that tunnel works..
if fs.check() is False: 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 # Care, expanduser is encoding using "mcbs", so treat it as bytes on python 2.7
home = expanduser('~').replace('\\', '\\\\') + '#1;' home = expanduser('~').replace('\\', '\\\\') + '#1;'
@ -27,7 +29,19 @@ filename = tools.saveTempFile(theFile)
x2goPath = os.environ['PROGRAMFILES(X86)'] + '\\x2goclient' x2goPath = os.environ['PROGRAMFILES(X86)'] + '\\x2goclient'
executable = tools.findApp('x2goclient.exe', [x2goPath]) executable = tools.findApp('x2goclient.exe', [x2goPath])
if executable is None: 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> raise Exception(
<p>You can download it for windows from <a href="http://wiki.x2go.org/doku.php">X2Go Site</a>.</p>''') '''<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. 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 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') typeName = _('X2Go')
typeType = 'X2GOTransport' typeType = 'X2GOTransport'
typeDescription = _('X2Go access (Experimental). Direct connection.') typeDescription = _('X2Go access (Experimental). Direct connection.')
@ -69,15 +70,15 @@ class X2GOTransport(BaseX2GOTransport):
quality = BaseX2GOTransport.quality quality = BaseX2GOTransport.quality
def getUDSTransportScript( # pylint: disable=too-many-locals def getUDSTransportScript( # pylint: disable=too-many-locals
self, self,
userService: 'models.UserService', userService: 'models.UserService',
transport: 'models.Transport', transport: 'models.Transport',
ip: str, ip: str,
os: typing.Dict[str, str], os: typing.Dict[str, str],
user: 'models.User', user: 'models.User',
password: str, password: str,
request: 'HttpRequest' request: 'HttpRequest',
) -> typing.Tuple[str, str, typing.Mapping[str, typing.Any]]: ) -> typing.Tuple[str, str, typing.Mapping[str, typing.Any]]:
ci = self.getConnectionInfo(userService, user, password) ci = self.getConnectionInfo(userService, user, password)
username = ci['username'] username = ci['username']
@ -101,7 +102,7 @@ class X2GOTransport(BaseX2GOTransport):
rootless=rootless, rootless=rootless,
width=width, width=width,
height=height, height=height,
user=username user=username,
) )
osName = { osName = {
@ -111,13 +112,10 @@ class X2GOTransport(BaseX2GOTransport):
}.get(os['OS']) }.get(os['OS'])
if osName is None: 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 = { sp = {'ip': ip, 'port': '22', 'key': priv, 'xf': xf}
'ip': ip,
'port': '22',
'key': priv,
'xf': xf
}
return self.getScript('scripts/{}/direct.py', osName, sp) return self.getScript('scripts/{}/direct.py', osName, sp)

View File

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

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright (c) 2016-2019 Virtual Cable S.L. # Copyright (c) 2016-2021 Virtual Cable S.L.U.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without modification, # 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, # * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution. # 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 # may be used to endorse or promote products derived from this software
# without specific prior written permission. # 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' trueFalse = lambda x: 'true' if x else 'false'
export = 'export="{export}"' if exports else '' export = 'export="{export}"' if exports else ''
if width == -1 or height == -1: if width == -1 or height == -1:
@ -116,5 +128,5 @@ def getTemplate(speed, pack, quality, sound, soundSystem, windowManager, exports
width=width, width=width,
height=height, height=height,
fullscreen=fullscreen, fullscreen=fullscreen,
user=user user=user,
) )

View File

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

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright (c) 2012 Virtual Cable S.L. # Copyright (c) 2012-2021 Virtual Cable S.L.U.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without modification, # 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, # * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation # this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution. # 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 # may be used to endorse or promote products derived from this software
# without specific prior written permission. # without specific prior written permission.
# #
@ -48,6 +48,7 @@ import sys
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def __init__(): def __init__():
""" """
This imports all packages that are descendant of this package, and, after that, 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]): for _, name, _ in pkgutil.iter_modules([pkgpath]):
# __import__(name, globals(), locals(), [], 1) # __import__(name, globals(), locals(), [], 1)
importlib.import_module('.' + name, __name__) # import module importlib.import_module('.' + name, __name__) # import module
importlib.invalidate_caches() importlib.invalidate_caches()
# This is marked as error in IDE, but it's not (__subclasses__) # This is marked as error in IDE, but it's not (__subclasses__)