--- firstboot.spec | 2 +- firstboot/pwcheck.py | 124 +++++++++-------------------------------------- modules/create_user.py | 6 ++- 3 files changed, 29 insertions(+), 103 deletions(-) diff --git a/firstboot.spec b/firstboot.spec index 53f2101..283d94c 100644 --- a/firstboot.spec +++ b/firstboot.spec @@ -23,7 +23,7 @@ Requires: system-config-users >= 1.2.111-1 Requires: authconfig-gtk, python-meh Requires: system-config-keyboard Requires: python-ethtool -Requires: cracklib-python +Requires: python-pwquality Requires(post): systemd-units systemd-sysv chkconfig Requires(preun): systemd-units Requires(postun): systemd-units diff --git a/firstboot/pwcheck.py b/firstboot/pwcheck.py index 3440a78..2d2d3dd 100644 --- a/firstboot/pwcheck.py +++ b/firstboot/pwcheck.py @@ -20,7 +20,7 @@ # import re -import cracklib +import pwquality import pygtk pygtk.require("2.0") @@ -34,125 +34,49 @@ import gettext _ = lambda x: gettext.ldgettext("firstboot", x) -class PwError(Exception): - pass - - -class PwRule(object): - - def __init__(self, rule, weight=1, required=False, desc=""): - if callable(rule): - # is a func - self.rule = rule - else: - # is a regex - pattern = re.compile(rule) - self.rule = lambda x: bool(pattern.search(x)) - - if not weight: - raise PwError("weight must be a non-zero value") - - self.weight = weight - self.required = required - - self.desc = desc - - @property - def include(self): - return self.weight > 0 - - @property - def exclude(self): - return self.weight < 0 - - def check(self, password): - passed = self.rule(password) - - if ((self.include and self.required and not passed) or - (self.exclude and self.required and passed)): - logger.debug("%s: %d", self.desc, 0) - raise PwError("password does not meet required criteria") - - if ((self.include and passed) or - (self.exclude and not passed)): - logger.debug("%s: %d", self.desc, self.weight) - return self.weight - else: - logger.debug("%s: %d", self.desc, 0) - return 0 +def clamp(value, lowerbound, upperbound): + return min(max(value, lowerbound), upperbound) class Password(object): - def cracklib_check(password): - try: - cracklib.FascistCheck(password) - except ValueError: - return False - else: - return True - - RULES = [ PwRule(rule=lambda x: len(x) >= 4, weight=1, required=True, - desc="4 characters or more"), - PwRule(rule=lambda x: len(x) >= 8, weight=1, required=False, - desc="8 characters or more"), - PwRule(rule=lambda x: len(x) >= 12, weight=1, required=False, - desc="12 characters or more"), - PwRule(rule=r"[a-z]+", weight=1, required=False, - desc="at least one lowercase character"), - PwRule(rule=r"[A-Z]+", weight=1, required=False, - desc="at least one uppercase character"), - PwRule(rule=r"[0-9]+", weight=1, required=False, - desc="at least one digit"), - PwRule(rule=r"[^a-zA-Z0-9]+", weight=1, required=False, - desc="at least one special character"), - PwRule(rule=cracklib_check, weight=-2, required=False, - desc="cracklib") ] - - MAX_STRENGTH = 7 + MIN_STRENGTH = 0 + MAX_STRENGTH = 100 STRENGTH_STRINGS = [ _("Very weak"), - _("Very weak"), - _("Weak"), _("Weak"), _("Fairly strong"), _("Strong"), - _("Very strong"), _("Very strong") ] - def __init__(self, password): + def __init__(self, password, username=None): self.password = password + self.username = username + self.pwq_settings = pwquality.PWQSettings() + self.pwq_settings.read_config() - @property - def strength(self): - strength = 0 - for rule in self.RULES: - try: - strength += rule.check(self.password) - except PwError: - return 0 + self.strength = self.MIN_STRENGTH + self.pwq_msg = '' + try: + self.strength = self.pwq_settings.check(self.password, None, self.username) + except pwquality.PWQError as (e, msg): + self.pwq_msg = msg - return strength + self.strength = clamp(self.strength, self.MIN_STRENGTH, self.MAX_STRENGTH) @property - def strength_string(self): - strength = self.strength + def strength_frac(self): + return float(self.strength) / self.MAX_STRENGTH - if strength < 0: - return self.STRENGTH_STRINGS[0] + @property + def strength_string(self): + strings_count = len(self.STRENGTH_STRINGS) + index = int(self.strength / (self.MAX_STRENGTH / strings_count)) try: - return self.STRENGTH_STRINGS[strength] + return self.STRENGTH_STRINGS[index] except IndexError: - return _("Undefined") - - @property - def strength_frac(self): - frac = float(self.strength) / self.MAX_STRENGTH - if frac > 1: - frac = 1.0 - - return frac + return self.STRENGTH_STRINGS[-1] def __str__(self): return "%s" % self.password diff --git a/modules/create_user.py b/modules/create_user.py index 3050852..4f1ebab 100644 --- a/modules/create_user.py +++ b/modules/create_user.py @@ -495,9 +495,11 @@ class moduleClass(Module): strengthLabel.set_fraction(0.0) return - pw = Password(pw) - strengthLabel.set_text('%s' % pw.strength_string) + username = self.usernameEntry.get_text() or None + + pw = Password(pw, username) strengthLabel.set_fraction(pw.strength_frac) + strengthLabel.set_text('%s' % pw.strength_string) def confirmEntry_changed(self, entry, passwordEntry, confirmIcon): pw = passwordEntry.get_text() -- 1.7.5.4 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list