Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Password Validator More Robust #80

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 31 additions & 14 deletions ckanext/security/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
import string

from ckan import authz
from ckan.common import _
from ckan.plugins.toolkit import _, asbool, config
from ckan.lib.navl.dictization_functions import Missing, Invalid

MIN_PASSWORD_LENGTH = 10
MIN_LEN_ERROR = (
'Your password must be {} characters or longer, and consist of at least '
'three of the following character sets: uppercase characters, lowercase '
'characters, digits, punctuation & special characters.'
MIN_LEN_ERROR = 'Your password must be {} characters or longer.'
COMPLEXITY_ERROR = (
'Your password must consist of at least three of the following character sets: '
'uppercase characters, lowercase characters, digits, punctuation & special characters.'
)
SAME_USERNAME_PASSWORD_ERROR = 'Your password cannot be the same as your username.'


def user_password_validator(key, data, errors, context):
Expand All @@ -24,15 +24,32 @@ def user_password_validator(key, data, errors, context):
elif value == '':
pass # Already handled in core
else:
# NZISM compliant password rules
rules = [
any(x.isupper() for x in value),
any(x.islower() for x in value),
any(x.isdigit() for x in value),
any(x in string.punctuation for x in value)
min_password_length = int(config.get('ckanext.security.min_password_length', 8))
nzism_compliant = asbool(config.get('ckanext.security.nzism_compliant_passwords', True))

username = data.get(('name',), None)
password_fields = [
data.get(('password',), None),
data.get(('password1',), None),
data.get(('password2',), None),
]
if len(value) < MIN_PASSWORD_LENGTH or sum(rules) < 3:
raise Invalid(_(MIN_LEN_ERROR.format(MIN_PASSWORD_LENGTH)))

if username in password_fields:
errors[key].append(_(SAME_USERNAME_PASSWORD_ERROR))

if len(value) < min_password_length:
errors[key].append(_(MIN_LEN_ERROR).format(min_password_length))

if nzism_compliant:
# NZISM compliant password rules
rules = [
any(x.isupper() for x in value),
any(x.islower() for x in value),
any(x.isdigit() for x in value),
any(x in string.punctuation for x in value)
]
if sum(rules) < 3:
errors[key].append(_(COMPLEXITY_ERROR))


def old_username_validator(key, data, errors, context):
Expand Down