Search in sources :

Example 1 with SeedlistManager

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());
}
Also used : SeedlistManager(password.pwm.svc.wordlist.SeedlistManager) HashSet(java.util.HashSet) Set(java.util.Set) Instant(java.time.Instant) ErrorInformation(password.pwm.error.ErrorInformation) PwmPasswordPolicy(password.pwm.config.profile.PwmPasswordPolicy) TimeDuration(password.pwm.util.java.TimeDuration) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map) HashSet(java.util.HashSet)

Aggregations

Instant (java.time.Instant)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Map (java.util.Map)1 Set (java.util.Set)1 PwmPasswordPolicy (password.pwm.config.profile.PwmPasswordPolicy)1 ErrorInformation (password.pwm.error.ErrorInformation)1 SeedlistManager (password.pwm.svc.wordlist.SeedlistManager)1 TimeDuration (password.pwm.util.java.TimeDuration)1