Esempio n. 1
0
    def deleteItem(self, item: Authenticator):
        # For every user, remove assigned services (mark them for removal)

        for user in item.users.all():
            for userService in user.userServices.all():
                userService.user = None
                userService.removeOrCancel()

        item.delete()
Esempio n. 2
0
def __registerUser(authenticator: Authenticator,
                   authInstance: AuthenticatorInstance,
                   username: str) -> typing.Optional[User]:
    """
    Check if this user already exists on database with this authenticator, if don't, create it with defaults
    This will work correctly with both internal or externals cause we first authenticate the user, if internal and user do not exists in database
    authenticate will return false, if external and return true, will create a reference in database
    """
    from uds.core.util.request import getRequest

    username = authInstance.transformUsername(username)
    logger.debug('Transformed username: %s', username)

    request = getRequest()

    usr = authenticator.getOrCreateUser(username, username)
    usr.real_name = authInstance.getRealName(username)
    usr.save()
    if usr is not None and State.isActive(usr.state):
        # Now we update database groups for this user
        usr.getManager().recreateGroups(usr)
        # And add an login event
        events.addEvent(authenticator,
                        events.ET_LOGIN,
                        username=username,
                        srcip=request.ip)  # pylint: disable=maybe-no-member
        events.addEvent(authenticator,
                        events.ET_PLATFORM,
                        platform=request.os.OS,
                        browser=request.os.Browser,
                        version=request.os.Version)  # pylint: disable=maybe-no-member
        return usr

    return None
Esempio n. 3
0
def authenticateViaCallback(authenticator: Authenticator,
                            params: typing.Any) -> typing.Optional[User]:
    """
    Given an username, this method will get invoked whenever the url for a callback
    for an authenticator is requested.

    The idea behind this is that, with authenticators that are based on url redirections
    (SSO auths), we provide a mechanism to allow the authenticator to login the user.

    This will:
       * Check that the authenticator supports a callback, raise an error if it
         doesn't support it.
       * Invoke authenticator callback, and expects, on exit, a valid username.
         If it gets None or '', it will raise an error.
       * Register user inside uds if necesary, will invoke in the process
         **getRealUsername** to get it, so keep it wher you can recover it.
       * Update user group membership using Authenticator getGroups, so, in your
         callbacks, remember to store (using provided environment storage, for example)
         the groups of this user so your getGroups will work correctly.
    """
    gm = auths.GroupsManager(authenticator)
    authInstance = authenticator.getInstance()

    # If there is no callback for this authenticator...
    if authInstance.authCallback == auths.Authenticator.authCallback:
        raise auths.exceptions.InvalidAuthenticatorException()

    username = authInstance.authCallback(params, gm)

    if username is None or username == '' or gm.hasValidGroups() is False:
        raise auths.exceptions.InvalidUserException(
            'User doesn\'t has access to UDS')

    return __registerUser(authenticator, authInstance, username)
Esempio n. 4
0
    def search(self, item: Authenticator) -> typing.List[typing.Dict]:
        self.ensureAccess(item, permissions.PERMISSION_READ)
        try:
            type_ = self._params['type']
            if type_ not in ('user', 'group'):
                raise self.invalidRequestException()

            term = self._params['term']

            limit = int(self._params.get('limit', '50'))

            auth = item.getInstance()

            canDoSearch = type_ == 'user' and (
                auth.searchUsers != auths.Authenticator.searchUsers) or (
                    auth.searchGroups != auths.Authenticator.searchGroups)
            if canDoSearch is False:
                raise self.notSupported()

            if type_ == 'user':
                return list(auth.searchUsers(term))[:limit]
            else:
                return list(auth.searchGroups(term))[:limit]
        except Exception as e:
            logger.exception('Too many results: %s', e)
            return [{
                'id': _('Too many results...'),
                'name': _('Refine your query')
            }]
