mirror of
https://github.com/dkmstr/openuds.git
synced 2025-01-11 05:17:55 +03:00
Modified transport to adapt for accept future client scripts in more langs
This commit is contained in:
parent
d0e9c96573
commit
5f93b68c25
@ -81,7 +81,7 @@ class Client(Handler):
|
||||
if error:
|
||||
if isinstance(error, int):
|
||||
error = errors.errorString(error)
|
||||
error = str(error) # Ensure error is an string
|
||||
error = str(error) # Ensures error is an string
|
||||
if errorCode != 0:
|
||||
# Reformat error so it is better understood by users
|
||||
# error += ' (code {0:04X})'.format(errorCode)
|
||||
@ -102,7 +102,7 @@ class Client(Handler):
|
||||
"""
|
||||
return Client.result(_('Correct'))
|
||||
|
||||
def get(self): # pylint: disable=too-many-locals
|
||||
def get(self):
|
||||
"""
|
||||
Processes get requests
|
||||
"""
|
||||
@ -128,7 +128,7 @@ class Client(Handler):
|
||||
scrambler,
|
||||
) = (
|
||||
self._args
|
||||
) # If more than 2 args, got an error. pylint: disable=unbalanced-tuple-unpacking
|
||||
) # If more than 2 args, raise an error
|
||||
hostname = self._params['hostname'] # Or if hostname is not included...
|
||||
srcIp = self._request.ip
|
||||
|
||||
@ -191,11 +191,7 @@ class Client(Handler):
|
||||
if not transportInstance:
|
||||
raise Exception('No transport instance!!!')
|
||||
|
||||
(
|
||||
transportScript,
|
||||
signature,
|
||||
params,
|
||||
) = transportInstance.getEncodedTransportScript(
|
||||
transport_script =transportInstance.getEncodedTransportScript(
|
||||
userService,
|
||||
transport,
|
||||
ip,
|
||||
@ -205,16 +201,14 @@ class Client(Handler):
|
||||
self._request,
|
||||
)
|
||||
|
||||
logger.debug('Signature: %s', signature)
|
||||
logger.debug('Data:#######\n%s\n###########', params)
|
||||
logger.debug('Script: %s', transport_script)
|
||||
|
||||
return Client.result(
|
||||
result={
|
||||
'script': transportScript,
|
||||
'signature': signature, # It is already on base64
|
||||
'params': codecs.encode(
|
||||
codecs.encode(json.dumps(params).encode(), 'bz2'), 'base64'
|
||||
).decode(),
|
||||
'script': transport_script.script,
|
||||
'type': transport_script.script_type,
|
||||
'signature': transport_script.signature_b64, # It is already on base64
|
||||
'params': transport_script.encoded_parameters,
|
||||
}
|
||||
)
|
||||
except ServiceNotReadyError as e:
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2012-2021 Virtual Cable S.L.U.
|
||||
# Copyright (c) 2012-2022 Virtual Cable S.L.U.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -32,8 +32,7 @@ UDS Service modules interfaces and classes.
|
||||
|
||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from .transport import Transport
|
||||
from .transport import DIRECT_GROUP, TUNNELED_GROUP
|
||||
from .transport import Transport, TransportScript, DIRECT_GROUP, TUNNELED_GROUP
|
||||
from .transport_factory import TransportsFactory
|
||||
from . import protocols
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
"""
|
||||
import codecs
|
||||
import logging
|
||||
import json
|
||||
import typing
|
||||
|
||||
from django.utils.translation import gettext_noop as _
|
||||
@ -52,6 +53,18 @@ logger = logging.getLogger(__name__)
|
||||
DIRECT_GROUP = _('Direct')
|
||||
TUNNELED_GROUP = _('Tunneled')
|
||||
|
||||
class TransportScript(typing.NamedTuple):
|
||||
script: str = ''
|
||||
script_type: typing.Union[typing.Literal['python'], typing.Literal['lua']] = 'python' # currently only python is supported
|
||||
signature_b64: str = '' # Signature of the script in base64
|
||||
parameters: typing.Mapping[str, typing.Any] = {}
|
||||
|
||||
@property
|
||||
def encoded_parameters(self) -> str:
|
||||
"""
|
||||
Returns encoded parameters for transport script
|
||||
"""
|
||||
return codecs.encode(codecs.encode(json.dumps(self.parameters).encode(), 'bz2'), 'base64').decode()
|
||||
|
||||
class Transport(Module):
|
||||
"""
|
||||
@ -211,14 +224,14 @@ class Transport(Module):
|
||||
user: 'models.User',
|
||||
password: str,
|
||||
request: 'ExtendedHttpRequestWithUser',
|
||||
) -> typing.Tuple[str, str, typing.Mapping[str, typing.Any]]:
|
||||
) -> TransportScript:
|
||||
"""
|
||||
If this is an uds transport, this will return the tranport script needed for executing
|
||||
this on client
|
||||
"""
|
||||
return (
|
||||
"raise Exception('The transport {transport} is not supported on your platform.'.format(transport=params['transport']))",
|
||||
'EH/91J7u9+/sHtB5+EUVRDW1+jqF0LuZzfRi8qxyIuSdJuWt'
|
||||
return TransportScript(
|
||||
script="raise Exception('The transport {transport} is not supported on your platform.'.format(transport=params['transport']))",
|
||||
signature_b64='EH/91J7u9+/sHtB5+EUVRDW1+jqF0LuZzfRi8qxyIuSdJuWt'
|
||||
'8V8Yngu24p0NNr13TaxPQ1rpGN8x0NsU/Ma8k4GGohc+zxdf'
|
||||
'4xlkwMjAIytp8jaMHKkzvcihiIAMtaicP786FZCwGMmFTH4Z'
|
||||
'A9i7YWaSzT95h84kirAG67J0GWKiyATxs6mtxBNaLgqU4juA'
|
||||
@ -233,7 +246,7 @@ class Transport(Module):
|
||||
'JuVuquKKSfiwOIdYcdPJ6gvpgkQQDPqt7wN+duyZA0FI5F4h'
|
||||
'O6acQZmbjBCqZoo9Qsg7k9cTcalNkc5flEYAk1mULnddgDM6'
|
||||
'YGmoJgVnDr0=',
|
||||
{'transport': transport.name},
|
||||
parameters={'transport': transport.name},
|
||||
)
|
||||
|
||||
def getEncodedTransportScript(
|
||||
@ -245,21 +258,21 @@ class Transport(Module):
|
||||
user: 'models.User',
|
||||
password: str,
|
||||
request: 'ExtendedHttpRequestWithUser',
|
||||
) -> typing.Tuple[str, str, typing.Mapping[str, str]]:
|
||||
) -> TransportScript:
|
||||
"""
|
||||
Encodes the script so the client can understand it
|
||||
"""
|
||||
script, signature, params = self.getUDSTransportScript(
|
||||
transport_script = self.getUDSTransportScript(
|
||||
userService, transport, ip, os, user, password, request
|
||||
)
|
||||
logger.debug('Transport script: %s', script)
|
||||
logger.debug('Transport script: %s', transport_script)
|
||||
|
||||
return (
|
||||
codecs.encode(codecs.encode(script.encode(), 'bz2'), 'base64')
|
||||
return TransportScript(
|
||||
script=codecs.encode(codecs.encode(transport_script.script.encode(), 'bz2'), 'base64')
|
||||
.decode()
|
||||
.replace('\n', ''),
|
||||
signature,
|
||||
params,
|
||||
signature_b64=transport_script.signature_b64,
|
||||
parameters=transport_script.parameters,
|
||||
)
|
||||
|
||||
def getLink(
|
||||
|
@ -39,6 +39,7 @@ from .tools import DictAsObj
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class KnownOS(enum.Enum):
|
||||
Linux = ('Linux', 'armv7l')
|
||||
ChromeOS = ('CrOS',)
|
||||
@ -51,6 +52,7 @@ class KnownOS(enum.Enum):
|
||||
WYSE = ('WYSE',)
|
||||
Unknown = ('Unknown',)
|
||||
|
||||
|
||||
knownOss = (
|
||||
KnownOS.WindowsPhone,
|
||||
KnownOS.Android,
|
||||
@ -111,12 +113,11 @@ browserRules: typing.Dict[str, typing.Tuple] = {
|
||||
|
||||
def getOsFromUA(
|
||||
ua: typing.Optional[str],
|
||||
) -> DictAsObj: # pylint: disable=too-many-branches
|
||||
) -> DictAsObj:
|
||||
"""
|
||||
Basic OS Client detector (very basic indeed :-))
|
||||
"""
|
||||
if ua is None:
|
||||
ua = KnownOS.Unknown.value[0]
|
||||
ua = ua or KnownOS.Unknown.value[0]
|
||||
|
||||
res = DictAsObj({'OS': KnownOS.Unknown, 'Version': '0.0', 'Browser': 'unknown'})
|
||||
found: bool = False
|
||||
@ -142,7 +143,7 @@ def getOsFromUA(
|
||||
# Check against no machin rules
|
||||
for mustNotREs in mustNot:
|
||||
for cre in browsersREs[mustNotREs]:
|
||||
if cre.search(ua) is not None:
|
||||
if cre.search(typing.cast(str, ua)) is not None:
|
||||
match = None
|
||||
break
|
||||
if match is None:
|
||||
|
@ -41,6 +41,7 @@ from .rdp_file import RDPFile
|
||||
# Not imported at runtime, just for type checking
|
||||
if typing.TYPE_CHECKING:
|
||||
from uds import models
|
||||
from uds.core import transports
|
||||
from uds.core.util.request import ExtendedHttpRequestWithUser
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -102,7 +103,7 @@ class RDPTransport(BaseRDPTransport):
|
||||
user: 'models.User',
|
||||
password: str,
|
||||
request: 'ExtendedHttpRequestWithUser',
|
||||
) -> typing.Tuple[str, str, typing.Mapping[str, typing.Any]]:
|
||||
) -> 'transports.TransportScript':
|
||||
# We use helper to keep this clean
|
||||
# prefs = user.prefs('rdp')
|
||||
|
||||
|
@ -61,6 +61,7 @@ class BaseRDPTransport(transports.Transport):
|
||||
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
|
||||
"""
|
||||
|
||||
isBase = True
|
||||
|
||||
iconFile = 'rdp.png'
|
||||
@ -174,12 +175,10 @@ class BaseRDPTransport(transports.Transport):
|
||||
{'id': '{4d36e979-e325-11ce-bfc1-08002be10318}', 'text': 'Printers'},
|
||||
{'id': '{50dd5230-ba8a-11d1-bf5d-0000f805f530}', 'text': 'Smartcards'},
|
||||
{'id': '{745a17a0-74d3-11d0-b6fe-00a0c90f57da}', 'text': 'HIDs'},
|
||||
|
||||
],
|
||||
tab=gui.PARAMETERS_TAB,
|
||||
)
|
||||
|
||||
|
||||
credssp = gui.CheckBoxField(
|
||||
label=_('Credssp Support'),
|
||||
order=29,
|
||||
@ -440,7 +439,7 @@ class BaseRDPTransport(transports.Transport):
|
||||
scriptNameTemplate: str,
|
||||
osName: str,
|
||||
params: typing.Mapping[str, typing.Any],
|
||||
) -> typing.Tuple[str, str, typing.Mapping[str, typing.Any]]:
|
||||
) -> transports.TransportScript:
|
||||
# Reads script
|
||||
scriptNameTemplate = scriptNameTemplate.format(osName)
|
||||
with open(os.path.join(os.path.dirname(__file__), scriptNameTemplate)) as f:
|
||||
@ -450,4 +449,9 @@ class BaseRDPTransport(transports.Transport):
|
||||
os.path.join(os.path.dirname(__file__), scriptNameTemplate + '.signature')
|
||||
) as f:
|
||||
signature = f.read()
|
||||
return script, signature, params
|
||||
return transports.TransportScript(
|
||||
script=script,
|
||||
script_type='python',
|
||||
signature_b64=signature,
|
||||
parameters=params,
|
||||
)
|
||||
|
@ -145,7 +145,7 @@ class TRDPTransport(BaseRDPTransport):
|
||||
user: 'models.User',
|
||||
password: str,
|
||||
request: 'ExtendedHttpRequestWithUser',
|
||||
) -> typing.Tuple[str, str, typing.Mapping[str, typing.Any]]:
|
||||
) -> 'transports.TransportScript':
|
||||
# We use helper to keep this clean
|
||||
# prefs = user.prefs('rdp')
|
||||
|
||||
|
@ -41,6 +41,7 @@ from .remote_viewer_file import RemoteViewerFile
|
||||
# Not imported at runtime, just for type checking
|
||||
if typing.TYPE_CHECKING:
|
||||
from uds import models
|
||||
from uds.core import transports
|
||||
from uds.core.util.request import ExtendedHttpRequestWithUser
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -75,7 +76,7 @@ class SPICETransport(BaseSpiceTransport):
|
||||
user: 'models.User',
|
||||
password: str,
|
||||
request: 'ExtendedHttpRequestWithUser',
|
||||
) -> typing.Tuple[str, str, typing.Mapping[str, typing.Any]]:
|
||||
) -> 'transports.TransportScript':
|
||||
userServiceInstance: typing.Any = userService.getInstance()
|
||||
|
||||
con = userServiceInstance.getConsoleConnection()
|
||||
|
@ -42,7 +42,6 @@ from uds.core.transports import protocols
|
||||
# Not imported at runtime, just for type checking
|
||||
if typing.TYPE_CHECKING:
|
||||
from uds import models
|
||||
from django.http import HttpRequest # pylint: disable=ungrouped-imports
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -54,6 +53,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
|
||||
"""
|
||||
|
||||
isBase = True
|
||||
|
||||
iconFile = 'spice.png'
|
||||
@ -173,7 +173,10 @@ class BaseSpiceTransport(transports.Transport):
|
||||
return v['username']
|
||||
|
||||
def processUserPassword(
|
||||
self, userService: typing.Union['models.UserService', 'models.ServicePool'], user: 'models.User', password: str
|
||||
self,
|
||||
userService: typing.Union['models.UserService', 'models.ServicePool'],
|
||||
user: 'models.User',
|
||||
password: str,
|
||||
) -> typing.Dict[str, str]:
|
||||
username = user.getUsernameForAuth()
|
||||
|
||||
@ -201,7 +204,7 @@ class BaseSpiceTransport(transports.Transport):
|
||||
|
||||
def getScript(
|
||||
self, scriptNameTemplate: str, osName: str, params: typing.Dict[str, typing.Any]
|
||||
) -> typing.Tuple[str, str, typing.Dict[str, typing.Any]]:
|
||||
) -> transports.TransportScript:
|
||||
# Reads script
|
||||
scriptNameTemplate = scriptNameTemplate.format(osName)
|
||||
with open(os.path.join(os.path.dirname(__file__), scriptNameTemplate)) as f:
|
||||
@ -211,4 +214,9 @@ class BaseSpiceTransport(transports.Transport):
|
||||
os.path.join(os.path.dirname(__file__), scriptNameTemplate + '.signature')
|
||||
) as f:
|
||||
signature = f.read()
|
||||
return script, signature, params
|
||||
return transports.TransportScript(
|
||||
script=script,
|
||||
script_type='python',
|
||||
signature_b64=signature,
|
||||
parameters=params,
|
||||
)
|
||||
|
@ -115,7 +115,7 @@ class TSPICETransport(BaseSpiceTransport):
|
||||
user: 'models.User',
|
||||
password: str,
|
||||
request: 'ExtendedHttpRequestWithUser',
|
||||
) -> typing.Tuple[str, str, typing.Mapping[str, typing.Any]]:
|
||||
) -> transports.TransportScript:
|
||||
userServiceInstance: typing.Any = userService.getInstance()
|
||||
|
||||
# Spice connection
|
||||
|
@ -41,6 +41,7 @@ from . import x2go_file
|
||||
# Not imported at runtime, just for type checking
|
||||
if typing.TYPE_CHECKING:
|
||||
from uds import models
|
||||
from uds.core import transports
|
||||
from uds.core.util.request import ExtendedHttpRequestWithUser
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -79,7 +80,7 @@ class X2GOTransport(BaseX2GOTransport):
|
||||
user: 'models.User',
|
||||
password: str,
|
||||
request: 'ExtendedHttpRequestWithUser',
|
||||
) -> typing.Tuple[str, str, typing.Mapping[str, typing.Any]]:
|
||||
) -> 'transports.TransportScript':
|
||||
ci = self.getConnectionInfo(userService, user, password)
|
||||
username = ci['username']
|
||||
|
||||
|
@ -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
|
||||
"""
|
||||
|
||||
isBase = True
|
||||
|
||||
iconFile = 'x2go.png'
|
||||
@ -287,7 +288,7 @@ class BaseX2GOTransport(transports.Transport):
|
||||
|
||||
def getScript(
|
||||
self, scriptNameTemplate: str, osName: str, params: typing.Dict[str, typing.Any]
|
||||
) -> typing.Tuple[str, str, typing.Dict[str, typing.Any]]:
|
||||
) -> 'transports.TransportScript':
|
||||
# Reads script
|
||||
scriptNameTemplate = scriptNameTemplate.format(osName)
|
||||
with open(os.path.join(os.path.dirname(__file__), scriptNameTemplate)) as f:
|
||||
@ -297,4 +298,9 @@ class BaseX2GOTransport(transports.Transport):
|
||||
os.path.join(os.path.dirname(__file__), scriptNameTemplate + '.signature')
|
||||
) as f:
|
||||
signature = f.read()
|
||||
return script, signature, params
|
||||
return transports.TransportScript(
|
||||
script=script,
|
||||
script_type='python',
|
||||
signature_b64=signature,
|
||||
parameters=params,
|
||||
)
|
||||
|
@ -122,7 +122,7 @@ class TX2GOTransport(BaseX2GOTransport):
|
||||
user: 'models.User',
|
||||
password: str,
|
||||
request: 'ExtendedHttpRequestWithUser',
|
||||
) -> typing.Tuple[str, str, typing.Mapping[str, typing.Any]]:
|
||||
) -> 'transports.TransportScript':
|
||||
|
||||
ci = self.getConnectionInfo(userService, user, password)
|
||||
username = ci['username']
|
||||
|
Loading…
Reference in New Issue
Block a user