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;
}
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;
}
Aggregations