Esempio n. 5
0
def authenticate(username: str, password: str, authenticator: Authenticator, useInternalAuthenticate: bool = False) -> typing.Optional[User]:
    """
    Given an username, password and authenticator, try to authenticate user
    @param username: username to authenticate
    @param password: password to authenticate this user
    @param authenticator: Authenticator (database object) used to authenticate with provided credentials
    @param useInternalAuthenticate: If True, tries to authenticate user using "internalAuthenticate". If false, it uses "authenticate".
                                    This is so because in some situations we may want to use a "trusted" method (internalAuthenticate is never invoked directly from web)
    @return: None if authentication fails, User object (database object) if authentication is o.k.
    """
    logger.debug('Authenticating user %s with authenticator %s', username, authenticator)

    # If global root auth is enabled && user/password is correct,
    if not useInternalAuthenticate and GlobalConfig.SUPER_USER_ALLOW_WEBACCESS.getBool(True) and username == GlobalConfig.SUPER_USER_LOGIN.get(True) and password == GlobalConfig.SUPER_USER_PASS.get(True):
        return getRootUser()

    gm = auths.GroupsManager(authenticator)
    authInstance = authenticator.getInstance()
    if useInternalAuthenticate is False:
        res = authInstance.authenticate(username, password, gm)
    else:
        res = authInstance.internalAuthenticate(username, password, gm)

    if res is False:
        return None

    logger.debug('Groups manager: %s', gm)

    # If do not have any valid group
    if gm.hasValidGroups() is False:
        logger.info('User {} has been authenticated, but he does not belongs to any UDS know group')
        return None

    return __registerUser(authenticator, authInstance, username)
Esempio n. 6
0
    def __init__(self, *args, **kwargs):
        # If an specified login is passed in, retrieve it & remove it from kwargs dict
        tag = kwargs.get('tag', None)
        if 'tag' in kwargs:
            del kwargs['tag']

        logger.debug('tag is "{0}"'.format(tag))

        super(LoginForm, self).__init__(*args, **kwargs)
        choices = []
        nonStandard = []
        standard = []

        auths = Authenticator.getByTag(tag)

        for a in auths:
            if a.getType() is None:
                continue
            if a.getType().isCustom() and tag == 'disabled':
                continue
            choices.append((a.uuid, a.name))
            if a.getType().isCustom():
                nonStandard.append(a.uuid)
            else:
                standard.append(a.uuid)

        self.fields['authenticator'].choices = choices
        self.fields['nonStandard'].initial = ','.join(nonStandard)
        self.fields['standard'].initial = ','.join(standard)
Esempio n. 7
0
 def getAuthInfo(auth: Authenticator):
     theType = auth.getType()
     return {
         'id': auth.uuid,
         'name': auth.name,
         'label': auth.small_name,
         'priority': auth.priority,
         'is_custom': theType.isCustom()
     }
Esempio n. 8
0
def getRootUser():
    # pylint: disable=unexpected-keyword-arg, no-value-for-parameter
    from uds.models import Authenticator
    u = User(id=ROOT_ID, name=GlobalConfig.SUPER_USER_LOGIN.get(True), real_name=_('System Administrator'), state=State.ACTIVE, staff_member=True, is_admin=True)
    u.manager = Authenticator()
    u.getGroups = lambda: []
    u.updateLastAccess = lambda: None
    u.logout = lambda: None
    return u
Esempio n. 9
0
def getRootUser() -> User:
    # pylint: disable=unexpected-keyword-arg, no-value-for-parameter
    user = User(id=ROOT_ID,
                name=GlobalConfig.SUPER_USER_LOGIN.get(True),
                real_name=_('System Administrator'),
                state=State.ACTIVE,
                staff_member=True,
                is_admin=True)
    user.manager = Authenticator()
    # Fake overwrite some methods, a bit cheating? maybe? :)
    user.getGroups = lambda: []  # type: ignore
    user.updateLastAccess = lambda: None  # type: ignore
    user.logout = lambda: None  # type: ignore
    return user
