Browse Source

fix and improve random pw generator config

Jason Rivard 8 years ago
parent
commit
7ded7b6cb6

+ 3 - 2
src/main/java/password/pwm/http/servlet/newuser/NewUserUtils.java

@@ -178,8 +178,9 @@ class NewUserUtils {
             NewUserUtils.LOGGER.trace(pwmSession, "will use temporary password process for new user entry: " + newUserDN);
             final PasswordData temporaryPassword;
             {
-                final RandomPasswordGenerator.RandomGeneratorConfig randomGeneratorConfig = new RandomPasswordGenerator.RandomGeneratorConfig();
-                randomGeneratorConfig.setPasswordPolicy(newUserProfile.getNewUserPasswordPolicy(pwmApplication, pwmRequest.getLocale()));
+                final RandomPasswordGenerator.RandomGeneratorConfig randomGeneratorConfig = RandomPasswordGenerator.RandomGeneratorConfig.builder()
+                        .passwordPolicy(newUserProfile.getNewUserPasswordPolicy(pwmApplication, pwmRequest.getLocale()))
+                        .build();
                 temporaryPassword = RandomPasswordGenerator.createRandomPassword(pwmSession.getLabel(), randomGeneratorConfig, pwmApplication);
             }
             final ChaiUser proxiedUser = ChaiFactory.createChaiUser(newUserDN, chaiProvider);

+ 97 - 102
src/main/java/password/pwm/util/RandomPasswordGenerator.java

@@ -23,6 +23,8 @@
 package password.pwm.util;
 
 import com.novell.ldapchai.exception.ImpossiblePasswordPolicyException;
+import lombok.Builder;
+import lombok.Getter;
 import password.pwm.AppProperty;
 import password.pwm.PwmApplication;
 import password.pwm.bean.SessionLabel;
@@ -100,8 +102,9 @@ public class RandomPasswordGenerator {
     )
             throws PwmUnrecoverableException
     {
-        final RandomGeneratorConfig randomGeneratorConfig = new RandomGeneratorConfig();
-        randomGeneratorConfig.setPasswordPolicy(passwordPolicy);
+        final RandomGeneratorConfig randomGeneratorConfig = RandomGeneratorConfig.builder()
+                .passwordPolicy(passwordPolicy)
+                .build();
 
         return createRandomPassword(
                 sessionLabel,
@@ -135,28 +138,34 @@ public class RandomPasswordGenerator {
     {
         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;
         final StringBuilder password = new StringBuilder();
@@ -165,24 +174,24 @@ public class RandomPasswordGenerator {
         final PwmPasswordPolicy randomGenPolicy;
         {
             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);
         }
 
         // initial creation
-        password.append(generateNewPassword(seedMachine, randomGeneratorConfig.getMinimumLength()));
+        password.append(generateNewPassword(seedMachine, effectiveConfig.getMinimumLength()));
 
         // read a rule validator
         final PwmPasswordRuleValidator pwmPasswordRuleValidator = new PwmPasswordRuleValidator(pwmApplication, randomGenPolicy);
@@ -197,7 +206,7 @@ public class RandomPasswordGenerator {
 
             if (tryCount % JITTER_COUNT == 0) {
                 password.delete(0,password.length());
-                password.append(generateNewPassword(seedMachine, randomGeneratorConfig.getMinimumLength()));
+                password.append(generateNewPassword(seedMachine, effectiveConfig.getMinimumLength()));
             }
 
             final List<ErrorInformation> errors = pwmPasswordRuleValidator.internalPwmPolicyValidator(
@@ -208,7 +217,7 @@ public class RandomPasswordGenerator {
             } else if (checkPasswordAgainstDisallowedHttpValues(pwmApplication.getConfig(), password.toString())) {
                 validPassword = false;
                 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;
     }
 
+    @Getter
+    @Builder(toBuilder = true)
     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 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"
+                ));
+            }
         }
     }
 }

+ 10 - 8
src/main/java/password/pwm/ws/server/rest/RestRandomPasswordServer.java

@@ -203,22 +203,23 @@ public class RestRandomPasswordServer extends AbstractRestServer {
     )
             throws ChaiUnavailableException, PwmUnrecoverableException
     {
-        final RandomPasswordGenerator.RandomGeneratorConfig randomConfig = new RandomPasswordGenerator.RandomGeneratorConfig();
+        final RandomPasswordGenerator.RandomGeneratorConfig.RandomGeneratorConfigBuilder randomConfigBuilder
+                = RandomPasswordGenerator.RandomGeneratorConfig.builder();
         if (jsonInput.strength > 0 && jsonInput.strength <= 100) {
-            randomConfig.setMinimumStrength(jsonInput.strength);
+            randomConfigBuilder.minimumStrength(jsonInput.strength);
         }
         if (jsonInput.minLength > 0 && jsonInput.minLength <= 100 * 1024) {
-            randomConfig.setMinimumLength(jsonInput.minLength);
+            randomConfigBuilder.minimumLength(jsonInput.minLength);
         }
         if (jsonInput.maxLength > 0 && jsonInput.maxLength <= 100 * 1024) {
-            randomConfig.setMaximumLength(jsonInput.maxLength);
+            randomConfigBuilder.maximumLength(jsonInput.maxLength);
         }
         if (jsonInput.chars != null) {
             final List<String> charValues = new ArrayList<>();
             for (int i = 0; i < jsonInput.chars.length(); i++) {
                 charValues.add(String.valueOf(jsonInput.chars.charAt(i)));
             }
-            randomConfig.setSeedlistPhrases(charValues);
+            randomConfigBuilder.seedlistPhrases(charValues);
         }
 
         if (!jsonInput.noUser && restRequestBean.getPwmSession().isAuthenticated()) {
@@ -231,22 +232,23 @@ public class RestRandomPasswordServer extends AbstractRestServer {
                         ? restRequestBean.getPwmApplication().getProxiedChaiUser(restRequestBean.getUserIdentity())
                         : restRequestBean.getPwmSession().getSessionManager().getActor(restRequestBean.getPwmApplication(),userIdentity);
 
-                randomConfig.setPasswordPolicy(PasswordUtility.readPasswordPolicyForUser(
+                randomConfigBuilder.passwordPolicy(PasswordUtility.readPasswordPolicyForUser(
                         restRequestBean.getPwmApplication(),
                         restRequestBean.getPwmSession().getLabel(),
                         restRequestBean.getUserIdentity(),
                         theUser,
                         restRequestBean.getPwmSession().getSessionStateBean().getLocale()));
             } else {
-                randomConfig.setPasswordPolicy(restRequestBean.getPwmSession().getUserInfo().getPasswordPolicy());
+                randomConfigBuilder.passwordPolicy(restRequestBean.getPwmSession().getUserInfo().getPasswordPolicy());
             }
         } else {
             final Configuration config  = restRequestBean.getPwmApplication().getConfig();
-            randomConfig.setPasswordPolicy(config.getPasswordPolicy(
+            randomConfigBuilder.passwordPolicy(config.getPasswordPolicy(
                     config.getPasswordProfileIDs().iterator().next(),
                     restRequestBean.getPwmSession().getSessionStateBean().getLocale()));
         }
 
+        final RandomPasswordGenerator.RandomGeneratorConfig randomConfig = randomConfigBuilder.build();
         final PasswordData randomPassword = RandomPasswordGenerator.createRandomPassword(restRequestBean.getPwmSession().getLabel(), randomConfig, restRequestBean.getPwmApplication());
         final JsonOutput outputMap = new JsonOutput();
         outputMap.password = randomPassword.getStringValue();