Exemple #1
0
 def test_user_known(self):
     user = '******'
     self.assertFalse(user_known(self.env, user))
     # Don't care for anonymous session IDs.
     self._create_session(user, False)
     self.assertFalse(user_known(self.env, user))
     self._create_session(user)
     self.assertTrue(user_known(self.env, user))
 def test_user_known(self):
     user = '******'
     self.assertFalse(user_known(self.env, user))
     # Don't care for anonymous session IDs.
     self._create_session(user, False)
     self.assertFalse(user_known(self.env, user))
     self._create_session(user)
     self.assertTrue(user_known(self.env, user))
Exemple #3
0
    def user_locked(self, user):
        """Returns whether the user account is currently locked.

        Expect True, if locked, False, if not and None otherwise.
        """
        if self.login_attempt_max_count < 1 or not user or \
                not user_known(self.env, user):
            self.log.debug(
                "AccountGuard.user_locked(%s) = None (%s)"
                % (user, self.login_attempt_max_count < 1 and \
                   'disabled by configuration' or 'anonymous user'))
            return None
        count = self.failed_count(user, reset=None)
        if count < self.login_attempt_max_count:
            self.log.debug(
                "AccountGuard.user_locked(%s) = False (try left)" % user)
            return False
        ts_release = self.release_time(user)
        if ts_release == 0:
            # Account locked permanently.
            self.log.debug(
                "AccountGuard.user_locked(%s) = True (permanently)" % user)
            return True
        # Time-locked or time-lock expired.
        ts_now = to_timestamp(to_datetime(None))
        locked = ts_release - ts_now > 0
        self.log.debug(
            "AccountGuard.user_locked(%s) = %s (%s)"
            % (user, locked, locked and 'time-lock' or 'lock expired'))
        return locked
Exemple #4
0
 def lock_time(self, user, next=False):
     """Calculate current time-lock length for user account."""
     base = self.lock_time_progression
     lock_count = self.lock_count(user)
     if not user or not user_known(self.env, user):
         return 0
     else:
         if next:
             # Preview calculation.
             exponent = lock_count
         else:
             exponent = lock_count - 1
     t_lock = self.user_lock_time * base ** exponent
     # Limit maximum lock time.
     if t_lock > self.user_lock_max_time:
         t_lock = self.user_lock_max_time
     self.log.debug("AccountGuard.lock_time(%s) = %s%s"
                    % (user, t_lock, next and ' (preview)' or ''))
     return t_lock
Exemple #5
0
    def failed_count(self, user, ipnr=None, reset=False):
        """Report number of previously logged failed login attempts.

        Enforce login policy with regards to tracking of login attempts
        and user account lock behavior.
        Default `False` for reset value causes logging of another attempt.
        `None` value for reset just reads failed login attempts count.
        `True` value for reset triggers final log deletion.
        """
        if not user or not user_known(self.env, user):
            return 0
        key = 'failed_logins_count'
        value = get_user_attribute(self.env, user, 1, key)
        count = value and user in value and int(value[user][1].get(key)) or 0
        if reset is None:
            # Report failed attempts count only.
            return count
        if not reset:
            # Trigger the failed attempt logger.
            attempts = self.get_failed_log(user)
            log_length = len(attempts)
            if log_length > self.login_attempt_max_count:
                # Truncate attempts list preserving most recent events.
                del attempts[:(log_length - self.login_attempt_max_count)]
            attempts.append({
                'ipnr': ipnr,
                'time': to_timestamp(to_datetime(None))
            })
            count += 1
            # Update or create attempts counter and list.
            set_user_attribute(self.env, user, 'failed_logins', str(attempts))
            set_user_attribute(self.env, user, key, count)
            self.log.debug("AccountGuard.failed_count(%s) = %s" %
                           (user, count))
        else:
            # Delete existing attempts counter and list.
            del_user_attribute(self.env, user, 1, 'failed_logins')
            del_user_attribute(self.env, user, 1, key)
            # Delete the lock count too.
            self.lock_count(user, 'reset')
        return count
Exemple #6
0
    def failed_count(self, user, ipnr=None, reset=False):
        """Report number of previously logged failed login attempts.

        Enforce login policy with regards to tracking of login attempts
        and user account lock behavior.
        Default `False` for reset value causes logging of another attempt.
        `None` value for reset just reads failed login attempts count.
        `True` value for reset triggers final log deletion.
        """
        if not user or not user_known(self.env, user):
            return 0
        key = 'failed_logins_count'
        value = get_user_attribute(self.env, user, 1, key)
        count = value and user in value and int(value[user][1].get(key)) or 0
        if reset is None:
            # Report failed attempts count only.
            return count
        if not reset:
            # Trigger the failed attempt logger.
            attempts = self.get_failed_log(user)
            log_length = len(attempts)
            if log_length > self.login_attempt_max_count:
                # Truncate attempts list preserving most recent events.
                del attempts[:(log_length - self.login_attempt_max_count)]
            attempts.append({'ipnr': ipnr,
                             'time': to_timestamp(to_datetime(None))})
            count += 1
            # Update or create attempts counter and list.
            set_user_attribute(self.env, user, 'failed_logins', str(attempts))
            set_user_attribute(self.env, user, key, count)
            self.log.debug(
                "AccountGuard.failed_count(%s) = %s" % (user, count))
        else:
            # Delete existing attempts counter and list.
            del_user_attribute(self.env, user, 1, 'failed_logins')
            del_user_attribute(self.env, user, 1, key)
            # Delete the lock count too.
            self.lock_count(user, 'reset')
        return count
Exemple #7
0
 def authenticate(self, req):
     if req.method == 'POST' and req.path_info.startswith('/login'):
         user = self._remote_user(req)
         acctmgr = AccountManager(self.env)
         guard = AccountGuard(self.env)
         if guard.login_attempt_max_count > 0:
             if user is None:
                 if req.args.get('user_locked') is None:
                     # get user for failed authentication attempt
                     f_user = req.args.get('user')
                     req.args['user_locked'] = False
                     if user_known(self.env, f_user):
                         if guard.user_locked(f_user) is False:
                             # log current failed login attempt
                             guard.failed_count(f_user, req.remote_addr)
                             if guard.user_locked(f_user) is True:
                                 # step up lock time prolongation
                                 # only when just triggering the lock
                                 guard.lock_count(f_user, 'up')
                                 req.args['user_locked'] = True
                         else:
                             # enforce lock
                             req.args['user_locked'] = True
             else:
                 if guard.user_locked(user) is not False:
                     req.args['user_locked'] = True
                     # void successful login as long as user is locked
                     user = None
                 else:
                     req.args['user_locked'] = False
                     if req.args.get('failed_logins') is None:
                         # Reset failed login attempts counter
                         req.args['failed_logins'] = guard.failed_count(
                                                      user, reset = True)
         if 'REMOTE_USER' not in req.environ:
             req.environ['REMOTE_USER'] = user
     return auth.LoginModule.authenticate(self, req)