Esempio n. 10
0
 def item_as_dict(self,
                  item: Authenticator) -> typing.Dict[str, typing.Any]:
     type_ = item.getType()
     return {
         'numeric_id': item.id,
         'id': item.uuid,
         'name': item.name,
         'tags': [tag.tag for tag in item.tags.all()],
         'comments': item.comments,
         'priority': item.priority,
         'small_name': item.small_name,
         'users_count': item.users.count(),
         'type': type_.type(),
         'type_name': type_.name(),
         'type_info': self.typeInfo(type_),
         'permission': permissions.getEffectivePermission(self._user, item)
     }
Esempio n. 11
0
    def __init__(self, *args, **kwargs):
        # If an specified login is passed in, retrieve it & remove it from kwargs dict
        tag = kwargs.get('tag', None)
        if 'tag' in kwargs:
            del kwargs['tag']

        # Parent init
        super(LoginForm, self).__init__(*args, **kwargs)

        choices = []

        for a in Authenticator.getByTag(tag):
            if not a.getType():  # Not existing manager for the auth?
                continue
            if a.getType().isCustom() and tag == 'disabled':
                continue
            choices.append((a.uuid, a.name))

        self.fields['authenticator'].choices = choices
Esempio n. 12
0
def getRootUser() -> User:
    """
    Returns an user not in DB that is ROOT for the platform

    Returns:
        User: [description]
    """
    user = User(
        id=ROOT_ID,
        name=GlobalConfig.SUPER_USER_LOGIN.get(True),
        real_name=_('System Administrator'),
        state=State.ACTIVE,
        staff_member=True,
        is_admin=True,
    )
    user.manager = Authenticator()  # type: ignore
    # Fake overwrite some methods, a bit cheating? maybe? :)
    user.getGroups = lambda: []  # type: ignore
    user.updateLastAccess = lambda: None  # type: ignore
    user.logout = lambda: None  # type: ignore
    return user
Esempio n. 13
0
def login(request, tag=None):
    """
    View responsible of logging in an user
    :param request:  http request
    :param tag: tag of login auth
    """
    # request.session.set_expiry(GlobalConfig.USER_SESSION_LENGTH.getInt())
    response = None

    # Default empty form
    form = LoginForm(tag=tag)

    if request.method == 'POST':
        form = LoginForm(request.POST, tag=tag)
        user, data = checkLogin(request, form, tag)
        if user:
            response = HttpResponseRedirect(reverse('uds.web.views.index'))
            webLogin(request, response, user, data)  # data is user password here
        else:  # error, data = error
            if isinstance(data, int):
                return errors.errorView(request, data)
            # Error to notify
            form.add_error(None, data)

    if response is None:
        response = render(request,
            theme.template('login.html'),
            {
                'form': form,
                'authenticators': Authenticator.getByTag(tag),
                'customHtml': GlobalConfig.CUSTOM_HTML_LOGIN.get(True),
                'version': VERSION

            }
        )

    getUDSCookie(request, response)

    return response
