use of password.pwm.svc.wordlist.SeedlistManager in project pwm by pwm-project.
the class RandomPasswordGenerator method createRandomPassword.
/**
* Creates a new password that satisfies the password rules. All rules are checked for. If for some
* reason the RANDOM algorithm can not generate a valid password, null will be returned.
* <p/>
* If there is an identifiable reason the password can not be created (such as mis-configured rules) then
* an {@link com.novell.ldapchai.exception.ImpossiblePasswordPolicyException} will be thrown.
*
* @param sessionLabel A valid pwmSession
* @param randomGeneratorConfig Policy to be used during generation
* @param pwmApplication Used to read configuration, seedmanager and other services.
* @return A randomly generated password value that meets the requirements of this {@code PasswordPolicy}
* @throws com.novell.ldapchai.exception.ImpossiblePasswordPolicyException If there is no way to create a password using the configured rules and
* default seed phrase
*/
public static PasswordData createRandomPassword(final SessionLabel sessionLabel, final RandomGeneratorConfig randomGeneratorConfig, final PwmApplication pwmApplication) throws PwmUnrecoverableException {
final Instant startTimeMS = Instant.now();
randomGeneratorConfig.validateSettings(pwmApplication);
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;
}
}
final SeedMachine seedMachine = new SeedMachine(normalizeSeeds(effectiveConfig.getSeedlistPhrases()));
int tryCount = 0;
final StringBuilder password = new StringBuilder();
// determine the password policy to use for random generation
final PwmPasswordPolicy randomGenPolicy;
{
final Map<String, String> newPolicyMap = new HashMap<>();
newPolicyMap.putAll(effectiveConfig.getPasswordPolicy().getPolicyMap());
final String max = newPolicyMap.put(PwmPasswordRule.MaximumLength.getKey(), String.valueOf(effectiveConfig.getMaximumLength()));
if (effectiveConfig.getMinimumLength() > effectiveConfig.getPasswordPolicy().getRuleHelper().readIntValue(PwmPasswordRule.MinimumLength)) {
newPolicyMap.put(PwmPasswordRule.MinimumLength.getKey(), String.valueOf(effectiveConfig.getMinimumLength()));
}
if (effectiveConfig.getMaximumLength() < effectiveConfig.getPasswordPolicy().getRuleHelper().readIntValue(PwmPasswordRule.MaximumLength)) {
newPolicyMap.put(PwmPasswordRule.MaximumLength.getKey(), String.valueOf(effectiveConfig.getMaximumLength()));
}
if (effectiveConfig.getMinimumStrength() > effectiveConfig.getPasswordPolicy().getRuleHelper().readIntValue(PwmPasswordRule.MinimumStrength)) {
newPolicyMap.put(PwmPasswordRule.MinimumStrength.getKey(), String.valueOf(effectiveConfig.getMinimumStrength()));
}
randomGenPolicy = PwmPasswordPolicy.createPwmPasswordPolicy(newPolicyMap);
}
// initial creation
password.append(generateNewPassword(seedMachine, effectiveConfig.getMinimumLength()));
// read a rule validator
final PwmPasswordRuleValidator pwmPasswordRuleValidator = new PwmPasswordRuleValidator(pwmApplication, randomGenPolicy);
// modify until it passes all the rules
final int maxTryCount = Integer.parseInt(pwmApplication.getConfig().readAppProperty(AppProperty.PASSWORD_RANDOMGEN_MAX_ATTEMPTS));
final int jitterCount = Integer.parseInt(pwmApplication.getConfig().readAppProperty(AppProperty.PASSWORD_RANDOMGEN_JITTER_COUNT));
boolean validPassword = false;
while (!validPassword && tryCount < maxTryCount) {
tryCount++;
validPassword = true;
if (tryCount % jitterCount == 0) {
password.delete(0, password.length());
password.append(generateNewPassword(seedMachine, effectiveConfig.getMinimumLength()));
}
final List<ErrorInformation> errors = pwmPasswordRuleValidator.internalPwmPolicyValidator(password.toString(), null, null, PwmPasswordRuleValidator.Flag.FailFast);
if (errors != null && !errors.isEmpty()) {
validPassword = false;
modifyPasswordBasedOnErrors(password, errors, seedMachine);
} else if (checkPasswordAgainstDisallowedHttpValues(pwmApplication.getConfig(), password.toString())) {
validPassword = false;
password.delete(0, password.length());
password.append(generateNewPassword(seedMachine, effectiveConfig.getMinimumLength()));
}
}
// report outcome
{
final TimeDuration td = TimeDuration.fromCurrent(startTimeMS);
if (validPassword) {
LOGGER.trace(sessionLabel, "finished random password generation in " + td.asCompactString() + " after " + tryCount + " tries.");
} else {
final List<ErrorInformation> errors = pwmPasswordRuleValidator.internalPwmPolicyValidator(password.toString(), null, null);
final int judgeLevel = PasswordUtility.judgePasswordStrength(pwmApplication.getConfig(), password.toString());
final StringBuilder sb = new StringBuilder();
sb.append("failed random password generation after ").append(td.asCompactString()).append(" after ").append(tryCount).append(" tries. ");
sb.append("(errors=").append(errors.size()).append(", judgeLevel=").append(judgeLevel);
LOGGER.error(sessionLabel, sb.toString());
}
}
StatisticsManager.incrementStat(pwmApplication, Statistic.GENERATED_PASSWORDS);
final String logText = "real-time random password generator called" + " (" + TimeDuration.compactFromCurrent(startTimeMS) + ")";
LOGGER.trace(sessionLabel, logText);
return new PasswordData(password.toString());
}
Aggregations