|
@@ -23,6 +23,8 @@
|
|
package password.pwm.util;
|
|
package password.pwm.util;
|
|
|
|
|
|
import com.novell.ldapchai.exception.ImpossiblePasswordPolicyException;
|
|
import com.novell.ldapchai.exception.ImpossiblePasswordPolicyException;
|
|
|
|
+import lombok.Builder;
|
|
|
|
+import lombok.Getter;
|
|
import password.pwm.AppProperty;
|
|
import password.pwm.AppProperty;
|
|
import password.pwm.PwmApplication;
|
|
import password.pwm.PwmApplication;
|
|
import password.pwm.bean.SessionLabel;
|
|
import password.pwm.bean.SessionLabel;
|
|
@@ -100,8 +102,9 @@ public class RandomPasswordGenerator {
|
|
)
|
|
)
|
|
throws PwmUnrecoverableException
|
|
throws PwmUnrecoverableException
|
|
{
|
|
{
|
|
- final RandomGeneratorConfig randomGeneratorConfig = new RandomGeneratorConfig();
|
|
|
|
- randomGeneratorConfig.setPasswordPolicy(passwordPolicy);
|
|
|
|
|
|
+ final RandomGeneratorConfig randomGeneratorConfig = RandomGeneratorConfig.builder()
|
|
|
|
+ .passwordPolicy(passwordPolicy)
|
|
|
|
+ .build();
|
|
|
|
|
|
return createRandomPassword(
|
|
return createRandomPassword(
|
|
sessionLabel,
|
|
sessionLabel,
|
|
@@ -135,28 +138,34 @@ public class RandomPasswordGenerator {
|
|
{
|
|
{
|
|
final long startTimeMS = System.currentTimeMillis();
|
|
final long startTimeMS = System.currentTimeMillis();
|
|
|
|
|
|
- validateSettings(pwmApplication, randomGeneratorConfig);
|
|
|
|
|
|
+ randomGeneratorConfig.validateSettings(pwmApplication);
|
|
|
|
|
|
- if (randomGeneratorConfig.getSeedlistPhrases() == null || randomGeneratorConfig.getSeedlistPhrases().isEmpty()) {
|
|
|
|
- Set<String> seeds = DEFAULT_SEED_PHRASES;
|
|
|
|
-
|
|
|
|
- final SeedlistManager seedlistManager = pwmApplication.getSeedlistManager();
|
|
|
|
- if (seedlistManager != null && seedlistManager.status() == PwmService.STATUS.OPEN && seedlistManager.size() > 0) {
|
|
|
|
- seeds = new HashSet<>();
|
|
|
|
- int safetyCounter = 0;
|
|
|
|
- while (seeds.size() < 10 && safetyCounter < 100) {
|
|
|
|
- safetyCounter++;
|
|
|
|
- final String randomWord = seedlistManager.randomSeed();
|
|
|
|
- if (randomWord != null) {
|
|
|
|
- seeds.add(randomWord);
|
|
|
|
|
|
+ final RandomGeneratorConfig effectiveConfig;
|
|
|
|
+ {
|
|
|
|
+ if (randomGeneratorConfig.getSeedlistPhrases() == null || randomGeneratorConfig.getSeedlistPhrases().isEmpty()) {
|
|
|
|
+ Set<String> seeds = DEFAULT_SEED_PHRASES;
|
|
|
|
+
|
|
|
|
+ final SeedlistManager seedlistManager = pwmApplication.getSeedlistManager();
|
|
|
|
+ if (seedlistManager != null && seedlistManager.status() == PwmService.STATUS.OPEN && seedlistManager.size() > 0) {
|
|
|
|
+ seeds = new HashSet<>();
|
|
|
|
+ int safetyCounter = 0;
|
|
|
|
+ while (seeds.size() < 10 && safetyCounter < 100) {
|
|
|
|
+ safetyCounter++;
|
|
|
|
+ final String randomWord = seedlistManager.randomSeed();
|
|
|
|
+ if (randomWord != null) {
|
|
|
|
+ seeds.add(randomWord);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ effectiveConfig = randomGeneratorConfig.toBuilder()
|
|
|
|
+ .seedlistPhrases(seeds)
|
|
|
|
+ .build();
|
|
|
|
+ } else {
|
|
|
|
+ effectiveConfig = randomGeneratorConfig;
|
|
}
|
|
}
|
|
- randomGeneratorConfig.setSeedlistPhrases(seeds);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- final SeedMachine seedMachine = new SeedMachine(normalizeSeeds(randomGeneratorConfig.getSeedlistPhrases()));
|
|
|
|
|
|
+ final SeedMachine seedMachine = new SeedMachine(normalizeSeeds(effectiveConfig.getSeedlistPhrases()));
|
|
|
|
|
|
int tryCount = 0;
|
|
int tryCount = 0;
|
|
final StringBuilder password = new StringBuilder();
|
|
final StringBuilder password = new StringBuilder();
|
|
@@ -165,24 +174,24 @@ public class RandomPasswordGenerator {
|
|
final PwmPasswordPolicy randomGenPolicy;
|
|
final PwmPasswordPolicy randomGenPolicy;
|
|
{
|
|
{
|
|
final Map<String, String> newPolicyMap = new HashMap<>();
|
|
final Map<String, String> newPolicyMap = new HashMap<>();
|
|
- newPolicyMap.putAll(randomGeneratorConfig.getPasswordPolicy().getPolicyMap());
|
|
|
|
|
|
+ newPolicyMap.putAll(effectiveConfig.getPasswordPolicy().getPolicyMap());
|
|
|
|
|
|
- final String max = newPolicyMap.put(PwmPasswordRule.MaximumLength.getKey(), String.valueOf(randomGeneratorConfig.getMaximumLength()));
|
|
|
|
|
|
+ final String max = newPolicyMap.put(PwmPasswordRule.MaximumLength.getKey(), String.valueOf(effectiveConfig.getMaximumLength()));
|
|
|
|
|
|
- if (randomGeneratorConfig.getMinimumLength() > randomGeneratorConfig.getPasswordPolicy().getRuleHelper().readIntValue(PwmPasswordRule.MinimumLength)) {
|
|
|
|
- newPolicyMap.put(PwmPasswordRule.MinimumLength.getKey(), String.valueOf(randomGeneratorConfig.getMinimumLength()));
|
|
|
|
|
|
+ if (effectiveConfig.getMinimumLength() > effectiveConfig.getPasswordPolicy().getRuleHelper().readIntValue(PwmPasswordRule.MinimumLength)) {
|
|
|
|
+ newPolicyMap.put(PwmPasswordRule.MinimumLength.getKey(), String.valueOf(effectiveConfig.getMinimumLength()));
|
|
}
|
|
}
|
|
- if (randomGeneratorConfig.getMaximumLength() < randomGeneratorConfig.getPasswordPolicy().getRuleHelper().readIntValue(PwmPasswordRule.MaximumLength)) {
|
|
|
|
- newPolicyMap.put(PwmPasswordRule.MaximumLength.getKey(), String.valueOf(randomGeneratorConfig.getMaximumLength()));
|
|
|
|
|
|
+ if (effectiveConfig.getMaximumLength() < effectiveConfig.getPasswordPolicy().getRuleHelper().readIntValue(PwmPasswordRule.MaximumLength)) {
|
|
|
|
+ newPolicyMap.put(PwmPasswordRule.MaximumLength.getKey(), String.valueOf(effectiveConfig.getMaximumLength()));
|
|
}
|
|
}
|
|
- if (randomGeneratorConfig.getMinimumStrength() > randomGeneratorConfig.getPasswordPolicy().getRuleHelper().readIntValue(PwmPasswordRule.MinimumStrength)) {
|
|
|
|
- newPolicyMap.put(PwmPasswordRule.MinimumStrength.getKey(), String.valueOf(randomGeneratorConfig.getMinimumStrength()));
|
|
|
|
|
|
+ if (effectiveConfig.getMinimumStrength() > effectiveConfig.getPasswordPolicy().getRuleHelper().readIntValue(PwmPasswordRule.MinimumStrength)) {
|
|
|
|
+ newPolicyMap.put(PwmPasswordRule.MinimumStrength.getKey(), String.valueOf(effectiveConfig.getMinimumStrength()));
|
|
}
|
|
}
|
|
randomGenPolicy = PwmPasswordPolicy.createPwmPasswordPolicy(newPolicyMap);
|
|
randomGenPolicy = PwmPasswordPolicy.createPwmPasswordPolicy(newPolicyMap);
|
|
}
|
|
}
|
|
|
|
|
|
// initial creation
|
|
// initial creation
|
|
- password.append(generateNewPassword(seedMachine, randomGeneratorConfig.getMinimumLength()));
|
|
|
|
|
|
+ password.append(generateNewPassword(seedMachine, effectiveConfig.getMinimumLength()));
|
|
|
|
|
|
// read a rule validator
|
|
// read a rule validator
|
|
final PwmPasswordRuleValidator pwmPasswordRuleValidator = new PwmPasswordRuleValidator(pwmApplication, randomGenPolicy);
|
|
final PwmPasswordRuleValidator pwmPasswordRuleValidator = new PwmPasswordRuleValidator(pwmApplication, randomGenPolicy);
|
|
@@ -197,7 +206,7 @@ public class RandomPasswordGenerator {
|
|
|
|
|
|
if (tryCount % JITTER_COUNT == 0) {
|
|
if (tryCount % JITTER_COUNT == 0) {
|
|
password.delete(0,password.length());
|
|
password.delete(0,password.length());
|
|
- password.append(generateNewPassword(seedMachine, randomGeneratorConfig.getMinimumLength()));
|
|
|
|
|
|
+ password.append(generateNewPassword(seedMachine, effectiveConfig.getMinimumLength()));
|
|
}
|
|
}
|
|
|
|
|
|
final List<ErrorInformation> errors = pwmPasswordRuleValidator.internalPwmPolicyValidator(
|
|
final List<ErrorInformation> errors = pwmPasswordRuleValidator.internalPwmPolicyValidator(
|
|
@@ -208,7 +217,7 @@ public class RandomPasswordGenerator {
|
|
} else if (checkPasswordAgainstDisallowedHttpValues(pwmApplication.getConfig(), password.toString())) {
|
|
} else if (checkPasswordAgainstDisallowedHttpValues(pwmApplication.getConfig(), password.toString())) {
|
|
validPassword = false;
|
|
validPassword = false;
|
|
password.delete(0, password.length());
|
|
password.delete(0, password.length());
|
|
- password.append(generateNewPassword(seedMachine, randomGeneratorConfig.getMinimumLength()));
|
|
|
|
|
|
+ password.append(generateNewPassword(seedMachine, effectiveConfig.getMinimumLength()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -544,99 +553,85 @@ public class RandomPasswordGenerator {
|
|
return newSeeds.isEmpty() ? DEFAULT_SEED_PHRASES : newSeeds;
|
|
return newSeeds.isEmpty() ? DEFAULT_SEED_PHRASES : newSeeds;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @Getter
|
|
|
|
+ @Builder(toBuilder = true)
|
|
public static class RandomGeneratorConfig {
|
|
public static class RandomGeneratorConfig {
|
|
- public static final int DEFAULT_MINIMUM_LENGTH = 6;
|
|
|
|
- public static final int DEFAULT_MAXIMUM_LENGTH = 16;
|
|
|
|
- public static final int DEFAULT_DESIRED_STRENGTH = 45;
|
|
|
|
|
|
+ private static final int DEFAULT_MINIMUM_LENGTH = 6;
|
|
|
|
+ private static final int DEFAULT_MAXIMUM_LENGTH = 16;
|
|
|
|
+ private static final int DEFAULT_DESIRED_STRENGTH = 45;
|
|
|
|
|
|
- public static final int MINIMUM_STRENGTH = 0;
|
|
|
|
- public static final int MAXIMUM_STRENGTH = 100;
|
|
|
|
|
|
+ private static final int MINIMUM_STRENGTH = 0;
|
|
|
|
+ private static final int MAXIMUM_STRENGTH = 100;
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * A set of phrases (Strings) used to generate the RANDOM passwords. There must be enough
|
|
|
|
+ * values in the phrases to build a random password that meets rule requirements
|
|
|
|
+ */
|
|
|
|
+ @Builder.Default
|
|
private Collection<String> seedlistPhrases = Collections.emptySet();
|
|
private Collection<String> seedlistPhrases = Collections.emptySet();
|
|
- private int minimumLength = DEFAULT_MINIMUM_LENGTH;
|
|
|
|
- private int maximumLength = DEFAULT_MAXIMUM_LENGTH;
|
|
|
|
- private int minimumStrength = DEFAULT_DESIRED_STRENGTH;
|
|
|
|
- private PwmPasswordPolicy passwordPolicy = PwmPasswordPolicy.defaultPolicy();
|
|
|
|
-
|
|
|
|
- public Collection<String> getSeedlistPhrases() {
|
|
|
|
- return seedlistPhrases;
|
|
|
|
- }
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
- * @param seedlistPhrases A set of phrases (Strings) used to generate the RANDOM passwords. There must be enough
|
|
|
|
- * values in the phrases to build a resonably RANDOM password that meets rule requirements
|
|
|
|
|
|
+ * The minimum length desired for the password. The algorithm will attempt to make
|
|
|
|
+ * the returned value at least this long, but it is not guaranteed.
|
|
*/
|
|
*/
|
|
- public void setSeedlistPhrases(final Collection<String> seedlistPhrases) {
|
|
|
|
- this.seedlistPhrases = seedlistPhrases;
|
|
|
|
- }
|
|
|
|
|
|
+ @Builder.Default
|
|
|
|
+ private int minimumLength = DEFAULT_MINIMUM_LENGTH;
|
|
|
|
|
|
- public int getMinimumLength() {
|
|
|
|
- return minimumLength;
|
|
|
|
- }
|
|
|
|
|
|
+ @Builder.Default
|
|
|
|
+ private int maximumLength = DEFAULT_MAXIMUM_LENGTH;
|
|
|
|
|
|
/**
|
|
/**
|
|
- * @param minimumLength The minimum length desired for the password. The algorith will attempt to make
|
|
|
|
- * the returned value at least this long, but it is not guarenteed.
|
|
|
|
|
|
+ * @param minimumStrength The minimum length desired strength. The algorithm will attempt to make
|
|
|
|
+ * the returned value at least this strong, but it is not guaranteed.
|
|
*/
|
|
*/
|
|
- public void setMinimumLength(final int minimumLength) {
|
|
|
|
- this.minimumLength = minimumLength;
|
|
|
|
- }
|
|
|
|
|
|
+ @Builder.Default
|
|
|
|
+ private int minimumStrength = DEFAULT_DESIRED_STRENGTH;
|
|
|
|
|
|
- public int getMaximumLength() {
|
|
|
|
- return maximumLength;
|
|
|
|
- }
|
|
|
|
|
|
+ @Builder.Default
|
|
|
|
+ private PwmPasswordPolicy passwordPolicy = PwmPasswordPolicy.defaultPolicy();
|
|
|
|
|
|
- public void setMaximumLength(final int maximumLength) {
|
|
|
|
- this.maximumLength = maximumLength;
|
|
|
|
- }
|
|
|
|
|
|
|
|
- public int getMinimumStrength() {
|
|
|
|
- return minimumStrength;
|
|
|
|
|
|
+ public int getMaximumLength() {
|
|
|
|
+ int policyMax = this.maximumLength;
|
|
|
|
+ if (this.getPasswordPolicy() != null) {
|
|
|
|
+ policyMax = this.getPasswordPolicy().getRuleHelper().readIntValue(PwmPasswordRule.MaximumLength);
|
|
|
|
+ }
|
|
|
|
+ return Math.min(this.maximumLength, policyMax);
|
|
}
|
|
}
|
|
|
|
|
|
- /**
|
|
|
|
- * @param minimumStrength The minimum length desired strength. The algorith will attempt to make
|
|
|
|
- * the returned value at least this strong, but it is not guarenteed.
|
|
|
|
- */
|
|
|
|
- public void setMinimumStrength(final int minimumStrength) {
|
|
|
|
- int desiredStrength = minimumStrength > MAXIMUM_STRENGTH ? MAXIMUM_STRENGTH : minimumStrength;
|
|
|
|
- desiredStrength = desiredStrength < MINIMUM_STRENGTH ? MINIMUM_STRENGTH : desiredStrength;
|
|
|
|
- this.minimumStrength = desiredStrength;
|
|
|
|
|
|
+ public int getMinimumStrength() {
|
|
|
|
+ int policyMin = this.minimumLength;
|
|
|
|
+ if (this.getPasswordPolicy() != null) {
|
|
|
|
+ policyMin = this.getPasswordPolicy().getRuleHelper().readIntValue(PwmPasswordRule.MinimumLength);
|
|
|
|
+ }
|
|
|
|
+ return Math.max(this.minimumLength, policyMin);
|
|
}
|
|
}
|
|
|
|
|
|
- public PwmPasswordPolicy getPasswordPolicy() {
|
|
|
|
- return passwordPolicy;
|
|
|
|
- }
|
|
|
|
|
|
+ void validateSettings(final PwmApplication pwmApplication)
|
|
|
|
+ throws PwmUnrecoverableException
|
|
|
|
+ {
|
|
|
|
+ final int maxLength = Integer.parseInt(
|
|
|
|
+ pwmApplication.getConfig().readAppProperty(AppProperty.PASSWORD_RANDOMGEN_MAX_LENGTH));
|
|
|
|
+ if (this.getMinimumLength() > maxLength) {
|
|
|
|
+ throw new PwmUnrecoverableException(new ErrorInformation(
|
|
|
|
+ PwmError.ERROR_UNKNOWN,
|
|
|
|
+ "minimum random generated password length exceeds preset random generator threshold"
|
|
|
|
+ ));
|
|
|
|
+ }
|
|
|
|
|
|
- public void setPasswordPolicy(final PwmPasswordPolicy passwordPolicy) {
|
|
|
|
- this.passwordPolicy = passwordPolicy;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ if (this.getMaximumLength() > maxLength) {
|
|
|
|
+ throw new PwmUnrecoverableException(new ErrorInformation(
|
|
|
|
+ PwmError.ERROR_UNKNOWN,
|
|
|
|
+ "maximum random generated password length exceeds preset random generator threshold"
|
|
|
|
+ ));
|
|
|
|
+ }
|
|
|
|
|
|
- public static void validateSettings(final PwmApplication pwmApplication, final RandomGeneratorConfig randomGeneratorConfig)
|
|
|
|
- throws PwmUnrecoverableException
|
|
|
|
- {
|
|
|
|
- final int maxLength = Integer.parseInt(
|
|
|
|
- pwmApplication.getConfig().readAppProperty(AppProperty.PASSWORD_RANDOMGEN_MAX_LENGTH));
|
|
|
|
- if (randomGeneratorConfig.getMinimumLength() > maxLength) {
|
|
|
|
- throw new PwmUnrecoverableException(new ErrorInformation(
|
|
|
|
- PwmError.ERROR_UNKNOWN,
|
|
|
|
- "minimum random generated password length exceeds preset random generator threshold"
|
|
|
|
- ));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (randomGeneratorConfig.getMaximumLength() > maxLength) {
|
|
|
|
- throw new PwmUnrecoverableException(new ErrorInformation(
|
|
|
|
- PwmError.ERROR_UNKNOWN,
|
|
|
|
- "maximum random generated password length exceeds preset random generator threshold"
|
|
|
|
- ));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (randomGeneratorConfig.getMinimumStrength() > RandomGeneratorConfig.MAXIMUM_STRENGTH) {
|
|
|
|
- throw new PwmUnrecoverableException(new ErrorInformation(
|
|
|
|
- PwmError.ERROR_UNKNOWN,
|
|
|
|
- "minimum random generated password strength exceeds maximum possible"
|
|
|
|
- ));
|
|
|
|
|
|
+ if (this.getMinimumStrength() > RandomGeneratorConfig.MAXIMUM_STRENGTH) {
|
|
|
|
+ throw new PwmUnrecoverableException(new ErrorInformation(
|
|
|
|
+ PwmError.ERROR_UNKNOWN,
|
|
|
|
+ "minimum random generated password strength exceeds maximum possible"
|
|
|
|
+ ));
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|