예제 #1
0
def canon_password(username, password, allow_weak):
    '''
    N.B. allow_weak = True should be used for lookup but not storage
    as it allows unassigned codepoints.
    '''
    username = to_utf8(username)
    password = to_utf8(password)
    password = demoronize(password)
    password = password.decode('utf-8')
    password = saslprep(password, allow_unassigned=allow_weak)
    if not allow_weak:
        if len(password) < 6:
            # FIXME: This error message is wrong -- there is no actual maximum length.
            raise ValueError(
                'Please enter a password of between 6 and 20 characters')
        try:
            cpassword = canon_username(password,
                                       allow_reserved=True).decode('idna')
        except:
            cpassword = password.decode('utf-8')
        try:
            username = canon_username(username,
                                      allow_reserved=True).decode('idna')
        except:
            try:
                username = username.decode('idna')
            except:
                username = username.decode('utf-8')
        # import here because this is a big, slow module
        from BTL.canonical.identifier import confuse
        password_letters = list(set([ch for ch in confuse(cpassword)]))
        password_letters.sort()
        username_letters = list(set([ch for ch in confuse(username)]))
        username_letters.sort()
        if cpassword in username or u''.join(password_letters) == u''.join(
                username_letters):
            raise ValueError('password is too similar to user name')
        # TODO: password re-use prevention (password history)
        # TODO: complexity checks (dictionary?)
        # TODO: lockout (temporary and permanent) after failed login attempts
    return password
예제 #2
0
def account_name_graphic(value,
                         prefix_reserved=[u'xn--'],
                         full_name_reserved=[]):
    '''
    Transform an acocunt name for graphic form collation.
    '''
    if value is not None:
        from BTL.canonical.identifier import confuse
        value = to_unicode(value)
        value = unicodedata.normalize('NFC', value)
        value = value.strip()
        value = u'-'.join(value.split())
        value = username_premap_re.sub(lambda m: username_premap[m.group(0)],
                                       value)
        global _account_name_graphic_premap, _account_name_graphic_premap_re
        value = value.strip()
        value = confuse(u'-').join(value.split())
        if _account_name_graphic_premap is None:
            _account_name_graphic_premap = dict([
                (confuse(k), confuse(v))
                for k, v in username_premap.iteritems()
            ])
        if _account_name_graphic_premap_re is None:
            _account_name_graphic_premap_re = re.compile(
                ur'|'.join([
                    ur'(?:%s)' % re.escape(i)
                    for i in _account_name_graphic_premap
                ]), re.UNICODE)
        value = _account_name_graphic_premap_re.sub(
            lambda m: _account_name_graphic_premap[m.group(0)], value)
        value = confuse(value)
        for prefix in prefix_reserved:
            if value.startswith(confuse(prefix)):
                raise ValueError(
                    'The requested user name is reserved.  It starts with something a lot like '
                    + prefix)
        for full_name in full_name_reserved:
            if value == confuse(full_name):
                raise ValueError(
                    'The requested user name is reserved.  It is too much like '
                    + full_name)
    return value