Exemple #1
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.
        """
        value = get_user_attribute(self.env, user, 1, 'failed_logins_count')
        count = value and int(value[user][1].get('failed_logins_count')) 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_utimestamp(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, 'failed_logins_count', count)
            self.log.debug("AcctMgr: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, 'failed_logins_count')
            # Delete the lock count too.
            self.lock_count(user, 'reset')
        return count
Exemple #2
0
    def lock_count(self, user, action='get'):
        """Count, log and report, how often in succession user account
        lock conditions have been met.

        This is the exponent for lock time prolongation calculation too.
        """
        key = 'lock_count'
        if not action == 'reset':
            value = get_user_attribute(self.env, user, 1, key)
            count = value and int(value[user][1].get(key)) or 0
            if not action == 'get':
                # Push and create or update cached count.
                count += 1
                set_user_attribute(self.env, user, key, count)
        else:
            # Reset/delete lock count cache.
            del_user_attribute(self.env, user, 1, key)
            count = 0
        return count
Exemple #3
0
    def lock_count(self, user, action='get'):
        """Count, log and report, how often in succession user account
        lock conditions have been met.

        This is the exponent for lock time prolongation calculation too.
        """
        key = 'lock_count'
        if not action == 'reset':
            value = get_user_attribute(self.env, user, 1, key)
            count = value and int(value[user][1].get(key)) or 0
            if not action == 'get':
                # Push and create or update cached count.
                count += 1
                set_user_attribute(self.env, user, key, count)
        else:
            # Reset/delete lock count cache.
            del_user_attribute(self.env, user, 1, key)
            count = 0
        return count
Exemple #4
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 #5
0
    def _do_db_cleanup(self, req):
        if req.perm.has_permission('ACCTMGR_ADMIN'):
            env = self.env
            changed = False
            # Get all data from 'session_attributes' db table.
            attr = get_user_attribute(self.env, username=None,
                                      authenticated=None)
            attrs = {}
            sel = req.args.get('sel')
            if req.args.get('purge') and sel is not None:
                sel = isinstance(sel, list) and sel or [sel]
                sel_len = len(sel)
                matched = []
                for acct, states in attr.iteritems():
                    for state in states['id'].keys():
                        for elem, id in states[state]['id'].iteritems():
                            if id in sel:
                                if acct in attrs.keys():
                                    if state in attrs[acct].keys():
                                        attrs[acct][state] \
                                            .append(elem)
                                    else:
                                        attrs[acct][state] = [elem]
                                else:
                                    attrs[acct] = {state: [elem]}
                                matched.append(id)
                                if len(matched) == sel_len:
                                    break
                        if len(matched) == sel_len:
                            break
                    if len(matched) == sel_len:
                        break
                for id in (frozenset(sel) - frozenset(matched)):
                    for acct, states in attr.iteritems():
                        for state, id_ in states['id'].iteritems():
                            if id == id_:
                                # Full account is marked, forget attributes.
                                if acct in attrs.keys():
                                    attrs[acct].update({state: []})
                                else:
                                    attrs[acct] = {state: []}
                                matched.append(id)
                                if len(matched) == sel_len:
                                    break
                        if len(matched) == sel_len:
                            break
                # DEVEL: for Python>2.4 better use defaultdict for counters
                del_count = {'acct': 0, 'attr': 0}
                for account, states in attrs.iteritems():
                    for state, elem in states.iteritems():
                        if len(elem) == 0:
                            del_user_attribute(env, account, state)
                            del_count['acct'] += 1
                        else:
                            for attribute in elem:
                                del_user_attribute(env, account, state,
                                                   attribute)
                                del_count['attr'] += 1
                    changed = True
            elif req.args.get('list'):
                req.redirect(req.href.admin('accounts', 'users'))

            if changed == True:
                # Update the dict after changes.
                attr = get_user_attribute(env, username=None,
                                          authenticated=None)
            data = {'_dgettext': dgettext}
            data.update(self._prepare_attrs(req, attr))

            if req.args.get('purge') and sel is not None:
                accounts = attributes = ''
                n_plural=del_count['acct']
                if n_plural > 0:
                    accounts = tag.li(tag.span(tag(ngettext(
                    "%(count)s account",
                    "%(count)s accounts",
                    n_plural, count=n_plural
                ))))
                n_plural=del_count['attr']
                if n_plural > 0:
                    attributes = tag.li(tag.span(tag(ngettext(
                    "%(count)s account attribute",
                    "%(count)s account attributes",
                    n_plural, count=n_plural
                ))))
                data['result'] = tag(_("Successfully deleted:"),
                                     tag.ul(accounts, attributes))
            add_stylesheet(req, 'acct_mgr/acct_mgr.css')
            return 'db_cleanup.html', data
Exemple #6
0
 def _do_config(self, req):
     stores = StoreOrder(stores=self.acctmgr.stores,
                         list=self.acctmgr.password_store)
     if req.method == 'POST':
         if req.args.get('restart'):
             del_user_attribute(self.env, attribute='password_refreshed')
             req.redirect(req.href.admin('accounts', 'config',
                                         done='restart'))
         _setorder(req, stores)
         self.config.set('account-manager', 'password_store',
                         ','.join(stores.get_enabled_store_names()))
         for store in stores.get_all_stores():
             for attr, option in _getoptions(store):
                 cls_name = store.__class__.__name__
                 newvalue = req.args.get('%s.%s' % (cls_name, attr))
                 self.log.debug("%s.%s: %s" % (cls_name, attr, newvalue))
                 if newvalue is not None:
                     self.config.set(option.section, option.name, newvalue)
                     self.config.save()
         self.config.set('account-manager', 'force_passwd_change',
                         req.args.get('force_passwd_change', False))
         self.config.set('account-manager', 'persistent_sessions',
                         req.args.get('persistent_sessions', False))
         self.config.set('account-manager', 'verify_email',
                         req.args.get('verify_email', False))
         self.config.set('account-manager', 'refresh_passwd',
                         req.args.get('refresh_passwd', False))
         self.config.save()
     sections = []
     for store in self.acctmgr.stores:
         if store.__class__.__name__ == "ResetPwStore":
             # Exclude special store, that is used strictly internally and
             # inherits configuration from SessionStore anyway.
             continue
         options = []
         for attr, option in _getoptions(store):
             error = None
             opt_val = None
             value = None
             try:
                 opt_val = option.__get__(store, store)
             except AttributeError, e:
                 self.env.log.error(e)
                 error = _("""Error while reading configuration -
                           Hint: Enable/install the required component.""")
                 pass
             if opt_val:
                 value = isinstance(opt_val, Component) and \
                         opt_val.__class__.__name__ or opt_val
             opt_sel = None
             try:
                 interface = option.xtnpt.interface
                 opt_sel = {'options': [], 'selected': None}
             except AttributeError:
                 # No ExtensionOption / Interface undefined
                 pass
             if opt_sel:
                 for impl in option.xtnpt.extensions(self.env):
                     extension = impl.__class__.__name__
                     opt_sel['options'].append(extension)
                     if opt_val and extension == value:
                         opt_sel['selected'] = extension
                 if len(opt_sel['options']) == 0 and error:
                     opt_sel['error'] = error
                 value = opt_sel
             options.append(
                         {'label': attr,
                         'name': '%s.%s' % (store.__class__.__name__, attr),
                         'value': value,
                         'doc': gettext(option.__doc__)
                         })
             continue
         sections.append(
                     {'name': store.__class__.__name__,
                     'classname': store.__class__.__name__,
                     'order': stores[store],
                     'options' : options,
                     })
         continue
Exemple #7
0
    def _do_db_cleanup(self, req):
        if req.perm.has_permission('ACCTMGR_ADMIN'):
            env = self.env
            changed = False
            # Get all data from 'session_attributes' db table.
            attr = get_user_attribute(self.env,
                                      username=None,
                                      authenticated=None)
            attrs = {}
            sel = req.args.get('sel')
            if req.args.get('purge') and sel is not None:
                sel = isinstance(sel, list) and sel or [sel]
                sel_len = len(sel)
                matched = []
                for acct, states in attr.iteritems():
                    for state in states['id'].keys():
                        for elem, id in states[state]['id'].iteritems():
                            if id in sel:
                                if acct in attrs.keys():
                                    if state in attrs[acct].keys():
                                        attrs[acct][state] \
                                            .append(elem)
                                    else:
                                        attrs[acct][state] = [elem]
                                else:
                                    attrs[acct] = {state: [elem]}
                                matched.append(id)
                                if len(matched) == sel_len:
                                    break
                        if len(matched) == sel_len:
                            break
                    if len(matched) == sel_len:
                        break
                for id in (frozenset(sel) - frozenset(matched)):
                    for acct, states in attr.iteritems():
                        for state, id_ in states['id'].iteritems():
                            if id == id_:
                                # Full account is marked, forget attributes.
                                if acct in attrs.keys():
                                    attrs[acct].update({state: []})
                                else:
                                    attrs[acct] = {state: []}
                                matched.append(id)
                                if len(matched) == sel_len:
                                    break
                        if len(matched) == sel_len:
                            break
                # DEVEL: for Python>2.4 better use defaultdict for counters
                del_count = {'acct': 0, 'attr': 0}
                for account, states in attrs.iteritems():
                    for state, elem in states.iteritems():
                        if len(elem) == 0:
                            del_user_attribute(env, account, state)
                            del_count['acct'] += 1
                        else:
                            for attribute in elem:
                                del_user_attribute(env, account, state,
                                                   attribute)
                                del_count['attr'] += 1
                    changed = True
            elif req.args.get('list'):
                req.redirect(req.href.admin('accounts', 'users'))

            if changed == True:
                # Update the dict after changes.
                attr = get_user_attribute(env,
                                          username=None,
                                          authenticated=None)
            data = {'_dgettext': dgettext}
            data.update(self._prepare_attrs(req, attr))

            if req.args.get('purge') and sel is not None:
                accounts = attributes = ''
                n_plural = del_count['acct']
                if n_plural > 0:
                    accounts = tag.li(
                        tag.span(
                            tag(
                                ngettext("%(count)s account",
                                         "%(count)s accounts",
                                         n_plural,
                                         count=n_plural))))
                n_plural = del_count['attr']
                if n_plural > 0:
                    attributes = tag.li(
                        tag.span(
                            tag(
                                ngettext("%(count)s account attribute",
                                         "%(count)s account attributes",
                                         n_plural,
                                         count=n_plural))))
                data['result'] = tag(_("Successfully deleted:"),
                                     tag.ul(accounts, attributes))
            add_stylesheet(req, 'acct_mgr/acct_mgr.css')
            return 'db_cleanup.html', data
Exemple #8
0
 def _do_config(self, req):
     stores = StoreOrder(stores=self.acctmgr.stores,
                         list=self.acctmgr.password_store)
     if req.method == 'POST':
         if req.args.get('restart'):
             del_user_attribute(self.env, attribute='password_refreshed')
             req.redirect(
                 req.href.admin('accounts', 'config', done='restart'))
         _setorder(req, stores)
         self.config.set('account-manager', 'password_store',
                         ','.join(stores.get_enabled_store_names()))
         for store in stores.get_all_stores():
             for attr, option in _getoptions(store):
                 cls_name = store.__class__.__name__
                 newvalue = req.args.get('%s.%s' % (cls_name, attr))
                 self.log.debug("%s.%s: %s" % (cls_name, attr, newvalue))
                 if newvalue is not None:
                     self.config.set(option.section, option.name, newvalue)
                     self.config.save()
         self.config.set('account-manager', 'force_passwd_change',
                         req.args.get('force_passwd_change', False))
         self.config.set('account-manager', 'persistent_sessions',
                         req.args.get('persistent_sessions', False))
         self.config.set('account-manager', 'verify_email',
                         req.args.get('verify_email', False))
         self.config.set('account-manager', 'refresh_passwd',
                         req.args.get('refresh_passwd', False))
         self.config.save()
     sections = []
     for store in self.acctmgr.stores:
         if store.__class__.__name__ == "ResetPwStore":
             # Exclude special store, that is used strictly internally and
             # inherits configuration from SessionStore anyway.
             continue
         options = []
         for attr, option in _getoptions(store):
             error = None
             opt_val = None
             value = None
             try:
                 opt_val = option.__get__(store, store)
             except AttributeError, e:
                 self.env.log.error(e)
                 error = _("""Error while reading configuration -
                           Hint: Enable/install the required component.""")
                 pass
             if opt_val:
                 value = isinstance(opt_val, Component) and \
                         opt_val.__class__.__name__ or opt_val
             opt_sel = None
             try:
                 interface = option.xtnpt.interface
                 opt_sel = {'options': [], 'selected': None}
             except AttributeError:
                 # No ExtensionOption / Interface undefined
                 pass
             if opt_sel:
                 for impl in option.xtnpt.extensions(self.env):
                     extension = impl.__class__.__name__
                     opt_sel['options'].append(extension)
                     if opt_val and extension == value:
                         opt_sel['selected'] = extension
                 if len(opt_sel['options']) == 0 and error:
                     opt_sel['error'] = error
                 value = opt_sel
             options.append({
                 'label':
                 attr,
                 'name':
                 '%s.%s' % (store.__class__.__name__, attr),
                 'value':
                 value,
                 'doc':
                 gettext(option.__doc__)
             })
             continue
         sections.append({
             'name': store.__class__.__name__,
             'classname': store.__class__.__name__,
             'order': stores[store],
             'options': options,
         })
         continue