Esempio n. 14
0
def login(request, tag=None):
    '''
    View responsible of logging in an user
    :param request:  http request
    :param tag: tag of login auth
    '''
    # request.session.set_expiry(GlobalConfig.USER_SESSION_LENGTH.getInt())

    host = request.META.get('HTTP_HOST') or request.META.get('SERVER_NAME') or 'auth_host'  # Last one is a placeholder in case we can't locate host name

    # Get Authenticators limitation
    logger.debug('Host: {0}'.format(host))
    if GlobalConfig.DISALLOW_GLOBAL_LOGIN.getBool(True) is True:
        if tag is None:
            try:
                Authenticator.objects.get(small_name=host)
                tag = host
            except Exception:
                try:
                    tag = Authenticator.objects.order_by('priority')[0].small_name
                except Exception:  # There is no authenticators yet, simply allow global login to nowhere.. :-)
                    tag = None

    logger.debug('Tag: {0}'.format(tag))

    logger.debug(request.method)
    if request.method == 'POST':
        if 'uds' not in request.COOKIES:
            logger.debug('Request does not have uds cookie')
            return errors.errorView(request, errors.COOKIES_NEEDED)  # We need cookies to keep session data
        request.session.cycle_key()
        form = LoginForm(request.POST, tag=tag)
        if form.is_valid():
            os = OsDetector.getOsFromUA(request.META.get('HTTP_USER_AGENT'))
            try:
                authenticator = Authenticator.objects.get(pk=form.cleaned_data['authenticator'])
            except Exception:
                authenticator = Authenticator()
            userName = form.cleaned_data['user']

            cache = Cache('auth')
            cacheKey = str(authenticator.id) + userName
            tries = cache.get(cacheKey)
            if tries is None:
                tries = 0
            if authenticator.getInstance().blockUserOnLoginFailures is True and tries >= GlobalConfig.MAX_LOGIN_TRIES.getInt():
                form.add_form_error('Too many authentication errors. User temporarily  blocked.')
                authLogLogin(request, authenticator, userName, 'Temporarily blocked')
            else:
                user = authenticate(userName, form.cleaned_data['password'], authenticator)
                logger.debug('User: {}'.format(user))

                if user is None:
                    logger.debug("Invalid credentials for user {0}".format(userName))
                    tries += 1
                    cache.put(cacheKey, tries, GlobalConfig.LOGIN_BLOCK.getInt())
                    form.add_form_error('Invalid credentials')
                    authLogLogin(request, authenticator, userName, 'Invalid credentials')
                else:
                    logger.debug('User {} has logged in'.format(userName))
                    cache.remove(cacheKey)  # Valid login, remove cached tries
                    response = HttpResponseRedirect(reverse('uds.web.views.index'))
                    webLogin(request, response, user, form.cleaned_data['password'])
                    # Add the "java supported" flag to session
                    request.session['OS'] = os
                    authLogLogin(request, authenticator, user.name)
                    return response
    else:
        form = LoginForm(tag=tag)

    response = render_to_response(theme.template('login.html'), {'form': form, 'customHtml': GlobalConfig.CUSTOM_HTML_LOGIN.get(True)},
                                  context_instance=RequestContext(request))

    getUDSCookie(request, response)

    return response
Esempio n. 15
0
def checkLogin(  # pylint: disable=too-many-branches, too-many-statements
    request: 'HttpRequest',
    form: 'LoginForm',
    tag: typing.Optional[str] = None
) -> typing.Tuple[typing.Optional['User'], typing.Any]:
    host = request.META.get('HTTP_HOST') or request.META.get(
        'SERVER_NAME'
    ) or 'auth_host'  # Last one is a placeholder in case we can't locate host name

    # Get Authenticators limitation
    logger.debug('Host: %s', host)
    if GlobalConfig.DISALLOW_GLOBAL_LOGIN.getBool(False) is True:
        if tag is None:
            try:
                Authenticator.objects.get(small_name=host)
                tag = host
            except Exception:
                try:
                    tag = Authenticator.objects.order_by(
                        'priority')[0].small_name
                except Exception:  # There is no authenticators yet, simply allow global login to nowhere.. :-)
                    tag = None

    logger.debug('Tag: %s', tag)

    if 'uds' not in request.COOKIES:
        logger.debug('Request does not have uds cookie')
        return (None, errors.COOKIES_NEEDED)
    if form.is_valid():
        os = request.os
        try:
            authenticator = Authenticator.objects.get(
                uuid=processUuid(form.cleaned_data['authenticator']))
        except Exception:
            authenticator = Authenticator()
        userName = form.cleaned_data['user']
        if GlobalConfig.LOWERCASE_USERNAME.getBool(True) is True:
            userName = userName.lower()

        cache = Cache('auth')
        cacheKey = str(authenticator.id) + userName
        tries = cache.get(cacheKey) or 0
        triesByIp = cache.get(request.ip) or 0
        maxTries = GlobalConfig.MAX_LOGIN_TRIES.getInt()
        if (authenticator.getInstance().blockUserOnLoginFailures is True and
            (tries >= maxTries) or triesByIp >= maxTries):
            authLogLogin(request, authenticator, userName,
                         'Temporarily blocked')
            return (
                None,
                _('Too many authentication errrors. User temporarily blocked'))

        password = form.cleaned_data['password']
        user = None
        if password == '':
            password = '******'  # Random string, in fact, just a placeholder that will not be used :)
        user = authenticate(userName, password, authenticator)
        logger.debug('User: %s', user)

        if user is None:
            logger.debug("Invalid user %s (access denied)", userName)
            cache.put(cacheKey, tries + 1, GlobalConfig.LOGIN_BLOCK.getInt())
            cache.put(request.ip, triesByIp + 1,
                      GlobalConfig.LOGIN_BLOCK.getInt())
            authLogLogin(request, authenticator, userName,
                         'Access denied (user not allowed by UDS)')
            return (None, _('Access denied'))

        request.session.cycle_key()

        logger.debug('User %s has logged in', userName)
        cache.remove(cacheKey)  # Valid login, remove cached tries

        # Add the "java supported" flag to session
        request.session['OS'] = os
        if form.cleaned_data['logouturl'] != '':
            logger.debug('The logoout url will be %s',
                         form.cleaned_data['logouturl'])
            request.session['logouturl'] = form.cleaned_data['logouturl']
        authLogLogin(request, authenticator, user.name)
        return (user, form.cleaned_data['password'])

    logger.info('Invalid form received')
    return (None, _('Invalid data'))
