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 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 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 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 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 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 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 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 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 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 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 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 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): """ 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('page.client-download')) 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().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: {}'.format(signature)) logger.debug('Data:#######\n{}\n###########'.format(params)) return Client.result(result={ 'script': transportScript, 'signature': signature, # It is already on base64 'params': json.dumps(params).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 = cryptoManager().decrypt(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): ''' 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!!!')