1
0
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:
Adolfo Gómez García 2022-08-27 19:09:12 +02:00
parent d0e9c96573
commit 5f93b68c25
13 changed files with 78 additions and 50 deletions

View File

@ -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:

View File

@ -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

View File

@ -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(

View File

@ -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:

View File

@ -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')

View File

@ -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,
)

View File

@ -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')

View File

@ -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()

View File

@ -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,
)

View File

@ -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

View File

@ -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']

View File

@ -60,6 +60,7 @@ class BaseX2GOTransport(transports.Transport):
Provides access via X2GO to service.
This transport can use an domain. If username processed by authenticator contains '@', it will split it and left-@-part will be username, and right password
"""
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,
)

View File

@ -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']