Esempio n. 16
0
def checkLogin(request, form, tag=None):
    host = request.META.get('HTTP_HOST') or request.META.get('SERVER_NAME') or 'auth_host'  # Last one is a placeholder in case we can't locate host name

    # Get Authenticators limitation
    logger.debug('Host: {0}'.format(host))
    if GlobalConfig.DISALLOW_GLOBAL_LOGIN.getBool(False) is True:
        if tag is None:
            try:
                Authenticator.objects.get(small_name=host)
                tag = host
            except Exception:
                try:
                    tag = Authenticator.objects.order_by('priority')[0].small_name
                except Exception:  # There is no authenticators yet, simply allow global login to nowhere.. :-)
                    tag = None

    logger.debug('Tag: {0}'.format(tag))

    if 'uds' not in request.COOKIES:
        logger.debug('Request does not have uds cookie')
        return (None, errors.COOKIES_NEEDED)
    if form.is_valid():
        os = request.os
        try:
            authenticator = Authenticator.objects.get(uuid=processUuid(form.cleaned_data['authenticator']))
        except Exception:
            authenticator = Authenticator()
        userName = form.cleaned_data['user']
        if GlobalConfig.LOWERCASE_USERNAME.getBool(True) is True:
            userName = userName.lower()

        cache = Cache('auth')
        cacheKey = str(authenticator.id) + userName
        tries = cache.get(cacheKey)
        if tries is None:
            tries = 0
        if authenticator.getInstance().blockUserOnLoginFailures is True and tries >= GlobalConfig.MAX_LOGIN_TRIES.getInt():
            authLogLogin(request, authenticator, userName, 'Temporarily blocked')
            return (None, _('Too many authentication errrors. User temporarily blocked'))
        else:
            password = form.cleaned_data['password']
            user = None
            if password == '':
                password = '******'  # Random string, in fact, just a placeholder that will not be used :)
            user = authenticate(userName, password, authenticator)
            logger.debug('User: {}'.format(user))

            if user is None:
                logger.debug("Invalid user {0} (access denied)".format(userName))
                tries += 1
                cache.put(cacheKey, tries, GlobalConfig.LOGIN_BLOCK.getInt())
                authLogLogin(request, authenticator, userName, 'Access denied (user not allowed by UDS)')
                return (None, _('Access denied'))
            else:
                request.session.cycle_key()

                logger.debug('User {} has logged in'.format(userName))
                cache.remove(cacheKey)  # Valid login, remove cached tries

                # Add the "java supported" flag to session
                request.session['OS'] = os
                if form.cleaned_data['logouturl'] != '':
                    logger.debug('The logoout url will be {}'.format(form.cleaned_data['logouturl']))
                    request.session['logouturl'] = form.cleaned_data['logouturl']
                authLogLogin(request, authenticator, user.name)
                return (user, form.cleaned_data['password'])

    logger.info('Invalid form received')
    return (None, _('Invalid data'))
