def getLink(self, userService, transport, ip, os, user, password, request): ci = self.processUserPassword(userService, user, password) username, password, domain = ci['username'], ci['password'], ci['domain'] if domain != '': username = domain + '\\' + username # Build params dict params = { 'protocol': 'rdp', 'hostname': ip, 'username': username, 'password': password, 'ignore-cert': 'true' } if self.enableAudio.isTrue() is False: params['disable-audio'] = 'true' if self.enablePrinting.isTrue() is True: params['enable-printing'] = 'true' logger.debug('RDP Params: {0}'.format(params)) ticket = TicketStore.create(params) return HttpResponseRedirect("{}/transport/?{}&{}".format(self.guacamoleServer.value, ticket, request.build_absolute_uri(reverse('Index'))))
def getUDSTransportScript(self, userService, transport, ip, os, user, password, request): prefs = user.prefs('nx') username = user.getUsernameForAuth() proc = username.split('@') username = proc[0] if self._fixedName is not '': username = self._fixedName if self._fixedPassword is not '': password = self._fixedPassword if self._useEmptyCreds is True: username, password = '', '' tunpass = ''.join(random.choice(string.letters + string.digits) for _i in range(12)) tunuser = TicketStore.create(tunpass) sshServer = self._tunnelServer if ':' not in sshServer: sshServer += ':443' sshHost, sshPort = sshServer.split(':') logger.debug('Username generated: {0}, password: {1}'.format(tunuser, tunpass)) width, height = CommonPrefs.getWidthHeight(prefs) # Fix username/password acording to os manager username, password = userService.processUserPassword(username, password) m = { 'ip': ip, 'tunUser': tunuser, 'tunPass': tunpass, 'tunHost': sshHost, 'tunPort': sshPort, 'password': password, 'port': self._listenPort } r = NXFile(username=username, password=password, width=width, height=height) r.host = '{address}' r.port = '{port}' r.connection = self._connection r.desktop = self._session r.cachedisk = self._cacheDisk r.cachemem = self._cacheMem os = { OsDetector.Windows: 'windows', OsDetector.Linux: 'linux', OsDetector.Macintosh: 'macosx' }.get(os['OS']) if os is None: return super(self.__class__, self).getUDSTransportScript(userService, transport, ip, os, user, password, request) return self.getScript('scripts/{}/tunnel.py'.format(os)).format( r=r, m=DictAsObj(m), )
def getUDSTransportScript(self, userService, transport, ip, os, user, password, request): prefs = user.prefs('nx') username = user.getUsernameForAuth() proc = username.split('@') username = proc[0] if self._fixedName is not '': username = self._fixedName if self._fixedPassword is not '': password = self._fixedPassword if self._useEmptyCreds is True: username, password = '', '' tunpass = ''.join(random.choice(string.letters + string.digits) for _i in range(12)) tunuser = TicketStore.create(tunpass) sshServer = self._tunnelServer if ':' not in sshServer: sshServer += ':443' sshHost, sshPort = sshServer.split(':') logger.debug('Username generated: {0}, password: {1}'.format(tunuser, tunpass)) width, height = CommonPrefs.getWidthHeight(prefs) # Fix username/password acording to os manager username, password = userService.processUserPassword(username, password) m = { 'ip': ip, 'tunUser': tunuser, 'tunPass': tunpass, 'tunHost': sshHost, 'tunPort': sshPort, 'password': password, 'port': self._listenPort } r = NXFile(username=username, password=password, width=width, height=height) r.host = '{address}' r.port = '{port}' r.connection = self._connection r.desktop = self._session r.cachedisk = self._cacheDisk r.cachemem = self._cacheMem os = { OsDetector.Windows: 'windows', OsDetector.Linux: 'linux', OsDetector.Macintosh: 'macosx' }.get(os['OS']) if os is None: return super(TSNXTransport, self).getUDSTransportScript(self, userService, transport, ip, os, user, password, request) return self.getScript('scripts/{}/tunnel.py'.format(os)).format( r=r, m=DictAsObj(m), )
def authCallback(request: HttpRequest, authName: str) -> HttpResponse: """ This url is provided so external SSO authenticators can get an url for redirecting back the users. This will invoke authCallback of the requested idAuth and, if this represents an authenticator that has an authCallback """ try: authenticator = Authenticator.objects.get(name=authName) params = request.GET.copy() params.update(request.POST) logger.debug('Auth callback for %s with params %s', authenticator, params.keys()) ticket = TicketStore.create({ 'params': params, 'auth': authenticator.uuid }) return HttpResponseRedirect( reverse('page.auth.callback_stage2', args=[ticket])) except Exception as e: # No authenticator found... return errors.exceptionView(request, e)
def clientEnabler(request, idService, idTransport): # Maybe we could even protect this even more by limiting referer to own server /? (just a meditation..) url = '' error = _('Service not ready. Please, try again in a while.') try: res = getService(request, idService, idTransport, doTest=False) if res is not None: scrambler = cryptoManager().randomString(32) password = cryptoManager().xor(webPassword(request), scrambler) _x, ads, _x, trans, _x = res data = { 'service': 'A' + ads.uuid, 'transport': trans.uuid, 'user': request.user.uuid, 'password': password } ticket = TicketStore.create(data) error = '' url = html.udsLink(request, ticket, scrambler) except Exception as e: error = six.text_type(e) # Not ready, show message and return to this page in a while return HttpResponse('{{ "url": "{}", "error": "{}" }}'.format(url, error), content_type='application/json')
def action(self) -> typing.MutableMapping[str, typing.Any]: logger.debug('Args: %s, Params: %s', self._args, self._params) try: return ActorV3Action.actorResult(TicketStore.get(self._params['ticket'], invalidate=True)) except TicketStore.DoesNotExist: raise BlockAccess() # If too many blocks...
def getLink(self, userService, transport, ip, os, user, password, request): ci = self.processUserPassword(userService, user, password) username, password, domain = ci['username'], ci['password'], ci[ 'domain'] if domain != '': username = domain + '\\' + username # Build params dict params = { 'protocol': 'rdp', 'hostname': ip, 'username': username, 'password': password, 'ignore-cert': 'true' } if self.enableAudio.isTrue() is False: params['disable-audio'] = 'true' if self.enablePrinting.isTrue() is True: params['enable-printing'] = 'true' logger.debug('RDP Params: {0}'.format(params)) ticket = TicketStore.create(params) return HttpResponseRedirect("{}/transport/?{}&{}".format( self.guacamoleServer.value, ticket, request.build_absolute_uri(reverse('Index'))))
def pam(request): response = '' if request.method == 'POST': return HttpResponseNotAllowed(['GET']) if 'id' in request.GET and 'pass' in request.GET: # This is an "auth" request ids = request.GET.getlist('id') response = '0' if len(ids) == 1: userId = ids[0] logger.debug("Auth request for user [{0}] and pass [{1}]".format(request.GET['id'], request.GET['pass'])) try: password = TicketStore.get(userId) if password == request.GET['pass']: response = '1' except Exception: # Non existing ticket, log it and stop logger.info('Invalid access from {} using user {}'.format(request.ip, userId)) else: logger.warn('Invalid request from {}: {}'.format(request.ip, [v for v in request.GET.lists()])) elif 'uid' in request.GET: # This is an "get name for id" call logger.debug("NSS Request for id [{0}]".format(request.GET['uid'])) response = '10000 udstmp' elif 'name' in request.GET: logger.debug("NSS Request for username [{0}]".format(request.GET['name'])) response = '10000 udstmp' return HttpResponse(response, content_type='text/plain')
def enableService(request: 'ExtendedHttpRequestWithUser', 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)}
def getUDSTransportScript( # pylint: disable=too-many-locals self, userService: 'models.UserService', transport: 'models.Transport', ip: str, os: typing.Dict[str, str], user: '******', password: str, request: 'HttpRequest' ) -> typing.Tuple[str, str, typing.Dict[str, typing.Any]]: userServiceInstance: typing.Any = userService.getInstance() # Spice connection con = userServiceInstance.getConsoleConnection() port: str = con['port'] or '-1' secure_port: str = con['secure_port'] or '-1' # Ticket tunpass = ''.join(random.SystemRandom().choice(string.letters + string.digits) for _i in range(12)) tunuser = TicketStore.create(tunpass) sshHost, sshPort = self.tunnelServer.value.split(':') r = RemoteViewerFile('127.0.0.1', '{port}', '{secure_port}', con['ticket']['value'], self.serverCertificate.value.strip(), con['cert_subject'], fullscreen=self.fullScreen.isTrue()) r.usb_auto_share = self.usbShare.isTrue() r.new_usb_auto_share = self.autoNewUsbShare.isTrue() r.smartcard = self.smartCardRedirect.isTrue() osName = { OsDetector.Windows: 'windows', OsDetector.Linux: 'linux', OsDetector.Macintosh: 'macosx' }.get(os['OS']) if osName is None: return super().getUDSTransportScript(userService, transport, ip, os, user, password, request) # if sso: # If SSO requested, and when supported by platform # userServiceInstance.desktopLogin(user, password, '') sp = { 'as_file': r.as_file, 'as_file_ns': r.as_file_ns, 'tunUser': tunuser, 'tunPass': tunpass, 'tunHost': sshHost, 'tunPort': sshPort, 'ip': con['address'], 'port': port, 'secure_port': secure_port } return self.getScript('scripts/{}/tunnel.py', osName, sp)
def guacamole(request, tunnelId): logger.debug('Received credentials request for tunnel id {0}'.format(tunnelId)) try: val = TicketStore.get(tunnelId, invalidate=False) response = dict2resp(val) except Exception: return HttpResponse(ERROR, content_type=CONTENT_TYPE) return HttpResponse(response, content_type=CONTENT_TYPE)
def userServiceEnabler(request, idService, idTransport): # Maybe we could even protect this even more by limiting referer to own server /? (just a meditation..) logger.debug('idService: {}, idTransport: {}'.format( 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) _x, userService, _x, trans, _x = res data = { 'service': 'A' + userService.uuid, 'transport': trans.uuid, 'user': request.user.uuid, 'password': password } ticket = TicketStore.create(data) error = '' 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) except MaxServicesReachedError: logger.info( 'Number of service reached MAX for service pool "{}"'.format( idService)) error = errors.errorString(errors.MAX_SERVICES_REACHED) except ServiceAccessDeniedByCalendar: logger.info( 'Access tried to a calendar limited access pool "{}"'.format( 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) }), content_type='application/json')
def getUDSTransportScript(self, userService, transport, ip, os, user, password, request): userServiceInstance = userService.getInstance() # Spice connection con = userServiceInstance.getConsoleConnection() port, secure_port = con['port'], con['secure_port'] port = -1 if port is None else port secure_port = -1 if secure_port is None else secure_port # Ticket tunpass = ''.join(random.SystemRandom().choice(string.letters + string.digits) for _i in range(12)) tunuser = TicketStore.create(tunpass) sshHost, sshPort = self.tunnelServer.value.split(':') r = RemoteViewerFile('127.0.0.1', '{port}', '{secure_port}', con['ticket']['value'], self.serverCertificate.value, con['cert_subject'], fullscreen=self.fullScreen.isTrue()) r.usb_auto_share = self.usbShare.isTrue() r.new_usb_auto_share = self.autoNewUsbShare.isTrue() r.smartcard = self.smartCardRedirect.isTrue() m = tools.DictAsObj({ 'r': r, 'tunUser': tunuser, 'tunPass': tunpass, 'tunHost': sshHost, 'tunPort': sshPort, 'ip': con['address'], 'port': port, 'secure_port': secure_port }) os = { OsDetector.Windows: 'windows', OsDetector.Linux: 'linux', OsDetector.Macintosh: 'macosx' }.get(os.OS) if os is None: return super(self.__class__, self).getUDSTransportScript(userService, transport, ip, os, user, password, request) return self.getScript('scripts/{}/tunnel.py'.format(os)).format(m=m)
def guacamole(request, tunnelId): logger.debug( 'Received credentials request for tunnel id {0}'.format(tunnelId)) try: val = TicketStore.get(tunnelId, invalidate=False) response = dict2resp(val) except Exception: return HttpResponse(ERROR, content_type=CONTENT_TYPE) return HttpResponse(response, content_type=CONTENT_TYPE)
def action(self) -> typing.MutableMapping[str, typing.Any]: logger.debug('Args: %s, Params: %s', self._args, self._params) try: # Simple check that token exists ActorToken.objects.get(token=self._params['token']) # Not assigned, because only needs check except ActorToken.DoesNotExist: raise BlockAccess() # If too many blocks... try: return ActorV3Action.actorResult(TicketStore.get(self._params['ticket'], invalidate=True)) except TicketStore.DoesNotExists: return ActorV3Action.actorResult(error='Invalid ticket')
def getLink(self, userService, transport, ip, os, user, password, request): ci = self.processUserPassword(userService, user, password) username, password, domain = ci['username'], ci['password'], ci[ 'domain'] if domain != '': username = domain + '\\' + username scrambler = cryptoManager().randomString(32) passwordCrypted = cryptoManager().symCrypt(password, scrambler) # Build params dict params = { 'protocol': 'rdp', 'hostname': ip, 'username': username, 'password': passwordCrypted, 'ignore-cert': 'true', 'security': self.security.value, 'drive-path': '/share/{}'.format(user.uuid), 'create-drive-path': 'true' } if self.enableFileSharing.isTrue(): params['enable-drive'] = 'true' if self.serverLayout.value != '-': params['server-layout'] = self.serverLayout.value if self.enableAudio.isTrue() is False: params['disable-audio'] = 'true' if self.enablePrinting.isTrue() is True: params['enable-printing'] = 'true' if self.wallpaper.isTrue() is True: params['enable-wallpaper'] = 'true' if self.desktopComp.isTrue() is True: params['enable-desktop-composition'] = 'true' if self.smooth.isTrue() is True: params['enable-font-smoothing'] = 'true' logger.debug('RDP Params: {0}'.format(params)) ticket = TicketStore.create(params, validity=self.ticketValidity.num()) return HttpResponseRedirect("{}/transport/?{}.{}&{}".format( self.guacamoleServer.value, ticket, scrambler, request.build_absolute_uri(reverse('Index'))))
def getTicket(self): ''' Processes get requests in order to obtain a ticket content GET /rest/actor/ticket/[ticketId] ''' logger.debug("Ticket args for GET: {0}".format(self._args)) if len(self._args) != 2: raise RequestError('Invalid request') try: return Actor.result(TicketStore.get(self._args[1], invalidate=True)) except Exception: return Actor.result({})
def guacamole(request, tunnelId): logger.debug('Received credentials request for tunnel id {0}'.format(tunnelId)) tunnelId, scrambler = tunnelId.split('.') try: val = TicketStore.get(tunnelId, invalidate=False) val['password'] = cryptoManager().symDecrpyt(val['password'], scrambler) response = dict2resp(val) except Exception: logger.error('Invalid guacamole ticket (F5 on client?): {}'.format(tunnelId)) return HttpResponse(ERROR, content_type=CONTENT_TYPE) return HttpResponse(response, content_type=CONTENT_TYPE)
def getLink(self, userService, transport, ip, os, user, password, request): ci = self.processUserPassword(userService, user, password) username, password, domain = ci['username'], ci['password'], ci['domain'] if domain != '': username = domain + '\\' + username scrambler = cryptoManager().randomString(32) passwordCrypted = cryptoManager().symCrypt(password, scrambler) # Build params dict params = { 'protocol': 'rdp', 'hostname': ip, 'username': username, 'password': passwordCrypted, 'ignore-cert': 'true', 'security': self.security.value, 'drive-path': '/share/{}'.format(user.uuid), 'create-drive-path': 'true' } if self.enableFileSharing.isTrue(): params['enable-drive'] = 'true' if self.serverLayout.value != '-': params['server-layout'] = self.serverLayout.value if self.enableAudio.isTrue() is False: params['disable-audio'] = 'true' if self.enablePrinting.isTrue() is True: params['enable-printing'] = 'true' if self.wallpaper.isTrue() is True: params['enable-wallpaper'] = 'true' if self.desktopComp.isTrue() is True: params['enable-desktop-composition'] = 'true' if self.smooth.isTrue() is True: params['enable-font-smoothing'] = 'true' logger.debug('RDP Params: {0}'.format(params)) ticket = TicketStore.create(params, validity=self.ticketValidity.num()) return HttpResponseRedirect("{}/transport/?{}.{}&{}".format(self.guacamoleServer.value, ticket, scrambler, request.build_absolute_uri(reverse('utility.closer'))))
def getTicket(self): ''' Processes get requests in order to obtain a ticket content GET /rest/actor/ticket/[ticketId]?key=masterKey&[secure=true|1|false|0] ''' logger.debug("Ticket args for GET: {0}".format(self._args)) secure = self._params.get('secure') in ('1', 'true') if len(self._args) != 2: raise RequestError('Invalid request') try: return Actor.result(TicketStore.get(self._args[1], invalidate=True, owner=SECURE_OWNER if secure else OWNER)) except Exception: return Actor.result({})
def guacamole(request: HttpRequest, tunnelId: str) -> HttpResponse: logger.debug('Received credentials request for tunnel id %s', tunnelId) tunnelId, scrambler = tunnelId.split('.') try: val = TicketStore.get(tunnelId, invalidate=False) val['password'] = cryptoManager().symDecrpyt(val['password'], scrambler) response = dict2resp(val) except Exception: logger.error('Invalid guacamole ticket (F5 on client?): %s', tunnelId) return HttpResponse(ERROR, content_type=CONTENT_TYPE) return HttpResponse(response, content_type=CONTENT_TYPE)
def get(self): ''' Processes get requests ''' logger.debug("Client args for GET: {0}".format(self._args)) if len(self._args) == 0: url = self._request.build_absolute_uri(reverse('ClientDownload')) return Client.result({ 'availableVersion': CLIENT_VERSION, 'requiredVersion': REQUIRED_CLIENT_VERSION, 'downloadUrl': url }) if len(self._args) == 1: return Client.result(_('Correct')) try: ticket, scrambler = self._args except Exception: raise RequestError('Invalid request') try: data = TicketStore.get(ticket) except Exception: return Client.result(error=errors.ACCESS_DENIED) self._request.user = User.objects.get(uuid=data['user']) try: logger.debug(data) res = getService(self._request, data['service'], data['transport']) logger.debug('Res: {}'.format(res)) if res is not None: ip, userService, userServiceInstance, transport, transportInstance = res password = cryptoManager().xor(data['password'], scrambler).decode('utf-8') transportScript = transportInstance.getUDSTransportScript(userService, transport, ip, self._request.os, self._request.user, password, self._request) logger.debug('Script:\n{}'.format(transportScript)) return Client.result(result=transportScript.encode('bz2').encode('base64')) except Exception as e: logger.exception("Exception") return Client.result(error=six.text_type(e)) return Client.result(error=errors.SERVICE_NOT_READY)
def userServiceEnabler(request, idService, idTransport): # Maybe we could even protect this even more by limiting referer to own server /? (just a meditation..) logger.debug('idService: {}, idTransport: {}'.format(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) _x, userService, _x, trans, _x = res data = { 'service': 'A' + userService.uuid, 'transport': trans.uuid, 'user': request.user.uuid, 'password': password } ticket = TicketStore.create(data) error = '' 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) except MaxServicesReachedError: logger.info('Number of service reached MAX for service pool "{}"'.format(idService)) error = errors.errorString(errors.MAX_SERVICES_REACHED) except ServiceAccessDeniedByCalendar: logger.info('Access tried to a calendar limited access pool "{}"'.format(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) }), content_type='application/json' )
def getTicket(self): """ Processes get requests in order to obtain a ticket content GET /rest/actor/ticket/[ticketId]?key=masterKey&[secure=true|1|false|0] """ logger.debug("Ticket args for GET: {0}".format(self._args)) secure = self._params.get('secure') in ('1', 'true') if len(self._args) != 2: raise RequestError('Invalid request') try: return Actor.result(TicketStore.get(self._args[1], invalidate=True)) except Exception: return Actor.result({})
def authCallback_stage2(request: HttpRequest, ticketId: str) -> HttpResponse: try: ticket = TicketStore.get(ticketId) params: typing.Dict[str, typing.Any] = ticket['params'] auth_uuid: str = ticket['auth'] authenticator = Authenticator.objects.get(uuid=auth_uuid) params['_request'] = request # params['_session'] = request.session # params['_user'] = request.user logger.debug('Request session:%s -> %s, %s', request.ip, request.session.keys(), request.session.session_key) user = authenticateViaCallback(authenticator, params) os = OsDetector.getOsFromUA(request.META['HTTP_USER_AGENT']) if user is None: authLogLogin(request, authenticator, '{0}'.format(params), 'Invalid at auth callback') raise auths.exceptions.InvalidUserException() response = HttpResponseRedirect(reverse('page.index')) webLogin(request, response, user, '') # Password is unavailable in this case request.session['OS'] = os # Now we render an intermediate page, so we get Java support from user # It will only detect java, and them redirect to Java return response except auths.exceptions.Redirect as e: return HttpResponseRedirect( request.build_absolute_uri(str(e)) if e.args and e.args[0] else '/' ) except auths.exceptions.Logout as e: return webLogout( request, request.build_absolute_uri(str(e)) if e.args and e.args[0] else None) except Exception as e: logger.exception('authCallback') return errors.exceptionView(request, e) # Will never reach this raise RuntimeError('Unreachable point reached!!!')
def processUserPassword(self, service, username, password): if service.getProperty('sso_available') == '1': # Generate a ticket, store it and return username with no password domain = '' if '@' in username: username, domain = username.split('@') elif '\\' in username: username, domain = username.split('\\') creds = { 'username': username, 'password': password, 'domain': domain } ticket = TicketStore.create(creds, validator=None, validity=300) # , owner=SECURE_OWNER, secure=True) return ticket, '' else: return osmanagers.OSManager.processUserPassword(self, service, username, password)
def getUDSTransportScript(self, userService, transport, ip, os, user, password, request): userServiceInstance = userService.getInstance() # Spice connection con = userServiceInstance.getConsoleConnection() port, secure_port = con['port'], con['secure_port'] port = -1 if port is None else port secure_port = -1 if secure_port is None else secure_port # Ticket tunpass = ''.join(random.choice(string.letters + string.digits) for _i in range(12)) tunuser = TicketStore.create(tunpass) sshHost, sshPort = self.tunnelServer.value.split(':') r = RemoteViewerFile('127.0.0.1', '{port}', '{secure_port}', con['ticket']['value'], self.serverCertificate.value, con['cert_subject'], fullscreen=self.fullScreen.isTrue()) r.usb_auto_share = self.usbShare.isTrue() r.new_usb_auto_share = self.autoNewUsbShare.isTrue() r.smartcard = self.smartCardRedirect.isTrue() m = tools.DictAsObj({ 'r': r, 'tunUser': tunuser, 'tunPass': tunpass, 'tunHost': sshHost, 'tunPort': sshPort, 'ip': con['address'], 'port': port, 'secure_port': secure_port }) os = { OsDetector.Windows: 'windows', OsDetector.Linux: 'linux', OsDetector.Macintosh: 'macosx' }.get(os.OS) if os is None: return super(self.__class__, self).getUDSTransportScript(userService, transport, ip, os, user, password, request) return self.getScript('scripts/{}/tunnel.py'.format(os)).format(m=m)
def pam(request): response = '' if request.method == 'POST': return HttpResponseNotAllowed(['GET']) if 'id' in request.GET and 'pass' in request.GET: # This is an "auth" request logger.debug("Auth request for user [{0}] and pass [{1}]".format(request.GET['id'], request.GET['pass'])) password = TicketStore.get(request.GET['id']) response = '0' if password == request.GET['pass']: response = '1' elif 'uid' in request.GET: # This is an "get name for id" call logger.debug("NSS Request for id [{0}]".format(request.GET['uid'])) response = '10000 udstmp' elif 'name' in request.GET: logger.debug("NSS Request for username [{0}]".format(request.GET['name'])) response = '10000 udstmp' return HttpResponse(response, content_type='text/plain')
def clientEnabler(request, idService, idTransport): # Maybe we could even protect this even more by limiting referer to own server /? (just a meditation..) logger.debug('idService: {}, idTransport: {}'.format(idService, idTransport)) url = '' error = _('Service not ready. Please, try again in a while.') try: res = userServiceManager().getService(request.user, request.ip, idService, idTransport, doTest=False) scrambler = cryptoManager().randomString(32) password = cryptoManager().xor(webPassword(request), scrambler) _x, userService, _x, trans, _x = res data = { 'service': 'A' + userService.uuid, 'transport': trans.uuid, 'user': request.user.uuid, 'password': password } ticket = TicketStore.create(data) error = '' 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) except MaxServicesReachedError: logger.info('Number of service reached MAX for service pool "{}"'.format(idService)) error = errors.errorString(errors.MAX_SERVICES_REACHED) except Exception as e: logger.exception('Error') error = six.text_type(e) return HttpResponse( '{{ "url": "{}", "error": "{}" }}'.format(url, error), content_type='application/json' )
def pam(request): response = '' if request.method == 'POST': return HttpResponseNotAllowed(['GET']) if 'id' in request.GET and 'pass' in request.GET: # This is an "auth" request logger.debug("Auth request for user [{0}] and pass [{1}]".format( request.GET['id'], request.GET['pass'])) password = TicketStore.get(request.GET['id']) response = '0' if password == request.GET['pass']: response = '1' elif 'uid' in request.GET: # This is an "get name for id" call logger.debug("NSS Request for id [{0}]".format(request.GET['uid'])) response = '10000 udstmp' elif 'name' in request.GET: logger.debug("NSS Request for username [{0}]".format( request.GET['name'])) response = '10000 udstmp' return HttpResponse(response, content_type='text/plain')
def guacamole(request: HttpRequest, tunnelId: str) -> HttpResponse: logger.debug('Received credentials request for tunnel id %s', tunnelId) try: tunnelId, scrambler = tunnelId.split('.') val = TicketStore.get(tunnelId, invalidate=False) # Extra check that the ticket data belongs to original requested user service/user if 'ticket-info' in val: ti = val['ticket-info'] del val['ticket-info'] # Do not send this data to guacamole!! :) try: userService = UserService.objects.get(uuid=ti['userService']) except Exception: logger.error( 'The requested guacamole userservice does not exists anymore' ) raise if userService.user.uuid != ti['user']: logger.error( 'The requested userservice has changed owner and is not accesible' ) raise Exception() if 'password' in val: val['password'] = cryptoManager().symDecrpyt( val['password'], scrambler) response = dict2resp(val) except Exception: # logger.error('Invalid guacamole ticket (F5 on client?): %s', tunnelId) return HttpResponse(ERROR, content_type=CONTENT_TYPE) return HttpResponse(response, content_type=CONTENT_TYPE)
def ticketAuth(request: 'HttpRequest', ticketId: str) -> HttpResponse: # pylint: disable=too-many-locals,too-many-branches,too-many-statements """ Used to authenticate an user via a ticket """ try: data = TicketStore.get(ticketId, invalidate=True) try: # Extract ticket.data from ticket.data storage, and remove it if success username = data['username'] groups = data['groups'] auth = data['auth'] realname = data['realname'] servicePool = data['servicePool'] password = cryptoManager().decrypt(data['password']) transport = data['transport'] except Exception: logger.error('Ticket stored is not valid') raise auths.exceptions.InvalidUserException() auth = Authenticator.objects.get(uuid=auth) # If user does not exists in DB, create it right now # Add user to groups, if they exists... grps: typing.List = [] for g in groups: try: grps.append(auth.groups.get(uuid=g)) except Exception: logger.debug('Group list has changed since ticket assignment') if not grps: logger.error('Ticket has no valid groups') raise Exception('Invalid ticket authentication') usr = auth.getOrCreateUser(username, realname) if usr is None or State.isActive( usr.state) is False: # If user is inactive, raise an exception raise auths.exceptions.InvalidUserException() # Add groups to user (replace existing groups) usr.groups.set(grps) # Force cookie generation webLogin(request, None, usr, password) request.user = usr # Temporarily store this user as "authenticated" user, next requests will be done using session request.session[ 'ticket'] = '1' # Store that user access is done using ticket # Override and recalc transport based on current os transport = None logger.debug("Service & transport: %s, %s", servicePool, transport) # Check if servicePool is part of the ticket if servicePool: # If service pool is in there, also is transport res = userServiceManager().getService(request.user, request.os, request.ip, 'F' + servicePool, transport, False) _, userService, _, transport, _ = res transportInstance = transport.getInstance() if transportInstance.ownLink is True: link = reverse('TransportOwnLink', args=('A' + userService.uuid, transport.uuid)) else: link = html.udsAccessLink(request, 'A' + userService.uuid, transport.uuid) request.session['launch'] = link response = HttpResponseRedirect(reverse('page.ticket.launcher')) else: response = HttpResponseRedirect(reverse('page.index')) # Now ensure uds cookie is at response getUDSCookie(request, response, True) return response except ServiceNotReadyError as e: return errors.errorView(request, errors.SERVICE_NOT_READY) except TicketStore.InvalidTicket: return errors.errorView(request, errors.RELOAD_NOT_SUPPORTED) except Authenticator.DoesNotExist: logger.error('Ticket has an non existing authenticator') return errors.errorView(request, errors.ACCESS_DENIED) except ServicePool.DoesNotExist: logger.error('Ticket has an invalid Service Pool') return errors.errorView(request, errors.SERVICE_NOT_FOUND) except Exception as e: logger.exception('Exception') return errors.exceptionView(request, e)
def getUDSTransportScript(self, userService, transport, ip, os, user, password, request): # We use helper to keep this clean # prefs = user.prefs('rdp') ci = self.getConnectionInfo(userService, user, password) username, password, domain = ci['username'], ci['password'], ci['domain'] # width, height = CommonPrefs.getWidthHeight(prefs) # depth = CommonPrefs.getDepth(prefs) width, height = self.screenSize.value.split('x') depth = self.colorDepth.value tunpass = ''.join(random.choice(string.letters + string.digits) for _i in range(12)) tunuser = TicketStore.create(tunpass) sshHost, sshPort = self.tunnelServer.value.split(':') logger.debug('Username generated: {0}, password: {1}'.format(tunuser, tunpass)) r = RDPFile(width == '-1' or height == '-1', width, height, depth, target=os['OS']) r.enablecredsspsupport = ci.get('sso', self.credssp.isTrue()) r.address = '{address}' r.username = username r.password = password r.domain = domain r.redirectPrinters = self.allowPrinters.isTrue() r.redirectSmartcards = self.allowSmartcards.isTrue() r.redirectDrives = self.allowDrives.isTrue() r.redirectHome = self.redirectHome.isTrue() r.redirectSerials = self.allowSerials.isTrue() r.enableClipboard = self.allowClipboard.isTrue() r.redirectAudio = self.allowAudio.isTrue() r.showWallpaper = self.wallpaper.isTrue() r.multimon = self.multimon.isTrue() r.desktopComposition = self.aero.isTrue() r.smoothFonts = self.smooth.isTrue() r.multimedia = self.multimedia.isTrue() r.alsa = self.alsa.isTrue() r.smartcardString = self.smartcardString.value r.printerString = self.printerString.value r.linuxCustomParameters = self.customParameters.value # data # data = { # 'os': os['OS'], # 'ip': ip, # 'tunUser': tunuser, # 'tunPass': tunpass, # 'tunHost': sshHost, # 'tunPort': sshPort, # 'tunWait': self.tunnelWait.num(), # 'username': username, # 'password': password, # 'hasCredentials': username != '' and password != '', # 'domain': domain, # 'width': width, # 'height': height, # 'depth': depth, # 'printers': self.allowPrinters.isTrue(), # 'smartcards': self.allowSmartcards.isTrue(), # 'drives': self.allowDrives.isTrue(), # 'serials': self.allowSerials.isTrue(), # 'compression': True, # 'wallpaper': self.wallpaper.isTrue(), # 'multimon': self.multimon.isTrue(), # 'fullScreen': width == -1 or height == -1, # 'this_server': request.build_absolute_uri('/'), # 'r': r, # } os = { OsDetector.Windows: 'windows', OsDetector.Linux: 'linux', OsDetector.Macintosh: 'macosx' }.get(os['OS']) if os is None: return super(self.__class__, self).getUDSTransportScript(userService, transport, ip, os, user, password, request) sp = { 'tunUser': tunuser, 'tunPass': tunpass, 'tunHost': sshHost, 'tunPort': sshPort, 'tunWait': self.tunnelWait.num(), 'ip': ip, 'password': password, 'this_server': request.build_absolute_uri('/'), } m = tools.DictAsObj(data) return self.getScript('scripts/{}/tunnel.py', os, sp)
def getUDSTransportScript(self, userService, transport, ip, os, user, password, request): # We use helper to keep this clean # prefs = user.prefs('rdp') ci = self.getConnectionInfo(userService, user, password) username, password, domain = ci['username'], ci['password'], ci['domain'] # width, height = CommonPrefs.getWidthHeight(prefs) # depth = CommonPrefs.getDepth(prefs) width, height = self.screenSize.value.split('x') depth = self.colorDepth.value tunpass = ''.join(random.choice(string.letters + string.digits) for _i in range(12)) tunuser = TicketStore.create(tunpass) sshHost, sshPort = self.tunnelServer.value.split(':') logger.debug('Username generated: {0}, password: {1}'.format(tunuser, tunpass)) r = RDPFile(width == '-1' or height == '-1', width, height, depth, target=os['OS']) r.enablecredsspsupport = ci.get('sso', self.credssp.isTrue()) r.address = '{address}' r.username = username r.password = password r.domain = domain r.redirectPrinters = self.allowPrinters.isTrue() r.redirectSmartcards = self.allowSmartcards.isTrue() r.redirectDrives = self.allowDrives.value r.redirectHome = self.redirectHome.isTrue() r.redirectSerials = self.allowSerials.isTrue() r.enableClipboard = self.allowClipboard.isTrue() r.redirectAudio = self.allowAudio.isTrue() r.showWallpaper = self.wallpaper.isTrue() r.multimon = self.multimon.isTrue() r.desktopComposition = self.aero.isTrue() r.smoothFonts = self.smooth.isTrue() r.multimedia = self.multimedia.isTrue() r.alsa = self.alsa.isTrue() r.smartcardString = self.smartcardString.value r.printerString = self.printerString.value r.linuxCustomParameters = self.customParameters.value # data # data = { # 'os': os['OS'], # 'ip': ip, # 'tunUser': tunuser, # 'tunPass': tunpass, # 'tunHost': sshHost, # 'tunPort': sshPort, # 'tunWait': self.tunnelWait.num(), # 'username': username, # 'password': password, # 'hasCredentials': username != '' and password != '', # 'domain': domain, # 'width': width, # 'height': height, # 'depth': depth, # 'printers': self.allowPrinters.isTrue(), # 'smartcards': self.allowSmartcards.isTrue(), # 'drives': self.allowDrives.isTrue(), # 'serials': self.allowSerials.isTrue(), # 'compression': True, # 'wallpaper': self.wallpaper.isTrue(), # 'multimon': self.multimon.isTrue(), # 'fullScreen': width == -1 or height == -1, # 'this_server': request.build_absolute_uri('/'), # 'r': r, # } os = { OsDetector.Windows: 'windows', OsDetector.Linux: 'linux', OsDetector.Macintosh: 'macosx' }.get(os['OS']) if os is None: return super(self.__class__, self).getUDSTransportScript(userService, transport, ip, os, user, password, request) sp = { 'tunUser': tunuser, 'tunPass': tunpass, 'tunHost': sshHost, 'tunPort': sshPort, 'tunWait': self.tunnelWait.num(), 'ip': ip, 'password': password, 'this_server': request.build_absolute_uri('/'), } m = tools.DictAsObj(data) return self.getScript('scripts/{}/tunnel.py', os, sp)
def run(self): logger.debug('Starting ticket storage cleanup') TicketStore.cleanup() logger.debug('Done ticket storage cleanup')
def getUDSTransportScript(self, userService, transport, ip, os, user, password, request): # We use helper to keep this clean prefs = user.prefs('rdp') ci = self.getConnectionInfo(userService, user, password) username, password, domain = ci['username'], ci['password'], ci['domain'] width, height = CommonPrefs.getWidthHeight(prefs) depth = CommonPrefs.getDepth(prefs) tunpass = ''.join(random.choice(string.letters + string.digits) for _i in range(12)) tunuser = TicketStore.create(tunpass) sshHost, sshPort = self.tunnelServer.value.split(':') logger.debug('Username generated: {0}, password: {1}'.format(tunuser, tunpass)) r = RDPFile(width == -1 or height == -1, width, height, depth, target=os['OS']) r.address = '{address}' r.username = username r.password = password r.domain = domain r.redirectPrinters = self.allowPrinters.isTrue() r.redirectSmartcards = self.allowSmartcards.isTrue() r.redirectDrives = self.allowDrives.isTrue() r.redirectSerials = self.allowSerials.isTrue() r.showWallpaper = self.wallpaper.isTrue() r.multimon = self.multimon.isTrue() # data data = { 'os': os['OS'], 'ip': ip, 'tunUser': tunuser, 'tunPass': tunpass, 'tunHost': sshHost, 'tunPort': sshPort, 'username': username, 'password': password, 'hasCredentials': username != '' and password != '', 'domain': domain, 'width': width, 'height': height, 'depth': depth, 'printers': self.allowPrinters.isTrue(), 'smartcards': self.allowSmartcards.isTrue(), 'drives': self.allowDrives.isTrue(), 'serials': self.allowSerials.isTrue(), 'compression': True, 'wallpaper': self.wallpaper.isTrue(), 'multimon': self.multimon.isTrue(), 'fullScreen': width == -1 or height == -1, 'this_server': request.build_absolute_uri('/'), 'r': r, } m = tools.DictAsObj(data) if m.domain != '': m.usernameWithDomain = '{}\\\\{}'.format(m.domain, m.username) else: m.usernameWithDomain = m.username if m.os == OsDetector.Windows: r.password = '******' os = { OsDetector.Windows: 'windows', OsDetector.Linux: 'linux', OsDetector.Macintosh: 'macosx' }.get(m.os) if os is None: return super(TSRDPTransport, self).getUDSTransportScript(self, userService, transport, ip, os, user, password, request) return self.getScript('scripts/{}/tunnel.py'.format(os)).format(m=m)
def getUDSTransportScript( # pylint: disable=too-many-locals self, userService: 'models.UserService', transport: 'models.Transport', ip: str, os: typing.Dict[str, str], user: '******', password: str, request: 'HttpRequest', ) -> typing.Tuple[str, str, typing.Mapping[str, typing.Any]]: # We use helper to keep this clean # prefs = user.prefs('rdp') ci = self.getConnectionInfo(userService, user, password) username, password, domain = ci['username'], ci['password'], ci[ 'domain'] # escape conflicting chars : Note, on 3.0 this should not be neccesary. Kept until more tests # password = password.replace('\\', '\\\\').replace('"', '\\"').replace("'", "\\'") # width, height = CommonPrefs.getWidthHeight(prefs) # depth = CommonPrefs.getDepth(prefs) width, height = self.screenSize.value.split('x') depth = self.colorDepth.value ticket = TicketStore.create_for_tunnel( userService=userService, port=3389, validity=self.tunnelWait.num() + 60, # Ticket overtime ) tunHost, tunPort = self.tunnelServer.value.split(':') r = RDPFile(width == '-1' or height == '-1', width, height, depth, target=os['OS']) r.enablecredsspsupport = ci.get( 'sso') == 'True' or self.credssp.isTrue() r.address = '{address}' r.username = username r.password = password r.domain = domain r.redirectPrinters = self.allowPrinters.isTrue() r.redirectSmartcards = self.allowSmartcards.isTrue() r.redirectDrives = self.allowDrives.value r.redirectSerials = self.allowSerials.isTrue() r.enableClipboard = self.allowClipboard.isTrue() r.redirectAudio = self.allowAudio.isTrue() r.redirectWebcam = self.allowWebcam.isTrue() r.showWallpaper = self.wallpaper.isTrue() r.multimon = self.multimon.isTrue() r.desktopComposition = self.aero.isTrue() r.smoothFonts = self.smooth.isTrue() r.enablecredsspsupport = self.credssp.isTrue() r.multimedia = self.multimedia.isTrue() r.alsa = self.alsa.isTrue() r.smartcardString = self.smartcardString.value r.printerString = self.printerString.value r.linuxCustomParameters = self.customParameters.value r.enforcedShares = self.enforceDrives.value osName = { OsDetector.Windows: 'windows', OsDetector.Linux: 'linux', OsDetector.Macintosh: 'macosx', }.get(os['OS']) if osName is None: return super().getUDSTransportScript(userService, transport, ip, os, user, password, request) sp: typing.MutableMapping[str, typing.Any] = { 'tunHost': tunHost, 'tunPort': tunPort, 'tunWait': self.tunnelWait.num(), 'tunChk': self.verifyCertificate.isTrue(), 'ticket': ticket, 'password': password, 'this_server': request.build_absolute_uri('/'), } if osName == 'windows': if password != '': r.password = '******' sp.update({ 'as_file': r.as_file, }) elif osName == 'linux': sp.update({ 'as_new_xfreerdp_params': r.as_new_xfreerdp_params, }) else: # Mac r.linuxCustomParameters = self.customParametersMAC.value sp.update({ '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 '', }) return self.getScript('scripts/{}/tunnel.py', osName, sp)
def getUDSTransportScript( # pylint: disable=too-many-locals self, userService: 'models.UserService', transport: 'models.Transport', ip: str, os: typing.Dict[str, str], user: '******', password: str, request: 'HttpRequest' ) -> typing.Tuple[str, str, typing.Dict[str, typing.Any]]: # We use helper to keep this clean # prefs = user.prefs('rdp') ci = self.getConnectionInfo(userService, user, password) username, password, domain = ci['username'], ci['password'], ci[ 'domain'] # width, height = CommonPrefs.getWidthHeight(prefs) # depth = CommonPrefs.getDepth(prefs) width, height = self.screenSize.value.split('x') depth = self.colorDepth.value tunpass = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _i in range(12)) tunuser = TicketStore.create(tunpass) sshHost, sshPort = self.tunnelServer.value.split(':') logger.debug('Username generated: %s, password: %s', tunuser, tunpass) r = RDPFile(width == '-1' or height == '-1', width, height, depth, target=os['OS']) r.enablecredsspsupport = ci.get( 'sso') == 'True' or self.credssp.isTrue() r.address = '{address}' r.username = username r.password = password r.domain = domain r.redirectPrinters = self.allowPrinters.isTrue() r.redirectSmartcards = self.allowSmartcards.isTrue() r.redirectDrives = self.allowDrives.value r.redirectHome = self.redirectHome.isTrue() r.redirectSerials = self.allowSerials.isTrue() r.enableClipboard = self.allowClipboard.isTrue() r.redirectAudio = self.allowAudio.isTrue() r.showWallpaper = self.wallpaper.isTrue() r.multimon = self.multimon.isTrue() r.desktopComposition = self.aero.isTrue() r.smoothFonts = self.smooth.isTrue() r.enablecredsspsupport = self.credssp.isTrue() r.multimedia = self.multimedia.isTrue() r.alsa = self.alsa.isTrue() r.smartcardString = self.smartcardString.value r.printerString = self.printerString.value r.linuxCustomParameters = self.customParameters.value r.enforcedShares = self.enforceDrives.value osName = { OsDetector.Windows: 'windows', OsDetector.Linux: 'linux', OsDetector.Macintosh: 'macosx' }.get(os['OS']) if osName is None: return super().getUDSTransportScript(userService, transport, ip, os, user, password, request) sp = { 'tunUser': tunuser, 'tunPass': tunpass, 'tunHost': sshHost, 'tunPort': sshPort, 'tunWait': self.tunnelWait.num(), 'ip': ip, 'password': password, 'this_server': request.build_absolute_uri('/'), } if osName == 'windows': if password != '': r.password = '******' sp.update({ 'as_file': r.as_file, }) elif osName == 'linux': sp.update({ 'as_new_xfreerdp_params': r.as_new_xfreerdp_params, 'as_rdesktop_params': r.as_rdesktop_params, }) else: # Mac sp.update({ 'as_file': r.as_file, 'as_cord_url': r.as_cord_url, 'as_new_xfreerdp_params': r.as_new_xfreerdp_params, }) if domain != '': sp['usernameWithDomain'] = '{}\\\\{}'.format(domain, username) else: sp['usernameWithDomain'] = username return self.getScript('scripts/{}/tunnel.py', osName, sp)
def getUDSTransportScript( # pylint: disable=too-many-locals self, userService: 'models.UserService', transport: 'models.Transport', ip: str, os: typing.Dict[str, str], user: '******', password: str, request: 'HttpRequest' ) -> typing.Tuple[str, str, typing.Dict[str, typing.Any]]: ci = self.getConnectionInfo(userService, user, password) username = ci['username'] priv, pub = self.getAndPushKey(username, userService) width, height = self.getScreenSize() rootless = False desktop = self.desktopType.value if desktop == "UDSVAPP": desktop = "/usr/bin/udsvapp " + self.customCmd.value rootless = True xf = x2go_file.getTemplate(speed=self.speed.value, pack=self.pack.value, quality=self.quality.value, sound=self.sound.isTrue(), soundSystem=self.sound.value, windowManager=desktop, exports=self.exports.isTrue(), rootless=rootless, width=width, height=height, user=username) tunpass = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _i in range(12)) tunuser = TicketStore.create(tunpass) sshHost, sshPort = self.tunnelServer.value.split(':') # data data = { 'os': os['OS'], 'ip': ip, 'port': 22, 'key': priv, 'width': width, 'height': height, 'printers': True, 'drives': self.exports.isTrue(), 'fullScreen': width == -1 or height == -1, 'this_server': request.build_absolute_uri('/'), 'xf': xf } m = tools.DictAsObj(data) osName = { OsDetector.Windows: 'windows', OsDetector.Linux: 'linux', # OsDetector.Macintosh: 'macosx' }.get(os['OS']) if osName is None: return super().getUDSTransportScript(userService, transport, ip, os, user, password, request) sp = { 'tunUser': tunuser, 'tunPass': tunpass, 'tunHost': sshHost, 'tunPort': sshPort, 'ip': ip, 'port': '22', 'key': priv, 'xf': xf } return self.getScript('scripts/{}/direct.py', osName, sp)
def getUDSTransportScript(self, userService, transport, ip, os, user, password, request): # We use helper to keep this clean # prefs = user.prefs('rdp') ci = self.getConnectionInfo(userService, user, password) username, password, domain = ci['username'], ci['password'], ci['domain'] # width, height = CommonPrefs.getWidthHeight(prefs) # depth = CommonPrefs.getDepth(prefs) width, height = self.screenSize.value.split('x') depth = self.colorDepth.value tunpass = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _i in range(12)) tunuser = TicketStore.create(tunpass) sshHost, sshPort = self.tunnelServer.value.split(':') logger.debug('Username generated: {0}, password: {1}'.format(tunuser, tunpass)) r = RDPFile(width == '-1' or height == '-1', width, height, depth, target=os['OS']) r.enablecredsspsupport = ci.get('sso', self.credssp.isTrue()) r.address = '{address}' r.username = username r.password = password r.domain = domain r.redirectPrinters = self.allowPrinters.isTrue() r.redirectSmartcards = self.allowSmartcards.isTrue() r.redirectDrives = self.allowDrives.value r.redirectHome = self.redirectHome.isTrue() r.redirectSerials = self.allowSerials.isTrue() r.enableClipboard = self.allowClipboard.isTrue() r.redirectAudio = self.allowAudio.isTrue() r.showWallpaper = self.wallpaper.isTrue() r.multimon = self.multimon.isTrue() r.desktopComposition = self.aero.isTrue() r.smoothFonts = self.smooth.isTrue() r.enablecredsspsupport = self.credssp.isTrue() r.multimedia = self.multimedia.isTrue() r.alsa = self.alsa.isTrue() r.smartcardString = self.smartcardString.value r.printerString = self.printerString.value r.linuxCustomParameters = self.customParameters.value os = { OsDetector.Windows: 'windows', OsDetector.Linux: 'linux', OsDetector.Macintosh: 'macosx' }.get(os['OS']) if os is None: return super(self.__class__, self).getUDSTransportScript(userService, transport, ip, os, user, password, request) sp = { 'tunUser': tunuser, 'tunPass': tunpass, 'tunHost': sshHost, 'tunPort': sshPort, 'tunWait': self.tunnelWait.num(), 'ip': ip, 'password': password, 'this_server': request.build_absolute_uri('/'), } if os == 'windows': if password != '': r.password = '******' sp.update({ 'as_file': r.as_file, }) elif os == 'linux': sp.update({ 'as_new_xfreerdp_params': r.as_new_xfreerdp_params, 'as_rdesktop_params': r.as_rdesktop_params, }) else: # Mac sp.update({ 'as_file': r.as_file, 'as_cord_url': r.as_cord_url, 'as_new_xfreerdp_params': r.as_new_xfreerdp_params, }) if domain != '': sp['usernameWithDomain'] = '{}\\\\{}'.format(domain, username) else: sp['usernameWithDomain'] = username return self.getScript('scripts/{}/tunnel.py', os, sp)
def get(self): ''' Processes get requests ''' logger.debug("Client args for GET: {0}".format(self._args)) if len(self._args) == 0: # Gets version url = self._request.build_absolute_uri(reverse('ClientDownload')) return Client.result({ 'availableVersion': CLIENT_VERSION, 'requiredVersion': REQUIRED_CLIENT_VERSION, 'downloadUrl': url }) if len(self._args) == 1: # Simple test return Client.result(_('Correct')) try: ticket, scrambler = self._args # If more than 2 args, got an error hostname = self._params['hostname'] # Or if hostname is not included... srcIp = self._request.ip # Ip is optional, if GlobalConfig.HONOR_CLIENT_IP_NOTIFY.getBool() is True: srcIp = self._params.get('ip', srcIp) except Exception: raise RequestError('Invalid request') logger.debug('Got Ticket: {}, scrambled: {}, Hostname: {}, Ip: {}'.format(ticket, scrambler, hostname, srcIp)) try: data = TicketStore.get(ticket) except Exception: return Client.result(error=errors.ACCESS_DENIED) self._request.user = User.objects.get(uuid=data['user']) try: logger.debug(data) res = userServiceManager().getService(self._request.user, self._request.ip, data['service'], data['transport']) logger.debug('Res: {}'.format(res)) ip, userService, userServiceInstance, transport, transportInstance = res password = cryptoManager().xor(data['password'], scrambler).decode('utf-8') userService.setConnectionSource(srcIp, hostname) # Store where we are accessing from so we can notify Service transportScript = transportInstance.getUDSTransportScript(userService, transport, ip, self._request.os, self._request.user, password, self._request) logger.debug('Script:\n{}'.format(transportScript)) return Client.result(result=transportScript.encode('bz2').encode('base64')) except ServiceNotReadyError as e: # Refresh ticket and make this retrayable TicketStore.revalidate(ticket, 20) # Retry will be in at most 5 seconds return Client.result(error=errors.SERVICE_IN_PREPARATION, errorCode=e.code, retryable=True) except Exception as e: logger.exception("Exception") return Client.result(error=six.text_type(e)) # Will never reach this raise RuntimeError('Unreachable point reached!!!')
def ticketAuth(request, ticketId): """ Used to authenticate an user via a ticket """ try: data = TicketStore.get(ticketId, invalidate=True) try: # Extract ticket.data from ticket.data storage, and remove it if success username = data['username'] groups = data['groups'] auth = data['auth'] realname = data['realname'] servicePool = data['servicePool'] password = data['password'] transport = data['transport'] except Exception: logger.error('Ticket stored is not valid') raise InvalidUserException() auth = Authenticator.objects.get(uuid=auth) # If user does not exists in DB, create it right now # Add user to groups, if they exists... grps = [] for g in groups: try: grps.append(auth.groups.get(uuid=g)) except Exception: logger.debug('Group list has changed since ticket assignment') if len(grps) == 0: logger.error('Ticket has no valid groups') raise Exception('Invalid ticket authentication') usr = auth.getOrCreateUser(username, realname) if usr is None or State.isActive(usr.state) is False: # If user is inactive, raise an exception raise InvalidUserException() # Add groups to user (replace existing groups) usr.groups.set(grps) # Force cookie generation webLogin(request, None, usr, password) request.user = usr # Temporarily store this user as "authenticated" user, next requests will be done using session request.session['ticket'] = '1' # Store that user access is done using ticket logger.debug("Service & transport: {}, {}".format(servicePool, transport)) for v in DeployedService.objects.all(): logger.debug("{} {}".format(v.uuid, v.name)) # Check if servicePool is part of the ticket if servicePool is not None: # If service pool is in there, also is transport res = userServiceManager().getService(request.user, request.ip, 'F' + servicePool, transport, False) _x, userService, _x, transport, _x = res transportInstance = transport.getInstance() if transportInstance.ownLink is True: link = reverse('TransportOwnLink', args=('A' + userService.uuid, transport.uuid)) else: link = html.udsAccessLink(request, 'A' + userService.uuid, transport.uuid) response = render( request, theme.template('simpleLauncher.html'), { 'link': link } ) else: response = HttpResponsePermanentRedirect(reverse('uds.web.views.index')) # Now ensure uds cookie is at response getUDSCookie(request, response, True) return response except ServiceNotReadyError as e: return render( request, theme.template('service_not_ready.html'), { 'fromLauncher': True, 'code': e.code } ) except TicketStore.InvalidTicket: return render( request, theme.template('simpleLauncherAlreadyLaunched.html') ) except Authenticator.DoesNotExist: logger.error('Ticket has an non existing authenticator') return errors.exceptionView(request, InvalidUserException()) except DeployedService.DoesNotExist: logger.error('Ticket has an invalid Service Pool') return errors.exceptionView(request, InvalidServiceException()) except Exception as e: logger.exception('Exception') return errors.exceptionView(request, e)
def get(self): # pylint: disable=too-many-locals """ Processes get requests """ logger.debug('Client args for GET: %s', self._args) if not self._args: # Gets version return Client.result({ 'availableVersion': CLIENT_VERSION, 'requiredVersion': REQUIRED_CLIENT_VERSION, 'downloadUrl': self._request.build_absolute_uri( reverse('page.client-download')) }) if len(self._args) == 1: # Simple test return Client.result(_('Correct')) try: ticket, scrambler = self._args # If more than 2 args, got an error. pylint: disable=unbalanced-tuple-unpacking hostname = self._params[ 'hostname'] # Or if hostname is not included... srcIp = self._request.ip # Ip is optional, if GlobalConfig.HONOR_CLIENT_IP_NOTIFY.getBool() is True: srcIp = self._params.get('ip', srcIp) except Exception: raise RequestError('Invalid request') logger.debug('Got Ticket: %s, scrambled: %s, Hostname: %s, Ip: %s', ticket, scrambler, hostname, srcIp) try: data = TicketStore.get(ticket) except Exception: return Client.result(error=errors.ACCESS_DENIED) self._request.user = User.objects.get(uuid=data['user']) try: logger.debug(data) ip, userService, userServiceInstance, transport, transportInstance = userServiceManager( ).getService(self._request.user, self._request.os, self._request.ip, data['service'], data['transport']) logger.debug('Res: %s %s %s %s %s', ip, userService, userServiceInstance, transport, transportInstance) password = cryptoManager().symDecrpyt(data['password'], scrambler) userService.setConnectionSource( srcIp, hostname ) # Store where we are accessing from so we can notify Service transportScript, signature, params = transportInstance.getEncodedTransportScript( userService, transport, ip, self._request.os, self._request.user, password, self._request) logger.debug('Signature: %s', signature) logger.debug('Data:#######\n%s\n###########', params) return Client.result( result={ 'script': transportScript, 'signature': signature, # It is already on base64 'params': encoders.encode(encoders.encode(json.dumps(params), 'bz2'), 'base64', asText=True), }) except ServiceNotReadyError as e: # Refresh ticket and make this retrayable TicketStore.revalidate( ticket, 20) # Retry will be in at most 5 seconds, so 20 is fine :) return Client.result(error=errors.SERVICE_IN_PREPARATION, errorCode=e.code, retryable=True) except Exception as e: logger.exception("Exception") return Client.result(error=str(e))
def getUDSTransportScript(self, userService, transport, ip, os, user, password, request): prefs = user.prefs('nx') ci = self.getConnectionInfo(userService, user, password) username = ci['username'] priv, pub = self.getAndPushKey(username, userService) width, height = CommonPrefs.getWidthHeight(prefs) logger.debug('') xf = x2gofile.getTemplate( speed=self.speed.value, pack=self.pack.value, quality=self.quality.value, sound=self.sound.isTrue(), soundSystem=self.sound.value, windowManager=self.desktopType.value, exports=self.exports.isTrue(), width=width, height=height, user=username ) tunpass = ''.join(random.choice(string.letters + string.digits) for _i in range(12)) tunuser = TicketStore.create(tunpass) sshHost, sshPort = self.tunnelServer.value.split(':') # data data = { 'os': os['OS'], 'ip': ip, 'port': 22, 'tunUser': tunuser, 'tunPass': tunpass, 'tunHost': sshHost, 'tunPort': sshPort, 'username': username, 'key': priv, 'width': width, 'height': height, 'printers': True, 'drives': self.exports.isTrue(), 'fullScreen': width == -1 or height == -1, 'this_server': request.build_absolute_uri('/'), 'xf': xf } m = tools.DictAsObj(data) os = { OsDetector.Windows: 'windows', OsDetector.Linux: 'linux', # OsDetector.Macintosh: 'macosx' }.get(m.os) if os is None: return super(self.__class__, self).getUDSTransportScript(userService, transport, ip, os, user, password, request) return self.getScript('scripts/{}/tunnel.py'.format(os)).format(m=m)
def put(self): """ Processes put requests, currently only under "create" """ logger.debug(self._args) # Parameters can only be theese for p in self._params: if p not in VALID_PARAMS: logger.debug('Parameter {} not in valid ticket parameters list'.format(p)) raise RequestError('Invalid parameters') if len(self._args) != 1 or self._args[0] not in ('create',): raise RequestError('Invalid method') if 'username' not in self._params or 'groups' not in self._params: raise RequestError('Invalid parameters') found = None for i in ('authId', 'authTag', 'auth', 'authSmallName'): if i in self._params: found = i break if found is None: raise RequestError('Invalid parameters (no auth)') force = self._params.get('force', '0') in ('1', 'true', 'True') userIp = self._params.get('userIp', None) try: authId = self._params.get('authId', None) authTag = self._params.get('authTag', self._params.get('authSmallName', None)) authName = self._params.get('auth', None) # Will raise an exception if no auth found if authId is not None: auth = Authenticator.objects.get(uuid=processUuid(authId.lower())) elif authName is not None: auth = Authenticator.objects.get(name=authName) else: auth = Authenticator.objects.get(small_name=authTag) username = self._params['username'] password = self._params.get('password', '') # Some machines needs password, depending on configuration groups = self._params['groups'] if isinstance(groups, (six.text_type, six.binary_type)): groups = (groups,) grps = [] for g in groups: try: grps.append(auth.groups.get(name=g).uuid) except Exception: logger.info('Group {} from ticket does not exists on auth {}, forced creation: {}'.format(g, auth, force)) if force: grps.append(auth.groups.create(name=g, comments='Autocreated form ticket by using force paratemeter').uuid) if len(grps) == 0: # No valid group in groups names raise Exception('Authenticator does not contain ANY of the requested groups') groups = grps time = int(self._params.get('time', 60)) time = 60 if time < 1 else time realname = self._params.get('realname', self._params['username']) servicePool = self._params.get('servicePool', None) transport = self._params.get('transport', None) if servicePool is not None: servicePool = DeployedService.objects.get(uuid=processUuid(servicePool)) # If forced that servicePool must honor groups if force: for addGrp in set(groups) - set(servicePool.assignedGroups.values_list('uuid', flat=True)): servicePool.assignedGroups.add(auth.groups.get(uuid=addGrp)) if transport is not None: transport = Transport.objects.get(uuid=processUuid(transport)) try: servicePool.validateTransport(transport) except Exception: logger.error('Transport {} is not valid for Service Pool {}'.format(transport.name, servicePool.name)) raise Exception('Invalid transport for Service Pool') else: if userIp is None: transport = tools.DictAsObj({'uuid': None}) else: transport = None for v in servicePool.transports.order_by('priority'): if v.validForIp(userIp): transport = v break if transport is None: logger.error('Service pool {} does not has valid transports for ip {}'.format(servicePool.name, userIp)) raise Exception('Service pool does not has any valid transports for ip {}'.format(userIp)) servicePool = servicePool.uuid transport = transport.uuid # pylint: disable=maybe-no-member except Authenticator.DoesNotExist: return Tickets.result(error='Authenticator does not exists') except DeployedService.DoesNotExist: return Tickets.result(error='Service pool does not exists') except Transport.DoesNotExist: return Tickets.result(error='Transport does not exists') except Exception as e: return Tickets.result(error=six.text_type(e)) data = { 'username': username, 'password': cryptoManager().encrypt(password), 'realname': realname, 'groups': groups, 'auth': auth.uuid, 'servicePool': servicePool, 'transport': transport, } ticket = TicketStore.create(data) return Tickets.result(ticket)