Search in sources :

Example 1 with RuleHelper

use of password.pwm.config.profile.PwmPasswordPolicy.RuleHelper in project pwm by pwm-project.

the class PwmPasswordRuleValidator method internalPwmPolicyValidator.

@SuppressWarnings("checkstyle:MethodLength")
public List<ErrorInformation> internalPwmPolicyValidator(final String passwordString, final String oldPasswordString, final UserInfo userInfo, final Flag... flags) throws PwmUnrecoverableException {
    final boolean failFast = flags != null && Arrays.asList(flags).contains(Flag.FailFast);
    // null check
    if (passwordString == null) {
        return Collections.singletonList(new ErrorInformation(PwmError.ERROR_UNKNOWN, "empty (null) new password"));
    }
    final List<ErrorInformation> errorList = new ArrayList<>();
    final PwmPasswordPolicy.RuleHelper ruleHelper = policy.getRuleHelper();
    final MacroMachine macroMachine = userInfo == null || userInfo.getUserIdentity() == null ? MacroMachine.forNonUserSpecific(pwmApplication, SessionLabel.SYSTEM_LABEL) : MacroMachine.forUser(pwmApplication, PwmConstants.DEFAULT_LOCALE, SessionLabel.SYSTEM_LABEL, userInfo.getUserIdentity());
    // check against old password
    if (oldPasswordString != null && oldPasswordString.length() > 0 && ruleHelper.readBooleanValue(PwmPasswordRule.DisallowCurrent)) {
        if (oldPasswordString.length() > 0) {
            if (oldPasswordString.equalsIgnoreCase(passwordString)) {
                errorList.add(new ErrorInformation(PwmError.PASSWORD_SAMEASOLD));
            }
        }
        // check chars from old password
        final int maxOldAllowed = ruleHelper.readIntValue(PwmPasswordRule.MaximumOldChars);
        if (maxOldAllowed > 0) {
            if (oldPasswordString.length() > 0) {
                final String lPassword = passwordString.toLowerCase();
                final Set<Character> dupeChars = new HashSet<>();
                // add all dupes to the set.
                for (final char loopChar : oldPasswordString.toLowerCase().toCharArray()) {
                    if (lPassword.indexOf(loopChar) != -1) {
                        dupeChars.add(loopChar);
                    }
                }
                // count the number of (unique) set elements.
                if (dupeChars.size() >= maxOldAllowed) {
                    errorList.add(new ErrorInformation(PwmError.PASSWORD_TOO_MANY_OLD_CHARS));
                }
            }
        }
    }
    if (failFast && errorList.size() > 1) {
        return errorList;
    }
    errorList.addAll(basicSyntaxRuleChecks(passwordString, policy, userInfo));
    if (failFast && errorList.size() > 1) {
        return errorList;
    }
    // check against disallowed values;
    if (!ruleHelper.getDisallowedValues().isEmpty()) {
        final String lcasePwd = passwordString.toLowerCase();
        final Set<String> paramValues = new HashSet<>(ruleHelper.getDisallowedValues());
        for (final String loopValue : paramValues) {
            if (loopValue != null && loopValue.length() > 0) {
                final String expandedValue = macroMachine.expandMacros(loopValue);
                if (StringUtils.isNotBlank(expandedValue)) {
                    final String loweredLoop = expandedValue.toLowerCase();
                    if (lcasePwd.contains(loweredLoop)) {
                        errorList.add(new ErrorInformation(PwmError.PASSWORD_USING_DISALLOWED));
                    }
                }
            }
        }
    }
    if (failFast && errorList.size() > 1) {
        return errorList;
    }
    // check disallowed attributes.
    if (!policy.getRuleHelper().getDisallowedAttributes().isEmpty()) {
        final List<String> paramConfigs = policy.getRuleHelper().getDisallowedAttributes(RuleHelper.Flag.KeepThresholds);
        if (userInfo != null) {
            final Map<String, String> userValues = userInfo.getCachedPasswordRuleAttributes();
            for (final String paramConfig : paramConfigs) {
                final String[] parts = paramConfig.split(":");
                final String attrName = parts[0];
                final String disallowedValue = StringUtils.defaultString(userValues.get(attrName));
                final int threshold = parts.length > 1 ? NumberUtils.toInt(parts[1]) : 0;
                if (containsDisallowedValue(passwordString, disallowedValue, threshold)) {
                    LOGGER.trace("password rejected, same as user attr " + attrName);
                    errorList.add(new ErrorInformation(PwmError.PASSWORD_SAMEASATTR));
                }
            }
        }
    }
    if (failFast && errorList.size() > 1) {
        return errorList;
    }
    {
        // check password strength
        final int requiredPasswordStrength = ruleHelper.readIntValue(PwmPasswordRule.MinimumStrength);
        if (requiredPasswordStrength > 0) {
            if (pwmApplication != null) {
                final int passwordStrength = PasswordUtility.judgePasswordStrength(pwmApplication.getConfig(), passwordString);
                if (passwordStrength < requiredPasswordStrength) {
                    errorList.add(new ErrorInformation(PwmError.PASSWORD_TOO_WEAK));
                    if (EXTRA_LOGGING) {
                        final String msg = "password rejected, password strength of " + passwordStrength + " is lower than policy requirement of " + requiredPasswordStrength;
                        LOGGER.trace(msg);
                    }
                }
            }
        }
    }
    if (failFast && errorList.size() > 1) {
        return errorList;
    }
    // check regex matches.
    for (final Pattern pattern : ruleHelper.getRegExMatch(macroMachine)) {
        if (!pattern.matcher(passwordString).matches()) {
            errorList.add(new ErrorInformation(PwmError.PASSWORD_INVALID_CHAR));
            if (EXTRA_LOGGING) {
                final String msg = "password rejected, does not match configured regex pattern: " + pattern.toString();
                LOGGER.trace(msg);
            }
        }
    }
    if (failFast && errorList.size() > 1) {
        return errorList;
    }
    // check no-regex matches.
    for (final Pattern pattern : ruleHelper.getRegExNoMatch(macroMachine)) {
        if (pattern.matcher(passwordString).matches()) {
            errorList.add(new ErrorInformation(PwmError.PASSWORD_INVALID_CHAR));
            if (EXTRA_LOGGING) {
                LOGGER.trace("password rejected, matches configured no-regex pattern: " + pattern.toString());
            }
        }
    }
    if (failFast && errorList.size() > 1) {
        return errorList;
    }
    // check char group matches
    if (ruleHelper.readIntValue(PwmPasswordRule.CharGroupsMinMatch) > 0) {
        final List<Pattern> ruleGroups = ruleHelper.getCharGroupValues();
        if (ruleGroups != null && !ruleGroups.isEmpty()) {
            final int requiredMatches = ruleHelper.readIntValue(PwmPasswordRule.CharGroupsMinMatch);
            int matches = 0;
            for (final Pattern pattern : ruleGroups) {
                if (pattern.matcher(passwordString).find()) {
                    matches++;
                }
            }
            if (matches < requiredMatches) {
                errorList.add(new ErrorInformation(PwmError.PASSWORD_NOT_ENOUGH_GROUPS));
            }
        }
        if (failFast && errorList.size() > 1) {
            return errorList;
        }
    }
    if (failFast && errorList.size() > 1) {
        return errorList;
    }
    // check if the password is in the dictionary.
    if (ruleHelper.readBooleanValue(PwmPasswordRule.EnableWordlist)) {
        if (pwmApplication != null) {
            if (pwmApplication.getWordlistManager() != null && pwmApplication.getWordlistManager().status() == PwmService.STATUS.OPEN) {
                final boolean found = pwmApplication.getWordlistManager().containsWord(passwordString);
                if (found) {
                    // LOGGER.trace(pwmSession, "password rejected, in wordlist file");
                    errorList.add(new ErrorInformation(PwmError.PASSWORD_INWORDLIST));
                }
            } else {
            /* noop */
            // LOGGER.warn(pwmSession, "password wordlist checking enabled, but wordlist is not available, skipping wordlist check");
            }
        }
        if (failFast && errorList.size() > 1) {
            return errorList;
        }
    }
    if (failFast && errorList.size() > 1) {
        return errorList;
    }
    // check for shared (global) password history
    if (pwmApplication != null) {
        if (pwmApplication.getConfig().readSettingAsBoolean(PwmSetting.PASSWORD_SHAREDHISTORY_ENABLE) && pwmApplication.getSharedHistoryManager().status() == PwmService.STATUS.OPEN) {
            final boolean found = pwmApplication.getSharedHistoryManager().containsWord(passwordString);
            if (found) {
                // LOGGER.trace(pwmSession, "password rejected, in global shared history");
                errorList.add(new ErrorInformation(PwmError.PASSWORD_INWORDLIST));
            }
        }
        if (failFast && errorList.size() > 1) {
            return errorList;
        }
    }
    return errorList;
}
Also used : Pattern(java.util.regex.Pattern) ArrayList(java.util.ArrayList) RuleHelper(password.pwm.config.profile.PwmPasswordPolicy.RuleHelper) ErrorInformation(password.pwm.error.ErrorInformation) PwmPasswordPolicy(password.pwm.config.profile.PwmPasswordPolicy) MacroMachine(password.pwm.util.macro.MacroMachine) HashSet(java.util.HashSet)