Esempio n. 17
0
def login(request, tag=None):
    '''
    View responsible of logging in an user
    :param request:  http request
    :param tag: tag of login auth
    '''
    # request.session.set_expiry(GlobalConfig.USER_SESSION_LENGTH.getInt())

    host = request.META.get('HTTP_HOST') or request.META.get('SERVER_NAME') or 'auth_host'  # Last one is a placeholder in case we can't locate host name

    # Get Authenticators limitation
    logger.debug('Host: {0}'.format(host))
    if GlobalConfig.DISALLOW_GLOBAL_LOGIN.getBool(False) is True:
        if tag is None:
            try:
                Authenticator.objects.get(small_name=host)
                tag = host
            except Exception:
                try:
                    tag = Authenticator.objects.order_by('priority')[0].small_name
                except Exception:  # There is no authenticators yet, simply allow global login to nowhere.. :-)
                    tag = None

    logger.debug('Tag: {0}'.format(tag))

    logger.debug(request.method)
    if request.method == 'POST':
        if 'uds' not in request.COOKIES:
            logger.debug('Request does not have uds cookie')
            return errors.errorView(request, errors.COOKIES_NEEDED)  # We need cookies to keep session data
        request.session.cycle_key()
        form = LoginForm(request.POST, tag=tag)
        if form.is_valid():
            os = request.os
            try:
                authenticator = Authenticator.objects.get(pk=form.cleaned_data['authenticator'])
            except Exception:
                authenticator = Authenticator()
            userName = form.cleaned_data['user']
            if GlobalConfig.LOWERCASE_USERNAME.getBool(True) is True:
                userName = userName.lower()

            cache = Cache('auth')
            cacheKey = str(authenticator.id) + userName
            tries = cache.get(cacheKey)
            if tries is None:
                tries = 0
            if authenticator.getInstance().blockUserOnLoginFailures is True and tries >= GlobalConfig.MAX_LOGIN_TRIES.getInt():
                form.add_error(None, 'Too many authentication errors. User temporarily  blocked.')
                authLogLogin(request, authenticator, userName, 'Temporarily blocked')
            else:
                password = form.cleaned_data['password']
                user = None
                if password == '':
                    password = '******'
                user = authenticate(userName, password, authenticator)
                logger.debug('User: {}'.format(user))

                if user is None:
                    logger.debug("Invalid credentials for user {0}".format(userName))
                    tries += 1
                    cache.put(cacheKey, tries, GlobalConfig.LOGIN_BLOCK.getInt())
                    form.add_error(None, ugettext('Invalid credentials'))
                    authLogLogin(request, authenticator, userName, 'Invalid credentials')
                else:
                    logger.debug('User {} has logged in'.format(userName))
                    cache.remove(cacheKey)  # Valid login, remove cached tries
                    response = HttpResponseRedirect(reverse('uds.web.views.index'))
                    webLogin(request, response, user, form.cleaned_data['password'])
                    # Add the "java supported" flag to session
                    request.session['OS'] = os
                    if form.cleaned_data['logouturl'] != '':
                        logger.debug('The logoout url will be {}'.format(form.cleaned_data['logouturl']))
                        request.session['logouturl'] = form.cleaned_data['logouturl']
                    authLogLogin(request, authenticator, user.name)
                    return response
        else:
            logger.info('Invalid form received')
    else:
        form = LoginForm(tag=tag)

    response = render_to_response(
        theme.template('login.html'),
        {
            'form': form,
            'customHtml': GlobalConfig.CUSTOM_HTML_LOGIN.get(True),
            'version': VERSION

        },
        context_instance=RequestContext(request)
    )

    getUDSCookie(request, response)

    return response