forked from shaba/openuds
Fixed connection client working
This commit is contained in:
parent
9a7afe7839
commit
e920628395
@ -243,6 +243,7 @@ class Handler:
|
||||
session.save()
|
||||
self._authToken = session.session_key
|
||||
self._session = session
|
||||
|
||||
return self._authToken
|
||||
|
||||
def cleanAuthToken(self) -> None:
|
||||
|
@ -39,7 +39,7 @@ from uds.REST import RequestError
|
||||
from uds.core.managers import userServiceManager
|
||||
from uds.core.managers import cryptoManager
|
||||
from uds.core.services.exceptions import ServiceNotReadyError
|
||||
from uds.web.util import errors
|
||||
from uds.web.util import errors, services
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -50,17 +50,18 @@ class Connection(Handler):
|
||||
"""
|
||||
Processes actor requests
|
||||
"""
|
||||
authenticated = True # Actor requests are not authenticated
|
||||
|
||||
authenticated = True # Connection requests are authenticated
|
||||
needs_admin = False
|
||||
needs_staff = False
|
||||
|
||||
@staticmethod
|
||||
def result(
|
||||
result: typing.Any = None,
|
||||
error: typing.Optional[typing.Union[str, int]] = None,
|
||||
errorCode: int = 0,
|
||||
retryable: bool = False
|
||||
) -> typing.Dict[str, typing.Any]:
|
||||
result: typing.Any = None,
|
||||
error: typing.Optional[typing.Union[str, int]] = None,
|
||||
errorCode: int = 0,
|
||||
retryable: bool = False,
|
||||
) -> typing.Dict[str, typing.Any]:
|
||||
"""
|
||||
Helper method to create a "result" set for connection response
|
||||
:param result: Result value to return (can be None, in which case it is converted to empty string '')
|
||||
@ -83,33 +84,44 @@ class Connection(Handler):
|
||||
|
||||
def serviceList(self):
|
||||
# We look for services for this authenticator groups. User is logged in in just 1 authenticator, so his groups must coincide with those assigned to ds
|
||||
from uds.web.util.services import getServicesData
|
||||
|
||||
# Ensure user is present on request, used by web views methods
|
||||
self._request.user = self._user
|
||||
self._request.user = self._user # type: ignore
|
||||
|
||||
return Connection.result(result=getServicesData(self._request))
|
||||
return Connection.result(result=services.getServicesData(self._request))
|
||||
|
||||
def connection(self, doNotCheck: bool = False):
|
||||
idService = self._args[0]
|
||||
idTransport = self._args[1]
|
||||
try:
|
||||
ip, userService, iads, trans, itrans = userServiceManager().getService( # pylint: disable=unused-variable
|
||||
self._user, self._request.os, self._request.ip, idService, idTransport, not doNotCheck
|
||||
(
|
||||
ip,
|
||||
userService,
|
||||
iads,
|
||||
trans,
|
||||
itrans,
|
||||
) = userServiceManager().getService( # pylint: disable=unused-variable
|
||||
self._user,
|
||||
self._request.os, # type: ignore
|
||||
self._request.ip, # type: ignore
|
||||
idService,
|
||||
idTransport,
|
||||
not doNotCheck,
|
||||
)
|
||||
ci = {
|
||||
'username': '',
|
||||
'password': '',
|
||||
'domain': '',
|
||||
'protocol': 'unknown',
|
||||
'ip': ip
|
||||
'ip': ip,
|
||||
}
|
||||
if itrans: # only will be available id doNotCheck is False
|
||||
ci.update(itrans.getConnectionInfo(userService, self._user, 'UNKNOWN'))
|
||||
return Connection.result(result=ci)
|
||||
except ServiceNotReadyError as e:
|
||||
# Refresh ticket and make this retrayable
|
||||
return Connection.result(error=errors.SERVICE_IN_PREPARATION, errorCode=e.code, retryable=True)
|
||||
return Connection.result(
|
||||
error=errors.SERVICE_IN_PREPARATION, errorCode=e.code, retryable=True
|
||||
)
|
||||
except Exception as e:
|
||||
logger.exception("Exception")
|
||||
return Connection.result(error=str(e))
|
||||
@ -122,23 +134,59 @@ class Connection(Handler):
|
||||
hostname = self._args[3]
|
||||
|
||||
try:
|
||||
res = userServiceManager().getService(self._user, self._request.os, self._request.ip, idService, idTransport)
|
||||
res = userServiceManager().getService(
|
||||
self._user, self._request.os, self._request.ip, idService, idTransport # type: ignore
|
||||
)
|
||||
logger.debug('Res: %s', res)
|
||||
ip, userService, userServiceInstance, transport, transportInstance = res # pylint: disable=unused-variable
|
||||
(
|
||||
ip,
|
||||
userService,
|
||||
userServiceInstance,
|
||||
transport,
|
||||
transportInstance,
|
||||
) = res # pylint: disable=unused-variable
|
||||
password = cryptoManager().symDecrpyt(self.getValue('password'), scrambler)
|
||||
|
||||
userService.setConnectionSource(self._request.ip, hostname) # Store where we are accessing from so we can notify Service
|
||||
userService.setConnectionSource(
|
||||
self._request.ip, hostname # type: ignore
|
||||
) # Store where we are accessing from so we can notify Service
|
||||
|
||||
transportScript = transportInstance.getEncodedTransportScript(userService, transport, ip, self._request.os, self._user, password, self._request)
|
||||
if not ip:
|
||||
raise ServiceNotReadyError()
|
||||
|
||||
transportScript = transportInstance.getEncodedTransportScript(
|
||||
userService,
|
||||
transport,
|
||||
ip,
|
||||
self._request.os, # type: ignore
|
||||
self._user,
|
||||
password,
|
||||
self._request,
|
||||
)
|
||||
|
||||
return Connection.result(result=transportScript)
|
||||
except ServiceNotReadyError as e:
|
||||
# Refresh ticket and make this retrayable
|
||||
return Connection.result(error=errors.SERVICE_IN_PREPARATION, errorCode=e.code, retryable=True)
|
||||
return Connection.result(
|
||||
error=errors.SERVICE_IN_PREPARATION, errorCode=e.code, retryable=True
|
||||
)
|
||||
except Exception as e:
|
||||
logger.exception("Exception")
|
||||
return Connection.result(error=str(e))
|
||||
|
||||
def getTicketContent(self):
|
||||
return {} # TODO: use this for something?
|
||||
|
||||
def getUdsLink(self):
|
||||
# Returns the UDS link for the user & transport
|
||||
self._request.user = self._user # type: ignore
|
||||
self._request._cryptedpass = self._session['REST']['password'] # type: ignore
|
||||
self._request._scrambler = self._request.META['HTTP_SCRAMBLER'] # type: ignore
|
||||
linkInfo = services.enableService(self._request, idService=self._args[0], idTransport=self._args[1])
|
||||
if linkInfo['error']:
|
||||
return Connection.result(error=linkInfo['error'])
|
||||
return Connection.result(result=linkInfo['url'])
|
||||
|
||||
def get(self):
|
||||
"""
|
||||
Processes get requests
|
||||
@ -157,9 +205,12 @@ class Connection(Handler):
|
||||
return self.connection()
|
||||
|
||||
if len(self._args) == 3:
|
||||
# /connection/idService/idTransport/skipChecking
|
||||
if self._args[2] == 'skipChecking':
|
||||
# /connection/idService/idTransport/skipcheck
|
||||
if self._args[2] == 'skipcheck':
|
||||
return self.connection(True)
|
||||
# /connection/idService/idTransport/udslink
|
||||
elif self._args[2] == 'udslink':
|
||||
return self.getUdsLink()
|
||||
|
||||
if len(self._args) == 4:
|
||||
# /connection/idService/idTransport/scrambler/hostname
|
||||
|
@ -311,7 +311,11 @@ def webPassword(request: HttpRequest) -> str:
|
||||
session (db) and client browser cookies. This method uses this two values to recompose the user password
|
||||
so we can provide it to remote sessions.
|
||||
"""
|
||||
return cryptoManager().symDecrpyt(request.session.get(PASS_KEY, ''), getUDSCookie(request)) # recover as original unicode string
|
||||
if hasattr(request, 'session'):
|
||||
return cryptoManager().symDecrpyt(request.session.get(PASS_KEY, ''), getUDSCookie(request)) # recover as original unicode string
|
||||
else: # No session, get from _session instead, this is an "client" REST request
|
||||
return cryptoManager().symDecrpyt(request._cryptedpass, request._scrambler) # type: ignore
|
||||
|
||||
|
||||
|
||||
def webLogout(request: HttpRequest, exit_url: typing.Optional[str] = None) -> HttpResponse:
|
||||
|
@ -28,6 +28,7 @@
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
import json
|
||||
import logging
|
||||
import typing
|
||||
|
||||
@ -35,15 +36,19 @@ from django.utils.translation import ugettext
|
||||
from django.utils import formats
|
||||
from django.urls import reverse
|
||||
|
||||
from uds.models import ServicePool, Transport, Network, ServicePoolGroup, MetaPool, getSqlDatetime
|
||||
|
||||
from uds.models import ServicePool, Transport, Network, ServicePoolGroup, MetaPool, getSqlDatetime, TicketStore
|
||||
from uds.core.util.config import GlobalConfig
|
||||
from uds.core.services.exceptions import ServiceNotReadyError, MaxServicesReachedError, ServiceAccessDeniedByCalendar
|
||||
from uds.core.auths.auth import webPassword
|
||||
from uds.web.util import errors
|
||||
from uds.core.util import html
|
||||
|
||||
from uds.core.managers import userServiceManager
|
||||
from uds.core.managers import userServiceManager, cryptoManager
|
||||
|
||||
# Not imported at runtime, just for type checking
|
||||
if typing.TYPE_CHECKING:
|
||||
from django.http import HttpRequest # pylint: disable=ungrouped-imports
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -242,3 +247,54 @@ def getServicesData(request: 'HttpRequest') -> typing.Dict[str, typing.Any]: #
|
||||
'transports': validTrans,
|
||||
'autorun': autorun
|
||||
}
|
||||
|
||||
def enableService(request: 'HttpRequest', idService: str, idTransport: str) -> typing.Mapping[str, typing.Any]:
|
||||
# Maybe we could even protect this even more by limiting referer to own server /? (just a meditation..)
|
||||
logger.debug('idService: %s, idTransport: %s', idService, idTransport)
|
||||
url = ''
|
||||
error = ugettext('Service not ready. Please, try again in a while.')
|
||||
|
||||
# If meta service, process and rebuild idService & idTransport
|
||||
|
||||
try:
|
||||
res = userServiceManager().getService(request.user, request.os, request.ip, idService, idTransport, doTest=False)
|
||||
scrambler = cryptoManager().randomString(32)
|
||||
password = cryptoManager().symCrypt(webPassword(request), scrambler)
|
||||
|
||||
userService, trans = res[1], res[3]
|
||||
|
||||
typeTrans = trans.getType()
|
||||
|
||||
error = '' # No error
|
||||
|
||||
if typeTrans.ownLink:
|
||||
url = reverse('TransportOwnLink', args=('A' + userService.uuid, trans.uuid))
|
||||
else:
|
||||
data = {
|
||||
'service': 'A' + userService.uuid,
|
||||
'transport': trans.uuid,
|
||||
'user': request.user.uuid,
|
||||
'password': password
|
||||
}
|
||||
|
||||
ticket = TicketStore.create(data)
|
||||
url = html.udsLink(request, ticket, scrambler)
|
||||
except ServiceNotReadyError as e:
|
||||
logger.debug('Service not ready')
|
||||
# Not ready, show message and return to this page in a while
|
||||
# error += ' (code {0:04X})'.format(e.code)
|
||||
error = ugettext('Your service is being created, please, wait for a few seconds while we complete it.)') + '({}%)'.format(int(e.code * 25))
|
||||
except MaxServicesReachedError:
|
||||
logger.info('Number of service reached MAX for service pool "%s"', idService)
|
||||
error = errors.errorString(errors.MAX_SERVICES_REACHED)
|
||||
except ServiceAccessDeniedByCalendar:
|
||||
logger.info('Access tried to a calendar limited access pool "%s"', idService)
|
||||
error = errors.errorString(errors.SERVICE_CALENDAR_DENIED)
|
||||
except Exception as e:
|
||||
logger.exception('Error')
|
||||
error = str(e)
|
||||
|
||||
return {
|
||||
'url': str(url),
|
||||
'error': str(error)
|
||||
}
|
||||
|
@ -33,18 +33,16 @@ import logging
|
||||
import typing
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.urls import reverse
|
||||
from django.http import HttpResponse
|
||||
from django.views.decorators.cache import cache_page, never_cache
|
||||
|
||||
from uds.core.auths.auth import webLoginRequired, webPassword
|
||||
from uds.core.managers import userServiceManager, cryptoManager
|
||||
from uds.models import TicketStore
|
||||
from uds.core.managers import userServiceManager
|
||||
from uds.core.ui.images import DEFAULT_IMAGE
|
||||
from uds.core.util.model import processUuid
|
||||
from uds.models import Transport, Image
|
||||
from uds.core.util import html, log
|
||||
from uds.core.services.exceptions import ServiceNotReadyError, MaxServicesReachedError, ServiceAccessDeniedByCalendar
|
||||
from uds.core.util import log
|
||||
from uds.core.services.exceptions import ServiceNotReadyError
|
||||
|
||||
from uds.web.util import errors
|
||||
from uds.web.util import services
|
||||
@ -113,58 +111,11 @@ def serviceImage(request: 'HttpRequest', idImage: str) -> HttpResponse:
|
||||
@webLoginRequired(admin=False)
|
||||
@never_cache
|
||||
def userServiceEnabler(request: 'HttpRequest', idService: str, idTransport: str) -> HttpResponse:
|
||||
# Maybe we could even protect this even more by limiting referer to own server /? (just a meditation..)
|
||||
logger.debug('idService: %s, idTransport: %s', idService, idTransport)
|
||||
url = ''
|
||||
error = _('Service not ready. Please, try again in a while.')
|
||||
|
||||
# If meta service, process and rebuild idService & idTransport
|
||||
|
||||
try:
|
||||
res = userServiceManager().getService(request.user, request.os, request.ip, idService, idTransport, doTest=False)
|
||||
scrambler = cryptoManager().randomString(32)
|
||||
password = cryptoManager().symCrypt(webPassword(request), scrambler)
|
||||
|
||||
userService, trans = res[1], res[3]
|
||||
|
||||
typeTrans = trans.getType()
|
||||
|
||||
error = '' # No error
|
||||
|
||||
if typeTrans.ownLink:
|
||||
url = reverse('TransportOwnLink', args=('A' + userService.uuid, trans.uuid))
|
||||
else:
|
||||
data = {
|
||||
'service': 'A' + userService.uuid,
|
||||
'transport': trans.uuid,
|
||||
'user': request.user.uuid,
|
||||
'password': password
|
||||
}
|
||||
|
||||
ticket = TicketStore.create(data)
|
||||
url = html.udsLink(request, ticket, scrambler)
|
||||
except ServiceNotReadyError as e:
|
||||
logger.debug('Service not ready')
|
||||
# Not ready, show message and return to this page in a while
|
||||
# error += ' (code {0:04X})'.format(e.code)
|
||||
error = _('Your service is being created, please, wait for a few seconds while we complete it.)') + '({}%)'.format(int(e.code * 25))
|
||||
except MaxServicesReachedError:
|
||||
logger.info('Number of service reached MAX for service pool "%s"', idService)
|
||||
error = errors.errorString(errors.MAX_SERVICES_REACHED)
|
||||
except ServiceAccessDeniedByCalendar:
|
||||
logger.info('Access tried to a calendar limited access pool "%s"', idService)
|
||||
error = errors.errorString(errors.SERVICE_CALENDAR_DENIED)
|
||||
except Exception as e:
|
||||
logger.exception('Error')
|
||||
error = str(e)
|
||||
|
||||
return HttpResponse(
|
||||
json.dumps({
|
||||
'url': str(url),
|
||||
'error': str(error)
|
||||
}),
|
||||
json.dumps(services.enableService(request, idService=idService, idTransport=idTransport)),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
|
||||
def closer(request: 'HttpRequest') -> HttpResponse:
|
||||
return HttpResponse('<html><body onload="window.close()"></body></html>')
|
||||
|
Loading…
Reference in New Issue
Block a user