Example 2 with RuleHelper

use of password.pwm.config.profile.PwmPasswordPolicy.RuleHelper in project pwm by pwm-project.

the class PwmPasswordRuleValidator method basicSyntaxRuleChecks.

@SuppressWarnings("checkstyle:MethodLength")
private static List<ErrorInformation> basicSyntaxRuleChecks(final String password, final PwmPasswordPolicy policy, final UserInfo userInfo) throws PwmUnrecoverableException {
    final List<ErrorInformation> errorList = new ArrayList<>();
    final PwmPasswordPolicy.RuleHelper ruleHelper = policy.getRuleHelper();
    final PasswordCharCounter charCounter = new PasswordCharCounter(password);
    final int passwordLength = password.length();
    // Check minimum length
    if (passwordLength < ruleHelper.readIntValue(PwmPasswordRule.MinimumLength)) {
        errorList.add(new ErrorInformation(PwmError.PASSWORD_TOO_SHORT));
    }
    // Check maximum length
    {
        final int passwordMaximumLength = ruleHelper.readIntValue(PwmPasswordRule.MaximumLength);
        if (passwordMaximumLength > 0 && passwordLength > passwordMaximumLength) {
            errorList.add(new ErrorInformation(PwmError.PASSWORD_TOO_LONG));
        }
    }
    // check number of numeric characters
    {
        final int numberOfNumericChars = charCounter.getNumericCharCount();
        if (ruleHelper.readBooleanValue(PwmPasswordRule.AllowNumeric)) {
            if (numberOfNumericChars < ruleHelper.readIntValue(PwmPasswordRule.MinimumNumeric)) {
                errorList.add(new ErrorInformation(PwmError.PASSWORD_NOT_ENOUGH_NUM));
            }
            final int maxNumeric = ruleHelper.readIntValue(PwmPasswordRule.MaximumNumeric);
            if (maxNumeric > 0 && numberOfNumericChars > maxNumeric) {
                errorList.add(new ErrorInformation(PwmError.PASSWORD_TOO_MANY_NUMERIC));
            }
            if (!ruleHelper.readBooleanValue(PwmPasswordRule.AllowFirstCharNumeric) && charCounter.isFirstNumeric()) {
                errorList.add(new ErrorInformation(PwmError.PASSWORD_FIRST_IS_NUMERIC));
            }
            if (!ruleHelper.readBooleanValue(PwmPasswordRule.AllowLastCharNumeric) && charCounter.isLastNumeric()) {
                errorList.add(new ErrorInformation(PwmError.PASSWORD_LAST_IS_NUMERIC));
            }
        } else {
            if (numberOfNumericChars > 0) {
                errorList.add(new ErrorInformation(PwmError.PASSWORD_TOO_MANY_NUMERIC));
            }
        }
    }
    // check number of upper characters
    {
        final int numberOfUpperChars = charCounter.getUpperCharCount();
        if (numberOfUpperChars < ruleHelper.readIntValue(PwmPasswordRule.MinimumUpperCase)) {
            errorList.add(new ErrorInformation(PwmError.PASSWORD_NOT_ENOUGH_UPPER));
        }
        final int maxUpper = ruleHelper.readIntValue(PwmPasswordRule.MaximumUpperCase);
        if (maxUpper > 0 && numberOfUpperChars > maxUpper) {
            errorList.add(new ErrorInformation(PwmError.PASSWORD_TOO_MANY_UPPER));
        }
    }
    // check number of alpha characters
    {
        final int numberOfAlphaChars = charCounter.getAlphaCharCount();
        if (numberOfAlphaChars < ruleHelper.readIntValue(PwmPasswordRule.MinimumAlpha)) {
            errorList.add(new ErrorInformation(PwmError.PASSWORD_NOT_ENOUGH_ALPHA));
        }
        final int maxAlpha = ruleHelper.readIntValue(PwmPasswordRule.MaximumAlpha);
        if (maxAlpha > 0 && numberOfAlphaChars > maxAlpha) {
            errorList.add(new ErrorInformation(PwmError.PASSWORD_TOO_MANY_ALPHA));
        }
    }
    // check number of non-alpha characters
    {
        final int numberOfNonAlphaChars = charCounter.getNonAlphaCharCount();
        if (numberOfNonAlphaChars < ruleHelper.readIntValue(PwmPasswordRule.MinimumNonAlpha)) {
            errorList.add(new ErrorInformation(PwmError.PASSWORD_NOT_ENOUGH_NONALPHA));
        }
        final int maxNonAlpha = ruleHelper.readIntValue(PwmPasswordRule.MaximumNonAlpha);
        if (maxNonAlpha > 0 && numberOfNonAlphaChars > maxNonAlpha) {
            errorList.add(new ErrorInformation(PwmError.PASSWORD_TOO_MANY_NONALPHA));
        }
    }
    // check number of lower characters
    {
        final int numberOfLowerChars = charCounter.getLowerCharCount();
        if (numberOfLowerChars < ruleHelper.readIntValue(PwmPasswordRule.MinimumLowerCase)) {
            errorList.add(new ErrorInformation(PwmError.PASSWORD_NOT_ENOUGH_LOWER));
        }
        final int maxLower = ruleHelper.readIntValue(PwmPasswordRule.MaximumLowerCase);
        if (maxLower > 0 && numberOfLowerChars > maxLower) {
            errorList.add(new ErrorInformation(PwmError.PASSWORD_TOO_MANY_UPPER));
        }
    }
    // check number of special characters
    {
        final int numberOfSpecialChars = charCounter.getSpecialCharsCount();
        if (ruleHelper.readBooleanValue(PwmPasswordRule.AllowSpecial)) {
            if (numberOfSpecialChars < ruleHelper.readIntValue(PwmPasswordRule.MinimumSpecial)) {
                errorList.add(new ErrorInformation(PwmError.PASSWORD_NOT_ENOUGH_SPECIAL));
            }
            final int maxSpecial = ruleHelper.readIntValue(PwmPasswordRule.MaximumSpecial);
            if (maxSpecial > 0 && numberOfSpecialChars > maxSpecial) {
                errorList.add(new ErrorInformation(PwmError.PASSWORD_TOO_MANY_SPECIAL));
            }
            if (!ruleHelper.readBooleanValue(PwmPasswordRule.AllowFirstCharSpecial) && charCounter.isFirstSpecial()) {
                errorList.add(new ErrorInformation(PwmError.PASSWORD_FIRST_IS_SPECIAL));
            }
            if (!ruleHelper.readBooleanValue(PwmPasswordRule.AllowLastCharSpecial) && charCounter.isLastSpecial()) {
                errorList.add(new ErrorInformation(PwmError.PASSWORD_LAST_IS_SPECIAL));
            }
        } else {
            if (numberOfSpecialChars > 0) {
                errorList.add(new ErrorInformation(PwmError.PASSWORD_TOO_MANY_SPECIAL));
            }
        }
    }
    // Check maximum character repeats (sequential)
    {
        final int maxSequentialRepeat = ruleHelper.readIntValue(PwmPasswordRule.MaximumSequentialRepeat);
        if (maxSequentialRepeat > 0 && charCounter.getSequentialRepeatedChars() > maxSequentialRepeat) {
            errorList.add(new ErrorInformation(PwmError.PASSWORD_TOO_MANY_REPEAT));
        }
        // Check maximum character repeats (overall)
        final int maxRepeat = ruleHelper.readIntValue(PwmPasswordRule.MaximumRepeat);
        if (maxRepeat > 0 && charCounter.getRepeatedChars() > maxRepeat) {
            errorList.add(new ErrorInformation(PwmError.PASSWORD_TOO_MANY_REPEAT));
        }
    }
    // Check minimum unique character
    {
        final int minUnique = ruleHelper.readIntValue(PwmPasswordRule.MinimumUnique);
        if (minUnique > 0 && charCounter.getUniqueChars() < minUnique) {
            errorList.add(new ErrorInformation(PwmError.PASSWORD_NOT_ENOUGH_UNIQUE));
        }
    }
    // check ad-complexity
    {
        final ADPolicyComplexity complexityLevel = ruleHelper.getADComplexityLevel();
        if (complexityLevel == ADPolicyComplexity.AD2003 || complexityLevel == ADPolicyComplexity.AD2008) {
            final int maxGroupViolations = ruleHelper.readIntValue(PwmPasswordRule.ADComplexityMaxViolations);
            errorList.addAll(checkPasswordForADComplexity(complexityLevel, userInfo, password, charCounter, maxGroupViolations));
        }
    }
    // check consecutive characters
    {
        final int maximumConsecutive = ruleHelper.readIntValue(PwmPasswordRule.MaximumConsecutive);
        if (tooManyConsecutiveChars(password, maximumConsecutive)) {
            errorList.add(new ErrorInformation(PwmError.PASSWORD_TOO_MANY_CONSECUTIVE));
        }
    }
    return errorList;
}
Also used : ErrorInformation(password.pwm.error.ErrorInformation) PwmPasswordPolicy(password.pwm.config.profile.PwmPasswordPolicy) ArrayList(java.util.ArrayList) RuleHelper(password.pwm.config.profile.PwmPasswordPolicy.RuleHelper) ADPolicyComplexity(password.pwm.config.option.ADPolicyComplexity)

Aggregations

ArrayList (java.util.ArrayList)2 PwmPasswordPolicy (password.pwm.config.profile.PwmPasswordPolicy)2 RuleHelper (password.pwm.config.profile.PwmPasswordPolicy.RuleHelper)2 ErrorInformation (password.pwm.error.ErrorInformation)2 HashSet (java.util.HashSet)1 Pattern (java.util.regex.Pattern)1 ADPolicyComplexity (password.pwm.config.option.ADPolicyComplexity)1 MacroMachine (password.pwm.util.macro.MacroMachine)1